Merge "Remove accidentally exposed Geofencing classes."
diff --git a/Android.bp b/Android.bp
index 010b2b4..9088315 100644
--- a/Android.bp
+++ b/Android.bp
@@ -13,6 +13,11 @@
// limitations under the License.
subdirs = [
+ "libs/*",
"native/android",
"native/graphics/jni",
]
+
+optional_subdirs = [
+ "core/tests/utiltests/jni",
+]
diff --git a/Android.mk b/Android.mk
index 5d902c2..36a35a1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -45,6 +45,7 @@
core/java/android/app/admin/SecurityLogTags.logtags \
core/java/android/content/EventLogTags.logtags \
core/java/android/speech/tts/EventLogTags.logtags \
+ core/java/android/net/EventLogTags.logtags \
core/java/android/webkit/EventLogTags.logtags \
core/java/com/android/internal/logging/EventLogTags.logtags \
@@ -212,6 +213,7 @@
core/java/android/net/INetworkManagementEventObserver.aidl \
core/java/android/net/INetworkPolicyListener.aidl \
core/java/android/net/INetworkPolicyManager.aidl \
+ core/java/android/net/INetworkRecommendationProvider.aidl \
core/java/android/net/INetworkScoreCache.aidl \
core/java/android/net/INetworkScoreService.aidl \
core/java/android/net/INetworkStatsService.aidl \
@@ -492,6 +494,7 @@
LOCAL_SRC_FILES += \
../../system/netd/server/binder/android/net/INetd.aidl \
+ ../native/cmds/installd/binder/android/os/IInstalld.aidl \
LOCAL_AIDL_INCLUDES += system/update_engine/binder_bindings
@@ -517,7 +520,7 @@
LOCAL_ADDITIONAL_DEPENDENCIES := $(framework_res_R_stamp)
LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart conscrypt okhttp legacy-test bouncycastle ext
+LOCAL_JAVA_LIBRARIES := core-oj core-libart conscrypt okhttp bouncycastle ext
LOCAL_STATIC_JAVA_LIBRARIES := \
framework-protos \
@@ -666,6 +669,9 @@
frameworks/base/core/java/android/view/textservice/SuggestionsInfo.aidl \
frameworks/base/core/java/android/service/carrier/CarrierIdentifier.aidl \
frameworks/base/core/java/android/service/carrier/MessagePdu.aidl \
+ frameworks/base/core/java/android/service/notification/Adjustment.aidl \
+ frameworks/base/core/java/android/service/notification/Condition.aidl \
+ frameworks/base/core/java/android/service/notification/SnoozeCriterion.aidl \
frameworks/base/core/java/android/service/notification/StatusBarNotification.aidl \
frameworks/base/core/java/android/service/chooser/ChooserTarget.aidl \
frameworks/base/core/java/android/speech/tts/Voice.aidl \
@@ -755,6 +761,7 @@
# Search through the base framework dirs for these packages.
# The result will be relative to frameworks/base.
fwbase_dirs_to_document := \
+ legacy-test/src \
test-runner/src \
$(patsubst $(LOCAL_PATH)/%,%, \
$(wildcard \
@@ -767,9 +774,6 @@
# include definition of libcore_to_document
include libcore/Docs.mk
-# include definition of junit_to_document
-include external/junit/Common.mk
-
non_base_dirs := \
../opt/telephony/src/java/android/provider \
../opt/telephony/src/java/android/telephony \
@@ -810,8 +814,7 @@
# Common sources for doc check and api check
common_src_files := \
$(call find-other-html-files, $(html_dirs)) \
- $(addprefix ../../, $(libcore_to_document)) \
- $(addprefix ../../external/junit/, $(junit_to_document))
+ $(addprefix ../../, $(libcore_to_document))
# These are relative to frameworks/base
framework_docs_LOCAL_SRC_FILES := \
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/OutlinePerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/OutlinePerfTest.java
new file mode 100644
index 0000000..3a4fc72
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/OutlinePerfTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.graphics.perftests;
+
+import android.graphics.Outline;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.filters.LargeTest;
+import android.view.RenderNode;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+@LargeTest
+public class OutlinePerfTest {
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ @Test
+ public void testSetEmpty() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+
+ Outline outline = new Outline();
+ while (state.keepRunning()) {
+ outline.setEmpty();
+ }
+ }
+
+ @Test
+ public void testSetRoundRect() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ Outline outline = new Outline();
+ while (state.keepRunning()) {
+ outline.setRoundRect(50, 50, 150, 150, 5);
+ }
+ }
+}
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/PathPerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/PathPerfTest.java
new file mode 100644
index 0000000..7a49b4f
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/PathPerfTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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.graphics.perftests;
+
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.filters.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+@LargeTest
+public class PathPerfTest {
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ @Test
+ public void testReset() {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ Path path = new Path();
+ while (state.keepRunning()) {
+ path.reset();
+ }
+ }
+
+ @Test
+ public void testAddReset() {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ Path path = new Path();
+ while (state.keepRunning()) {
+ path.addRect(0, 0, 100, 100, Path.Direction.CW);
+ path.reset();
+ }
+ }
+
+ @Test
+ public void testRewind() {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ Path path = new Path();
+ while (state.keepRunning()) {
+ path.rewind();
+ }
+ }
+
+ @Test
+ public void testAddRewind() {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ Path path = new Path();
+ while (state.keepRunning()) {
+ path.addRect(0, 0, 100, 100, Path.Direction.CW);
+ path.rewind();
+ }
+ }
+
+ @Test
+ public void testIsEmpty() {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ Path path = new Path();
+ path.addRect(0, 0, 100, 100, Path.Direction.CW);
+ while (state.keepRunning()) {
+ path.isEmpty();
+ }
+ }
+
+ @Test
+ public void testIsConvex() {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ Path path = new Path();
+ path.addRect(0, 0, 100, 100, Path.Direction.CW);
+ while (state.keepRunning()) {
+ path.isConvex();
+ }
+ }
+
+ @Test
+ public void testGetSetFillType() {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ Path path = new Path();
+ path.addRect(0, 0, 100, 100, Path.Direction.CW);
+ while (state.keepRunning()) {
+ path.setFillType(Path.FillType.EVEN_ODD);
+ path.getFillType();
+ }
+ }
+
+ @Test
+ public void testIsRect() {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ Path path = new Path();
+ path.addRect(0, 0, 100, 100, Path.Direction.CW);
+ final RectF outRect = new RectF();
+ while (state.keepRunning()) {
+ path.isRect(outRect);
+ }
+ }
+}
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
index 922a475..dfbabeb 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
@@ -16,14 +16,18 @@
package android.graphics.perftests;
+import android.graphics.Outline;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.support.test.filters.LargeTest;
+import android.view.DisplayListCanvas;
import android.view.RenderNode;
import org.junit.Rule;
import org.junit.Test;
+import java.util.ArrayList;
+
@LargeTest
public class RenderNodePerfTest {
@Rule
@@ -65,4 +69,58 @@
node.isValid();
}
}
+
+ @Test
+ public void testStartEnd() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ RenderNode node = RenderNode.create("LinearLayout", null);
+ while (state.keepRunning()) {
+ DisplayListCanvas canvas = node.start(100, 100);
+ node.end(canvas);
+ }
+ }
+
+ @Test
+ public void testStartEndDeepHierarchy() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ RenderNode[] nodes = new RenderNode[30];
+ DisplayListCanvas[] canvases = new DisplayListCanvas[nodes.length];
+ for (int i = 0; i < nodes.length; i++) {
+ nodes[i] = RenderNode.create("LinearLayout", null);
+ }
+
+ while (state.keepRunning()) {
+ for (int i = 0; i < nodes.length; i++) {
+ canvases[i] = nodes[i].start(100, 100);
+ }
+ for (int i = nodes.length - 1; i >= 0; i--) {
+ nodes[i].end(canvases[i]);
+ }
+ }
+ }
+
+ @Test
+ public void testHasIdentityMatrix() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ RenderNode node = RenderNode.create("LinearLayout", null);
+ while (state.keepRunning()) {
+ node.hasIdentityMatrix();
+ }
+ }
+
+ @Test
+ public void testSetOutline() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ RenderNode node = RenderNode.create("LinearLayout", null);
+ Outline a = new Outline();
+ a.setRoundRect(0, 0, 100, 100, 10);
+ Outline b = new Outline();
+ b.setRect(50, 50, 150, 150);
+ b.setAlpha(0.5f);
+
+ while (state.keepRunning()) {
+ node.setOutline(a);
+ node.setOutline(b);
+ }
+ }
}
diff --git a/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java b/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java
new file mode 100644
index 0000000..c7da48c
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java
@@ -0,0 +1,238 @@
+/*
+ * 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 static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.perftests.utils.StubActivity;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View.MeasureSpec;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(Parameterized.class)
+@LargeTest
+public class ViewShowHidePerfTest {
+
+ @Rule
+ public ActivityTestRule mActivityRule = new ActivityTestRule(StubActivity.class);
+
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ public Context getContext() {
+ return InstrumentationRegistry.getInstrumentation().getTargetContext();
+ }
+
+ static abstract class SubTreeFactory {
+ String mName;
+ SubTreeFactory(String name) { mName = name; }
+
+ abstract View create(Context context, int depth);
+
+ @Override
+ public String toString() {
+ return mName;
+ }
+ }
+
+ private static SubTreeFactory[] sSubTreeFactories = new SubTreeFactory[] {
+ new SubTreeFactory("NestedLinearLayoutTree") {
+ private int mColorToggle = 0;
+
+ private void createNestedLinearLayoutTree(Context context, LinearLayout parent,
+ int remainingDepth) {
+ if (remainingDepth <= 0) {
+ mColorToggle = (mColorToggle + 1) % 4;
+ parent.setBackgroundColor((mColorToggle < 2) ? Color.RED : Color.BLUE);
+ return;
+ }
+
+ boolean vertical = remainingDepth % 2 == 0;
+ parent.setOrientation(vertical ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
+
+ for (int i = 0; i < 2; i++) {
+ LinearLayout child = new LinearLayout(context);
+ // vertical: match parent in x axis, horizontal: y axis.
+ parent.addView(child, new LinearLayout.LayoutParams(
+ (vertical ? ViewGroup.LayoutParams.MATCH_PARENT : 0),
+ (vertical ? 0 : ViewGroup.LayoutParams.MATCH_PARENT),
+ 1.0f));
+
+ createNestedLinearLayoutTree(context, child, remainingDepth - 1);
+ }
+ }
+
+ @Override
+ public View create(Context context, int depth) {
+ LinearLayout root = new LinearLayout(context);
+ createNestedLinearLayoutTree(context, root, depth - 1);
+ return root;
+ }
+ },
+ new SubTreeFactory("ImageViewList") {
+ @Override
+ public View create(Context context, int depth) {
+ LinearLayout root = new LinearLayout(context);
+ root.setOrientation(LinearLayout.HORIZONTAL);
+ int childCount = (int) Math.pow(2, depth);
+ for (int i = 0; i < childCount; i++) {
+ ImageView imageView = new ImageView(context);
+ root.addView(imageView, new LinearLayout.LayoutParams(
+ 0, ViewGroup.LayoutParams.MATCH_PARENT, 1.0f));
+ imageView.setImageDrawable(new ColorDrawable(Color.RED));
+ }
+ return root;
+ }
+ },
+ };
+
+
+ @Parameterized.Parameters(name = "Factory:{0},depth:{1}")
+ public static Iterable<Object[]> params() {
+ List<Object[]> params = new ArrayList<>();
+ for (int depth : new int[] {1, 6, 10}) {
+ for (SubTreeFactory subTreeFactory : sSubTreeFactories) {
+ params.add(new Object[]{ subTreeFactory, depth });
+ }
+ }
+ return params;
+ }
+
+ private final View mChild;
+
+ public ViewShowHidePerfTest(SubTreeFactory subTreeFactory, int depth) {
+ mChild = subTreeFactory.create(getContext(), depth);
+ }
+
+ interface TestCallback {
+ void run(BenchmarkState state, int width, int height, ViewGroup parent, View child);
+ }
+
+ private void testParentWithChild(TestCallback callback) throws Throwable {
+ mActivityRule.runOnUiThread(() -> {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+
+ FrameLayout parent = new FrameLayout(getContext());
+ mActivityRule.getActivity().setContentView(parent);
+
+ final int width = 1000;
+ final int height = 1000;
+ layout(width, height, parent);
+
+ callback.run(state, width, height, parent, mChild);
+ });
+ }
+
+ private void updateAndValidateDisplayList(View view) {
+ boolean hasDisplayList = view.updateDisplayListIfDirty().isValid();
+ assertTrue(hasDisplayList);
+ }
+
+ private void layout(int width, int height, View view) {
+ view.measure(
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+ view.layout(0, 0, height, width);
+ }
+
+ @Test
+ public void testRemove() throws Throwable {
+ testParentWithChild((state, width, height, parent, child) -> {
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ updateAndValidateDisplayList(parent); // Note, done to be safe, likely not needed
+ parent.addView(child);
+ layout(width, height, child);
+ updateAndValidateDisplayList(parent);
+ state.resumeTiming();
+
+ parent.removeAllViews();
+ }
+ });
+ }
+
+ @Test
+ public void testAdd() throws Throwable {
+ testParentWithChild((state, width, height, parent, child) -> {
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ layout(width, height, child); // Note, done to be safe, likely not needed
+ updateAndValidateDisplayList(parent); // Note, done to be safe, likely not needed
+ parent.removeAllViews();
+ updateAndValidateDisplayList(parent);
+ state.resumeTiming();
+
+ parent.addView(child);
+ }
+ });
+ }
+
+
+ private void testVisibility(int fromVisibility, int toVisibility) throws Throwable {
+ testParentWithChild((state, width, height, parent, child) -> {
+ parent.addView(child);
+
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ layout(width, height, parent);
+ updateAndValidateDisplayList(parent);
+ child.setVisibility(fromVisibility);
+ layout(width, height, parent);
+ updateAndValidateDisplayList(parent);
+ state.resumeTiming();
+
+ child.setVisibility(toVisibility);
+ }
+ });
+ }
+
+ @Test
+ public void testInvisibleToVisible() throws Throwable {
+ testVisibility(View.INVISIBLE, View.VISIBLE);
+ }
+
+ @Test
+ public void testVisibleToInvisible() throws Throwable {
+ testVisibility(View.VISIBLE, View.INVISIBLE);
+ }
+ @Test
+ public void testGoneToVisible() throws Throwable {
+ testVisibility(View.GONE, View.VISIBLE);
+ }
+
+ @Test
+ public void testVisibleToGone() throws Throwable {
+ testVisibility(View.VISIBLE, View.GONE);
+ }
+}
diff --git a/api/current.txt b/api/current.txt
index 304ccf8..67bc116 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -750,6 +750,8 @@
field public static final int keyWidth = 16843325; // 0x101023d
field public static final int keyboardLayout = 16843691; // 0x10103ab
field public static final int keyboardMode = 16843341; // 0x101024d
+ field public static final int keyboardNavigationCluster = 16844096; // 0x1010540
+ field public static final int keyboardNavigationSection = 16844097; // 0x1010541
field public static final int keycode = 16842949; // 0x10100c5
field public static final int killAfterRestore = 16843420; // 0x101029c
field public static final int label = 16842753; // 0x1010001
@@ -893,11 +895,13 @@
field public static final int negativeButtonText = 16843254; // 0x10101f6
field public static final int nestedScrollingEnabled = 16843830; // 0x1010436
field public static final int networkSecurityConfig = 16844071; // 0x1010527
+ field public static final int nextClusterForward = 16844098; // 0x1010542
field public static final int nextFocusDown = 16842980; // 0x10100e4
field public static final int nextFocusForward = 16843580; // 0x101033c
field public static final int nextFocusLeft = 16842977; // 0x10100e1
field public static final int nextFocusRight = 16842978; // 0x10100e2
field public static final int nextFocusUp = 16842979; // 0x10100e3
+ field public static final int nextSectionForward = 16844099; // 0x1010543
field public static final int noHistory = 16843309; // 0x101022d
field public static final int normalScreens = 16843397; // 0x1010285
field public static final int notificationTimeout = 16843651; // 0x1010383
@@ -1425,6 +1429,7 @@
field public static final int viewportWidth = 16843778; // 0x1010402
field public static final int visibility = 16842972; // 0x10100dc
field public static final int visible = 16843156; // 0x1010194
+ field public static final int visibleToEphemeral = 16844095; // 0x101053f
field public static final int vmSafeMode = 16843448; // 0x10102b8
field public static final int voiceIcon = 16843908; // 0x1010484
field public static final int voiceLanguage = 16843349; // 0x1010255
@@ -2804,9 +2809,14 @@
public static class GestureDescription.StrokeDescription {
ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long);
+ ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long, int, boolean);
+ method public int getContinuedStrokeId();
method public long getDuration();
+ method public int getId();
method public android.graphics.Path getPath();
method public long getStartTime();
+ method public boolean isContinued();
+ field public static final int INVALID_STROKE_ID = -1; // 0xffffffff
}
}
@@ -3474,6 +3484,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public void enterPictureInPictureMode(float);
+ method public void enterPictureInPictureModeOnMoveToBackground(boolean);
method public android.view.View findViewById(int);
method public void finish();
method public void finishActivity(int);
@@ -5941,6 +5952,13 @@
package android.app.admin {
+ public final class ConnectEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
+ method public java.lang.String getIpAddress();
+ method public int getPort();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.ConnectEvent> CREATOR;
+ }
+
public final class DeviceAdminInfo implements android.os.Parcelable {
ctor public DeviceAdminInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
@@ -5981,6 +5999,7 @@
method public void onEnabled(android.content.Context, android.content.Intent);
method public void onLockTaskModeEntering(android.content.Context, android.content.Intent, java.lang.String);
method public void onLockTaskModeExiting(android.content.Context, android.content.Intent);
+ method public void onNetworkLogsAvailable(android.content.Context, android.content.Intent, long, int);
method public void onPasswordChanged(android.content.Context, android.content.Intent);
method public void onPasswordExpiring(android.content.Context, android.content.Intent);
method public void onPasswordFailed(android.content.Context, android.content.Intent);
@@ -6085,6 +6104,7 @@
method public boolean isLockTaskPermitted(java.lang.String);
method public boolean isManagedProfile(android.content.ComponentName);
method public boolean isMasterVolumeMuted(android.content.ComponentName);
+ method public boolean isNetworkLoggingEnabled(android.content.ComponentName);
method public boolean isPackageSuspended(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
method public boolean isProfileOwnerApp(java.lang.String);
method public boolean isProvisioningAllowed(java.lang.String);
@@ -6098,6 +6118,7 @@
method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
method public boolean requestBugreport(android.content.ComponentName);
method public boolean resetPassword(java.lang.String, int);
+ method public java.util.List<android.app.admin.NetworkEvent> retrieveNetworkLogs(android.content.ComponentName, long);
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
@@ -6121,6 +6142,7 @@
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
+ method public void setNetworkLoggingEnabled(android.content.ComponentName, boolean);
method public void setOrganizationColor(android.content.ComponentName, int);
method public void setOrganizationName(android.content.ComponentName, java.lang.CharSequence);
method public java.lang.String[] setPackagesSuspended(android.content.ComponentName, java.lang.String[], boolean);
@@ -6185,6 +6207,7 @@
field public static final deprecated java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM";
field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS";
+ field public static final java.lang.String EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION = "android.app.extra.PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION";
field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
@@ -6234,6 +6257,22 @@
field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
}
+ public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
+ method public java.lang.String getHostname();
+ method public java.lang.String[] getIpAddresses();
+ method public int getIpAddressesCount();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.DnsEvent> CREATOR;
+ }
+
+ public abstract class NetworkEvent implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.lang.String getPackageName();
+ method public long getTimestamp();
+ method public abstract void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.NetworkEvent> CREATOR;
+ }
+
public class SecurityLog {
ctor public SecurityLog();
field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
@@ -7944,6 +7983,7 @@
method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public abstract android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ method public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
method public boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
method protected final void setPathPermissions(android.content.pm.PathPermission[]);
method protected final void setReadPermission(java.lang.String);
@@ -7976,6 +8016,7 @@
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String) throws android.os.RemoteException;
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal) throws android.os.RemoteException;
+ method public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal) throws android.os.RemoteException;
method public deprecated boolean release();
method public final android.net.Uri uncanonicalize(android.net.Uri) throws android.os.RemoteException;
method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
@@ -8078,6 +8119,7 @@
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ method public final android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
method public final boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
method public final void registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver);
method public void releasePersistableUriPermission(android.net.Uri, int);
@@ -8100,6 +8142,9 @@
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
+ field public static final java.lang.String QUERY_ARG_SELECTION = "android:query-selection";
+ field public static final java.lang.String QUERY_ARG_SELECTION_ARGS = "android:query-selection-args";
+ field public static final java.lang.String QUERY_ARG_SORT_ORDER = "android:query-sort-order";
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
field public static final java.lang.String SCHEME_CONTENT = "content";
field public static final java.lang.String SCHEME_FILE = "file";
@@ -8344,6 +8389,7 @@
field public static final java.lang.String TELECOM_SERVICE = "telecom";
field public static final java.lang.String TELEPHONY_SERVICE = "phone";
field public static final java.lang.String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
+ field public static final java.lang.String TEXT_CLASSIFICATION_SERVICE = "textclassification";
field public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
field public static final java.lang.String TV_INPUT_SERVICE = "tv_input";
field public static final java.lang.String UI_MODE_SERVICE = "uimode";
@@ -8816,6 +8862,7 @@
field public static final java.lang.String CATEGORY_SELECTED_ALTERNATIVE = "android.intent.category.SELECTED_ALTERNATIVE";
field public static final java.lang.String CATEGORY_TAB = "android.intent.category.TAB";
field public static final java.lang.String CATEGORY_TEST = "android.intent.category.TEST";
+ field public static final java.lang.String CATEGORY_TYPED_OPENABLE = "android.intent.category.TYPED_OPENABLE";
field public static final java.lang.String CATEGORY_UNIT_TEST = "android.intent.category.UNIT_TEST";
field public static final java.lang.String CATEGORY_VOICE = "android.intent.category.VOICE";
field public static final android.os.Parcelable.Creator<android.content.Intent> CREATOR;
@@ -11744,6 +11791,7 @@
enum_constant public static final android.graphics.Bitmap.Config ALPHA_8;
enum_constant public static final deprecated android.graphics.Bitmap.Config ARGB_4444;
enum_constant public static final android.graphics.Bitmap.Config ARGB_8888;
+ enum_constant public static final android.graphics.Bitmap.Config HARDWARE;
enum_constant public static final android.graphics.Bitmap.Config RGB_565;
}
@@ -12204,12 +12252,6 @@
enum_constant public static final android.graphics.Interpolator.Result NORMAL;
}
- public deprecated class LayerRasterizer extends android.graphics.Rasterizer {
- ctor public LayerRasterizer();
- method public void addLayer(android.graphics.Paint, float, float);
- method public void addLayer(android.graphics.Paint);
- }
-
public class LightingColorFilter extends android.graphics.ColorFilter {
ctor public LightingColorFilter(int, int);
}
@@ -12371,7 +12413,6 @@
method public int getOffsetForAdvance(char[], int, int, int, int, boolean, float);
method public int getOffsetForAdvance(java.lang.CharSequence, int, int, int, int, boolean, float);
method public android.graphics.PathEffect getPathEffect();
- method public deprecated android.graphics.Rasterizer getRasterizer();
method public float getRunAdvance(char[], int, int, int, int, boolean, int);
method public float getRunAdvance(java.lang.CharSequence, int, int, int, int, boolean, int);
method public android.graphics.Shader getShader();
@@ -12428,7 +12469,6 @@
method public void setLinearText(boolean);
method public android.graphics.MaskFilter setMaskFilter(android.graphics.MaskFilter);
method public android.graphics.PathEffect setPathEffect(android.graphics.PathEffect);
- method public deprecated android.graphics.Rasterizer setRasterizer(android.graphics.Rasterizer);
method public android.graphics.Shader setShader(android.graphics.Shader);
method public void setShadowLayer(float, float, float, int);
method public void setStrikeThruText(boolean);
@@ -12735,10 +12775,6 @@
ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
}
- public deprecated class Rasterizer {
- ctor public Rasterizer();
- }
-
public final class Rect implements android.os.Parcelable {
ctor public Rect();
ctor public Rect(int, int, int, int);
@@ -20199,8 +20235,8 @@
}
public class AudioTrack implements android.media.AudioRouting {
- ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
- ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+ ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+ ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
@@ -21489,7 +21525,7 @@
method public void selectTrack(int) throws java.lang.IllegalStateException;
method public void setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
- method public void setAudioStreamType(int);
+ method public deprecated void setAudioStreamType(int);
method public void setAuxEffectSendLevel(float);
method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
@@ -29678,9 +29714,11 @@
method public deprecated void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
method public static boolean supportsMultipleUsers();
field public static final java.lang.String ALLOW_PARENT_PROFILE_APP_LINKING = "allow_parent_profile_app_linking";
+ field public static final java.lang.String DISALLOW_ADD_MANAGED_PROFILE = "no_add_managed_profile";
field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user";
field public static final java.lang.String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps";
+ field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
@@ -29701,6 +29739,7 @@
field public static final java.lang.String DISALLOW_NETWORK_RESET = "no_network_reset";
field public static final java.lang.String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
field public static final java.lang.String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
+ field public static final java.lang.String DISALLOW_REMOVE_MANAGED_PROFILE = "no_remove_managed_profile";
field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
field public static final java.lang.String DISALLOW_SAFE_BOOT = "no_safe_boot";
field public static final java.lang.String DISALLOW_SET_USER_ICON = "no_set_user_icon";
@@ -34833,7 +34872,8 @@
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
- method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.SaveCallback);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
}
@@ -34851,6 +34891,11 @@
method public android.service.autofill.FillCallback.FillData.Builder setTextField(int, java.lang.String);
}
+ public final class SaveCallback {
+ method public void onFailure(java.lang.CharSequence);
+ method public void onSuccess(int[]);
+ }
+
}
package android.service.carrier {
@@ -35056,18 +35101,19 @@
package android.service.notification {
public final class Adjustment implements android.os.Parcelable {
- ctor public Adjustment(java.lang.String, java.lang.String, int, android.os.Bundle, java.lang.CharSequence, android.net.Uri, int);
+ ctor public Adjustment(java.lang.String, java.lang.String, android.os.Bundle, java.lang.CharSequence, int);
ctor protected Adjustment(android.os.Parcel);
method public int describeContents();
method public java.lang.CharSequence getExplanation();
- method public int getImportance();
method public java.lang.String getKey();
method public java.lang.String getPackage();
- method public android.net.Uri getReference();
method public android.os.Bundle getSignals();
method public int getUser();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
+ field public static final java.lang.String KEY_CHANNEL_ID = "key_channel_id";
+ field public static final java.lang.String KEY_PEOPLE = "key_people";
+ field public static final java.lang.String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
}
public final class Condition implements android.os.Parcelable {
@@ -35120,8 +35166,12 @@
ctor public NotificationAssistantService();
method public final void adjustNotification(android.service.notification.Adjustment);
method public final void adjustNotifications(java.util.List<android.service.notification.Adjustment>);
+ method public void createNotificationChannel(java.lang.String, android.app.NotificationChannel);
+ method public void deleteNotificationChannel(java.lang.String, java.lang.String);
+ method public java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
method public final android.os.IBinder onBind(android.content.Intent);
method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+ method public void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
}
@@ -35189,11 +35239,14 @@
public static class NotificationListenerService.Ranking {
ctor public NotificationListenerService.Ranking();
+ method public java.util.List<java.lang.String> getAdditionalPeople();
+ method public android.app.NotificationChannel getChannel();
method public int getImportance();
method public java.lang.CharSequence getImportanceExplanation();
method public java.lang.String getKey();
method public java.lang.String getOverrideGroupKey();
method public int getRank();
+ method public java.util.List<android.service.notification.SnoozeCriterion> getSnoozeCriteria();
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
method public boolean matchesInterruptionFilter();
@@ -35207,6 +35260,17 @@
field public static final android.os.Parcelable.Creator<android.service.notification.NotificationListenerService.RankingMap> CREATOR;
}
+ public final class SnoozeCriterion implements android.os.Parcelable {
+ ctor public SnoozeCriterion(java.lang.String, java.lang.CharSequence, java.lang.CharSequence);
+ ctor protected SnoozeCriterion(android.os.Parcel);
+ method public int describeContents();
+ method public java.lang.CharSequence getConfirmation();
+ method public java.lang.CharSequence getExplanation();
+ method public java.lang.String getId();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.notification.SnoozeCriterion> CREATOR;
+ }
+
public class StatusBarNotification implements android.os.Parcelable {
ctor public deprecated StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
ctor public StatusBarNotification(android.os.Parcel);
@@ -37259,7 +37323,10 @@
field public static final java.lang.String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool";
field public static final java.lang.String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
field public static final java.lang.String KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
+ field public static final java.lang.String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int";
field public static final java.lang.String KEY_IMS_DTMF_TONE_DELAY_INT = "ims_dtmf_tone_delay_int";
+ field public static final java.lang.String KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL = "is_ims_conference_size_enforced_bool";
+ field public static final java.lang.String KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL = "mdn_is_additional_voicemail_number_bool";
field public static final java.lang.String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
field public static final java.lang.String KEY_MMS_ALIAS_MAX_CHARS_INT = "aliasMaxChars";
field public static final java.lang.String KEY_MMS_ALIAS_MIN_CHARS_INT = "aliasMinChars";
@@ -37642,6 +37709,7 @@
}
public final class SmsManager {
+ method public java.lang.String createAppSpecificSmsToken(android.app.PendingIntent);
method public java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
method public void downloadMultimediaMessage(android.content.Context, java.lang.String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
method public android.os.Bundle getCarrierConfigValues();
@@ -39182,6 +39250,12 @@
method public java.util.Map<java.lang.String, java.lang.Float> getTypeConfidence();
}
+ public final class TextClassificationManager implements android.text.TextAssistant {
+ method public void addLinks(android.text.Spannable, int);
+ method public java.util.List<android.text.TextLanguage> detectLanguages(java.lang.CharSequence);
+ method public android.text.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+ }
+
public abstract interface TextDirectionHeuristic {
method public abstract boolean isRtl(char[], int, int);
method public abstract boolean isRtl(java.lang.CharSequence, int, int);
@@ -39197,6 +39271,13 @@
field public static final android.text.TextDirectionHeuristic RTL;
}
+ public final class TextLanguage {
+ ctor public TextLanguage(int, int, java.util.Map<java.lang.String, java.lang.Float>);
+ method public int getEndIndex();
+ method public java.util.Map<java.lang.String, java.lang.Float> getLanguageConfidence();
+ method public int getStartIndex();
+ }
+
public class TextPaint extends android.graphics.Paint {
ctor public TextPaint();
ctor public TextPaint(int);
@@ -39891,12 +39972,6 @@
method public void writeToParcel(android.os.Parcel, int);
}
- public class RasterizerSpan extends android.text.style.CharacterStyle implements android.text.style.UpdateAppearance {
- ctor public RasterizerSpan(android.graphics.Rasterizer);
- method public android.graphics.Rasterizer getRasterizer();
- method public void updateDrawState(android.text.TextPaint);
- }
-
public class RelativeSizeSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
ctor public RelativeSizeSpan(float);
ctor public RelativeSizeSpan(android.os.Parcel);
@@ -42892,7 +42967,8 @@
method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
method public boolean dispatchNestedScroll(int, int, int, int, int[]);
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
- method public void dispatchProvideStructure(android.view.ViewStructure);
+ method public deprecated void dispatchProvideStructure(android.view.ViewStructure);
+ method public void dispatchProvideStructure(android.view.ViewStructure, int);
method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
method protected void dispatchSetActivated(boolean);
@@ -42989,11 +43065,13 @@
method public final int getMeasuredWidthAndState();
method public int getMinimumHeight();
method public int getMinimumWidth();
+ method public int getNextClusterForwardId();
method public int getNextFocusDownId();
method public int getNextFocusForwardId();
method public int getNextFocusLeftId();
method public int getNextFocusRightId();
method public int getNextFocusUpId();
+ method public int getNextSectionForwardId();
method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
method public android.view.ViewOutlineProvider getOutlineProvider();
method public int getOverScrollMode();
@@ -43096,6 +43174,8 @@
method public boolean isInEditMode();
method public boolean isInLayout();
method public boolean isInTouchMode();
+ method public final boolean isKeyboardNavigationCluster();
+ method public final boolean isKeyboardNavigationSection();
method public boolean isLaidOut();
method public boolean isLayoutDirectionResolved();
method public boolean isLayoutRequested();
@@ -43158,8 +43238,10 @@
method protected void onMeasure(int, int);
method protected void onOverScrolled(int, int, boolean, boolean);
method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
- method public void onProvideStructure(android.view.ViewStructure);
- method public void onProvideVirtualStructure(android.view.ViewStructure);
+ method public deprecated void onProvideStructure(android.view.ViewStructure);
+ method public void onProvideStructure(android.view.ViewStructure, int);
+ method public deprecated void onProvideVirtualStructure(android.view.ViewStructure);
+ method public void onProvideVirtualStructure(android.view.ViewStructure, int);
method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
method protected void onRestoreInstanceState(android.os.Parcelable);
method public void onRtlPropertiesChanged(int);
@@ -43262,6 +43344,8 @@
method public void setId(int);
method public void setImportantForAccessibility(int);
method public void setKeepScreenOn(boolean);
+ method public void setKeyboardNavigationCluster(boolean);
+ method public void setKeyboardNavigationSection(boolean);
method public void setLabelFor(int);
method public void setLayerPaint(android.graphics.Paint);
method public void setLayerType(int, android.graphics.Paint);
@@ -43273,11 +43357,13 @@
method public void setMinimumHeight(int);
method public void setMinimumWidth(int);
method public void setNestedScrollingEnabled(boolean);
+ method public void setNextClusterForwardId(int);
method public void setNextFocusDownId(int);
method public void setNextFocusForwardId(int);
method public void setNextFocusLeftId(int);
method public void setNextFocusRightId(int);
method public void setNextFocusUpId(int);
+ method public void setNextSectionForwardId(int);
method public void setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener);
method public void setOnClickListener(android.view.View.OnClickListener);
method public void setOnContextClickListener(android.view.View.OnContextClickListener);
@@ -43361,6 +43447,8 @@
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+ field public static final int ASSIST_FLAG_NON_SANITIZED_TEXT = 2; // 0x2
+ field public static final int ASSIST_FLAG_SANITIZED_TEXT = 1; // 0x1
field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
@@ -43467,6 +43555,7 @@
field public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024; // 0x400
field public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512; // 0x200
field public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256; // 0x100
+ field public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 16; // 0x10
field public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 8192; // 0x2000
field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
@@ -44384,7 +44473,7 @@
field public static final int FLAG_ALT_FOCUSABLE_IM = 131072; // 0x20000
field public static final deprecated int FLAG_BLUR_BEHIND = 4; // 0x4
field public static final int FLAG_DIM_BEHIND = 2; // 0x2
- field public static final int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
+ field public static final deprecated int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
field public static final deprecated int FLAG_DITHER = 4096; // 0x1000
field public static final int FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = -2147483648; // 0x80000000
field public static final int FLAG_FORCE_NOT_FULLSCREEN = 2048; // 0x800
@@ -59820,6 +59909,10 @@
ctor public Locale(java.lang.String, java.lang.String);
ctor public Locale(java.lang.String);
method public java.lang.Object clone();
+ method public static java.util.List<java.util.Locale> filter(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.util.Locale>, java.util.Locale.FilteringMode);
+ method public static java.util.List<java.util.Locale> filter(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.util.Locale>);
+ method public static java.util.List<java.lang.String> filterTags(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.lang.String>, java.util.Locale.FilteringMode);
+ method public static java.util.List<java.lang.String> filterTags(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.lang.String>);
method public static java.util.Locale forLanguageTag(java.lang.String);
method public static java.util.Locale[] getAvailableLocales();
method public java.lang.String getCountry();
@@ -59848,6 +59941,8 @@
method public java.lang.String getUnicodeLocaleType(java.lang.String);
method public java.lang.String getVariant();
method public boolean hasExtensions();
+ method public static java.util.Locale lookup(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.util.Locale>);
+ method public static java.lang.String lookupTag(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.lang.String>);
method public static synchronized void setDefault(java.util.Locale);
method public static synchronized void setDefault(java.util.Locale.Category, java.util.Locale);
method public java.util.Locale stripExtensions();
@@ -59903,6 +59998,28 @@
enum_constant public static final java.util.Locale.Category FORMAT;
}
+ public static final class Locale.FilteringMode extends java.lang.Enum {
+ method public static java.util.Locale.FilteringMode valueOf(java.lang.String);
+ method public static final java.util.Locale.FilteringMode[] values();
+ enum_constant public static final java.util.Locale.FilteringMode AUTOSELECT_FILTERING;
+ enum_constant public static final java.util.Locale.FilteringMode EXTENDED_FILTERING;
+ enum_constant public static final java.util.Locale.FilteringMode IGNORE_EXTENDED_RANGES;
+ enum_constant public static final java.util.Locale.FilteringMode MAP_EXTENDED_RANGES;
+ enum_constant public static final java.util.Locale.FilteringMode REJECT_EXTENDED_RANGES;
+ }
+
+ public static final class Locale.LanguageRange {
+ ctor public Locale.LanguageRange(java.lang.String);
+ ctor public Locale.LanguageRange(java.lang.String, double);
+ method public java.lang.String getRange();
+ method public double getWeight();
+ method public static java.util.List<java.util.Locale.LanguageRange> mapEquivalents(java.util.List<java.util.Locale.LanguageRange>, java.util.Map<java.lang.String, java.util.List<java.lang.String>>);
+ method public static java.util.List<java.util.Locale.LanguageRange> parse(java.lang.String);
+ method public static java.util.List<java.util.Locale.LanguageRange> parse(java.lang.String, java.util.Map<java.lang.String, java.util.List<java.lang.String>>);
+ field public static final double MAX_WEIGHT = 1.0;
+ field public static final double MIN_WEIGHT = 0.0;
+ }
+
public class LongSummaryStatistics implements java.util.function.IntConsumer java.util.function.LongConsumer {
ctor public LongSummaryStatistics();
method public void accept(int);
@@ -62569,13 +62686,13 @@
ctor public Attributes.Name(java.lang.String);
field public static final java.util.jar.Attributes.Name CLASS_PATH;
field public static final java.util.jar.Attributes.Name CONTENT_TYPE;
- field public static final java.util.jar.Attributes.Name EXTENSION_INSTALLATION;
+ field public static final deprecated java.util.jar.Attributes.Name EXTENSION_INSTALLATION;
field public static final java.util.jar.Attributes.Name EXTENSION_LIST;
field public static final java.util.jar.Attributes.Name EXTENSION_NAME;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_TITLE;
- field public static final java.util.jar.Attributes.Name IMPLEMENTATION_URL;
+ field public static final deprecated java.util.jar.Attributes.Name IMPLEMENTATION_URL;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR;
- field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR_ID;
+ field public static final deprecated java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR_ID;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VERSION;
field public static final java.util.jar.Attributes.Name MAIN_CLASS;
field public static final java.util.jar.Attributes.Name MANIFEST_VERSION;
@@ -62642,11 +62759,11 @@
}
public static abstract interface Pack200.Packer {
- method public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void addPropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract void pack(java.util.jar.JarFile, java.io.OutputStream) throws java.io.IOException;
method public abstract void pack(java.util.jar.JarInputStream, java.io.OutputStream) throws java.io.IOException;
method public abstract java.util.SortedMap<java.lang.String, java.lang.String> properties();
- method public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void removePropertyChangeListener(java.beans.PropertyChangeListener);
field public static final java.lang.String CLASS_ATTRIBUTE_PFX = "pack.class.attribute.";
field public static final java.lang.String CODE_ATTRIBUTE_PFX = "pack.code.attribute.";
field public static final java.lang.String DEFLATE_HINT = "pack.deflate.hint";
@@ -62669,9 +62786,9 @@
}
public static abstract interface Pack200.Unpacker {
- method public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void addPropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract java.util.SortedMap<java.lang.String, java.lang.String> properties();
- method public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void removePropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract void unpack(java.io.InputStream, java.util.jar.JarOutputStream) throws java.io.IOException;
method public abstract void unpack(java.io.File, java.util.jar.JarOutputStream) throws java.io.IOException;
field public static final java.lang.String DEFLATE_HINT = "unpack.deflate.hint";
diff --git a/api/removed.txt b/api/removed.txt
index 683a695..10e6eb5 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -78,10 +78,25 @@
enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET;
}
+ public deprecated class LayerRasterizer extends android.graphics.Rasterizer {
+ ctor public LayerRasterizer();
+ method public void addLayer(android.graphics.Paint, float, float);
+ method public void addLayer(android.graphics.Paint);
+ }
+
+ public class Paint {
+ method public deprecated android.graphics.Rasterizer getRasterizer();
+ method public deprecated android.graphics.Rasterizer setRasterizer(android.graphics.Rasterizer);
+ }
+
public deprecated class PixelXorXfermode extends android.graphics.Xfermode {
ctor public PixelXorXfermode(int);
}
+ public class Rasterizer {
+ ctor public Rasterizer();
+ }
+
}
package android.location {
@@ -393,6 +408,15 @@
}
+package android.text.style {
+
+ public class RasterizerSpan extends android.text.style.CharacterStyle implements android.text.style.UpdateAppearance {
+ ctor public RasterizerSpan(android.graphics.Rasterizer);
+ method public android.graphics.Rasterizer getRasterizer();
+ }
+
+}
+
package android.util {
public deprecated class FloatMath {
diff --git a/api/system-current.txt b/api/system-current.txt
index e328fb2..ab57024 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -857,6 +857,8 @@
field public static final int keyWidth = 16843325; // 0x101023d
field public static final int keyboardLayout = 16843691; // 0x10103ab
field public static final int keyboardMode = 16843341; // 0x101024d
+ field public static final int keyboardNavigationCluster = 16844096; // 0x1010540
+ field public static final int keyboardNavigationSection = 16844097; // 0x1010541
field public static final int keycode = 16842949; // 0x10100c5
field public static final int killAfterRestore = 16843420; // 0x101029c
field public static final int label = 16842753; // 0x1010001
@@ -1000,11 +1002,13 @@
field public static final int negativeButtonText = 16843254; // 0x10101f6
field public static final int nestedScrollingEnabled = 16843830; // 0x1010436
field public static final int networkSecurityConfig = 16844071; // 0x1010527
+ field public static final int nextClusterForward = 16844098; // 0x1010542
field public static final int nextFocusDown = 16842980; // 0x10100e4
field public static final int nextFocusForward = 16843580; // 0x101033c
field public static final int nextFocusLeft = 16842977; // 0x10100e1
field public static final int nextFocusRight = 16842978; // 0x10100e2
field public static final int nextFocusUp = 16842979; // 0x10100e3
+ field public static final int nextSectionForward = 16844099; // 0x1010543
field public static final int noHistory = 16843309; // 0x101022d
field public static final int normalScreens = 16843397; // 0x1010285
field public static final int notificationTimeout = 16843651; // 0x1010383
@@ -1536,6 +1540,7 @@
field public static final int viewportWidth = 16843778; // 0x1010402
field public static final int visibility = 16842972; // 0x10100dc
field public static final int visible = 16843156; // 0x1010194
+ field public static final int visibleToEphemeral = 16844095; // 0x101053f
field public static final int vmSafeMode = 16843448; // 0x10102b8
field public static final int voiceIcon = 16843908; // 0x1010484
field public static final int voiceLanguage = 16843349; // 0x1010255
@@ -2918,9 +2923,14 @@
public static class GestureDescription.StrokeDescription {
ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long);
+ ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long, int, boolean);
+ method public int getContinuedStrokeId();
method public long getDuration();
+ method public int getId();
method public android.graphics.Path getPath();
method public long getStartTime();
+ method public boolean isContinued();
+ field public static final int INVALID_STROKE_ID = -1; // 0xffffffff
}
}
@@ -3591,6 +3601,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public void enterPictureInPictureMode(float);
+ method public void enterPictureInPictureModeOnMoveToBackground(boolean);
method public android.view.View findViewById(int);
method public void finish();
method public void finishActivity(int);
@@ -6113,6 +6124,13 @@
package android.app.admin {
+ public final class ConnectEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
+ method public java.lang.String getIpAddress();
+ method public int getPort();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.ConnectEvent> CREATOR;
+ }
+
public final class DeviceAdminInfo implements android.os.Parcelable {
ctor public DeviceAdminInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
@@ -6153,6 +6171,7 @@
method public void onEnabled(android.content.Context, android.content.Intent);
method public void onLockTaskModeEntering(android.content.Context, android.content.Intent, java.lang.String);
method public void onLockTaskModeExiting(android.content.Context, android.content.Intent);
+ method public void onNetworkLogsAvailable(android.content.Context, android.content.Intent, long, int);
method public void onPasswordChanged(android.content.Context, android.content.Intent);
method public void onPasswordExpiring(android.content.Context, android.content.Intent);
method public void onPasswordFailed(android.content.Context, android.content.Intent);
@@ -6265,9 +6284,12 @@
method public boolean isCallerApplicationRestrictionsManagingPackage();
method public boolean isDeviceManaged();
method public boolean isDeviceOwnerApp(java.lang.String);
+ method public boolean isDeviceProvisioned();
+ method public boolean isDeviceProvisioningConfigApplied();
method public boolean isLockTaskPermitted(java.lang.String);
method public boolean isManagedProfile(android.content.ComponentName);
method public boolean isMasterVolumeMuted(android.content.ComponentName);
+ method public boolean isNetworkLoggingEnabled(android.content.ComponentName);
method public boolean isPackageSuspended(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
method public boolean isProfileOwnerApp(java.lang.String);
method public boolean isProvisioningAllowed(java.lang.String);
@@ -6282,6 +6304,7 @@
method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
method public boolean requestBugreport(android.content.ComponentName);
method public boolean resetPassword(java.lang.String, int);
+ method public java.util.List<android.app.admin.NetworkEvent> retrieveNetworkLogs(android.content.ComponentName, long);
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
@@ -6298,6 +6321,7 @@
method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean);
method public void setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.CharSequence);
+ method public void setDeviceProvisioningConfigApplied();
method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
@@ -6306,6 +6330,7 @@
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
+ method public void setNetworkLoggingEnabled(android.content.ComponentName, boolean);
method public void setOrganizationColor(android.content.ComponentName, int);
method public void setOrganizationName(android.content.ComponentName, java.lang.CharSequence);
method public java.lang.String[] setPackagesSuspended(android.content.ComponentName, java.lang.String[], boolean);
@@ -6374,6 +6399,7 @@
field public static final deprecated java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM";
field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS";
+ field public static final java.lang.String EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION = "android.app.extra.PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION";
field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
@@ -6428,6 +6454,22 @@
field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
}
+ public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
+ method public java.lang.String getHostname();
+ method public java.lang.String[] getIpAddresses();
+ method public int getIpAddressesCount();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.DnsEvent> CREATOR;
+ }
+
+ public abstract class NetworkEvent implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.lang.String getPackageName();
+ method public long getTimestamp();
+ method public abstract void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.NetworkEvent> CREATOR;
+ }
+
public class SecurityLog {
ctor public SecurityLog();
field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
@@ -8279,6 +8321,7 @@
method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public abstract android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ method public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
method public boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
method protected final void setPathPermissions(android.content.pm.PathPermission[]);
method protected final void setReadPermission(java.lang.String);
@@ -8311,6 +8354,7 @@
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String) throws android.os.RemoteException;
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal) throws android.os.RemoteException;
+ method public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal) throws android.os.RemoteException;
method public deprecated boolean release();
method public final android.net.Uri uncanonicalize(android.net.Uri) throws android.os.RemoteException;
method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
@@ -8413,6 +8457,7 @@
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ method public final android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
method public final boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
method public final void registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver);
method public void releasePersistableUriPermission(android.net.Uri, int);
@@ -8435,6 +8480,9 @@
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
+ field public static final java.lang.String QUERY_ARG_SELECTION = "android:query-selection";
+ field public static final java.lang.String QUERY_ARG_SELECTION_ARGS = "android:query-selection-args";
+ field public static final java.lang.String QUERY_ARG_SORT_ORDER = "android:query-sort-order";
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
field public static final java.lang.String SCHEME_CONTENT = "content";
field public static final java.lang.String SCHEME_FILE = "file";
@@ -8690,6 +8738,7 @@
field public static final java.lang.String TELECOM_SERVICE = "telecom";
field public static final java.lang.String TELEPHONY_SERVICE = "phone";
field public static final java.lang.String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
+ field public static final java.lang.String TEXT_CLASSIFICATION_SERVICE = "textclassification";
field public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
field public static final java.lang.String TV_INPUT_SERVICE = "tv_input";
field public static final java.lang.String UI_MODE_SERVICE = "uimode";
@@ -9176,6 +9225,7 @@
field public static final java.lang.String CATEGORY_SELECTED_ALTERNATIVE = "android.intent.category.SELECTED_ALTERNATIVE";
field public static final java.lang.String CATEGORY_TAB = "android.intent.category.TAB";
field public static final java.lang.String CATEGORY_TEST = "android.intent.category.TEST";
+ field public static final java.lang.String CATEGORY_TYPED_OPENABLE = "android.intent.category.TYPED_OPENABLE";
field public static final java.lang.String CATEGORY_UNIT_TEST = "android.intent.category.UNIT_TEST";
field public static final java.lang.String CATEGORY_VOICE = "android.intent.category.VOICE";
field public static final android.os.Parcelable.Creator<android.content.Intent> CREATOR;
@@ -10201,6 +10251,7 @@
method public void setAppPackageName(java.lang.String);
method public void setDontKillApp(boolean);
method public void setGrantedRuntimePermissions(java.lang.String[]);
+ method public void setInstallAsInstantApp(boolean);
method public void setInstallLocation(int);
method public void setOriginatingUid(int);
method public void setOriginatingUri(android.net.Uri);
@@ -10493,6 +10544,7 @@
field public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1; // 0x1
field public static final int MASK_PERMISSION_FLAGS = 255; // 0xff
field public static final int MATCH_ALL = 131072; // 0x20000
+ field public static final int MATCH_ANY_USER = 4194304; // 0x400000
field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000
field public static final int MATCH_DIRECT_BOOT_UNAWARE = 262144; // 0x40000
@@ -12229,6 +12281,7 @@
enum_constant public static final android.graphics.Bitmap.Config ALPHA_8;
enum_constant public static final deprecated android.graphics.Bitmap.Config ARGB_4444;
enum_constant public static final android.graphics.Bitmap.Config ARGB_8888;
+ enum_constant public static final android.graphics.Bitmap.Config HARDWARE;
enum_constant public static final android.graphics.Bitmap.Config RGB_565;
}
@@ -12689,12 +12742,6 @@
enum_constant public static final android.graphics.Interpolator.Result NORMAL;
}
- public deprecated class LayerRasterizer extends android.graphics.Rasterizer {
- ctor public LayerRasterizer();
- method public void addLayer(android.graphics.Paint, float, float);
- method public void addLayer(android.graphics.Paint);
- }
-
public class LightingColorFilter extends android.graphics.ColorFilter {
ctor public LightingColorFilter(int, int);
}
@@ -12856,7 +12903,6 @@
method public int getOffsetForAdvance(char[], int, int, int, int, boolean, float);
method public int getOffsetForAdvance(java.lang.CharSequence, int, int, int, int, boolean, float);
method public android.graphics.PathEffect getPathEffect();
- method public deprecated android.graphics.Rasterizer getRasterizer();
method public float getRunAdvance(char[], int, int, int, int, boolean, int);
method public float getRunAdvance(java.lang.CharSequence, int, int, int, int, boolean, int);
method public android.graphics.Shader getShader();
@@ -12913,7 +12959,6 @@
method public void setLinearText(boolean);
method public android.graphics.MaskFilter setMaskFilter(android.graphics.MaskFilter);
method public android.graphics.PathEffect setPathEffect(android.graphics.PathEffect);
- method public deprecated android.graphics.Rasterizer setRasterizer(android.graphics.Rasterizer);
method public android.graphics.Shader setShader(android.graphics.Shader);
method public void setShadowLayer(float, float, float, int);
method public void setStrikeThruText(boolean);
@@ -13220,10 +13265,6 @@
ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
}
- public deprecated class Rasterizer {
- ctor public Rasterizer();
- }
-
public final class Rect implements android.os.Parcelable {
ctor public Rect();
ctor public Rect(int, int, int, int);
@@ -21708,8 +21749,8 @@
}
public class AudioTrack implements android.media.AudioRouting {
- ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
- ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+ ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+ ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
@@ -22998,7 +23039,7 @@
method public void selectTrack(int) throws java.lang.IllegalStateException;
method public void setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
- method public void setAudioStreamType(int);
+ method public deprecated void setAudioStreamType(int);
method public void setAuxEffectSendLevel(float);
method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
@@ -25892,6 +25933,19 @@
field public final android.net.WifiKey wifiKey;
}
+ public abstract class NetworkRecommendationProvider {
+ ctor public NetworkRecommendationProvider(android.os.Handler);
+ method public final android.os.IBinder getBinder();
+ method public abstract void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback);
+ method public abstract void onRequestScores(android.net.NetworkKey[]);
+ field public static final java.lang.String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT";
+ field public static final java.lang.String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
+ }
+
+ public static final class NetworkRecommendationProvider.ResultCallback {
+ method public void onResult(android.net.RecommendationResult);
+ }
+
public class NetworkRequest implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
@@ -25912,10 +25966,12 @@
method public boolean clearScores() throws java.lang.SecurityException;
method public void disableScoring() throws java.lang.SecurityException;
method public java.lang.String getActiveScorerPackage();
+ method public android.net.RecommendationResult requestRecommendation(android.net.RecommendationRequest) throws java.lang.SecurityException;
method public boolean setActiveScorer(java.lang.String) throws java.lang.SecurityException;
method public boolean updateScores(android.net.ScoredNetwork[]) throws java.lang.SecurityException;
field public static final java.lang.String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
field public static final java.lang.String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE";
+ field public static final java.lang.String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS";
field public static final java.lang.String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED";
field public static final java.lang.String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
field public static final java.lang.String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
@@ -25950,6 +26006,24 @@
field public static final android.os.Parcelable.Creator<android.net.ProxyInfo> CREATOR;
}
+ public final class RecommendationRequest implements android.os.Parcelable {
+ ctor protected RecommendationRequest(android.os.Parcel);
+ method public int describeContents();
+ method public android.net.wifi.WifiConfiguration getCurrentSelectedConfig();
+ method public android.net.NetworkCapabilities getRequiredCapabilities();
+ method public android.net.wifi.ScanResult[] getScanResults();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR;
+ }
+
+ public final class RecommendationResult implements android.os.Parcelable {
+ ctor public RecommendationResult(android.net.wifi.WifiConfiguration);
+ method public int describeContents();
+ method public android.net.wifi.WifiConfiguration getWifiConfiguration();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.RecommendationResult> CREATOR;
+ }
+
public final class RouteInfo implements android.os.Parcelable {
method public int describeContents();
method public android.net.IpPrefix getDestination();
@@ -26003,9 +26077,12 @@
public class ScoredNetwork implements android.os.Parcelable {
ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve);
ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean);
+ ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean, android.os.Bundle);
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
+ field public static final java.lang.String EXTRA_HAS_CAPTIVE_PORTAL = "android.net.extra.HAS_CAPTIVE_PORTAL";
+ field public final android.os.Bundle attributes;
field public final boolean meteredHint;
field public final android.net.NetworkKey networkKey;
field public final android.net.RssiCurve rssiCurve;
@@ -32235,9 +32312,11 @@
method public deprecated void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
method public static boolean supportsMultipleUsers();
field public static final java.lang.String ALLOW_PARENT_PROFILE_APP_LINKING = "allow_parent_profile_app_linking";
+ field public static final java.lang.String DISALLOW_ADD_MANAGED_PROFILE = "no_add_managed_profile";
field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user";
field public static final java.lang.String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps";
+ field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
@@ -32256,8 +32335,10 @@
field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
field public static final java.lang.String DISALLOW_NETWORK_RESET = "no_network_reset";
+ field public static final java.lang.String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
field public static final java.lang.String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
field public static final java.lang.String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
+ field public static final java.lang.String DISALLOW_REMOVE_MANAGED_PROFILE = "no_remove_managed_profile";
field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
field public static final java.lang.String DISALLOW_SAFE_BOOT = "no_safe_boot";
field public static final java.lang.String DISALLOW_SET_USER_ICON = "no_set_user_icon";
@@ -35466,6 +35547,7 @@
field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
+ field public static final java.lang.String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
field public static final java.lang.String ACTION_HARD_KEYBOARD_SETTINGS = "android.settings.HARD_KEYBOARD_SETTINGS";
field public static final java.lang.String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS";
field public static final java.lang.String ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS = "android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS";
@@ -35556,6 +35638,7 @@
field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
field public static final java.lang.String MODE_RINGER = "mode_ringer";
field public static final java.lang.String NETWORK_PREFERENCE = "network_preference";
+ field public static final java.lang.String NETWORK_RECOMMENDATIONS_ENABLED = "network_recommendations_enabled";
field public static final java.lang.String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
field public static final java.lang.String RADIO_BLUETOOTH = "bluetooth";
field public static final java.lang.String RADIO_CELL = "cell";
@@ -35580,6 +35663,7 @@
field public static final int WIFI_SLEEP_POLICY_DEFAULT = 0; // 0x0
field public static final int WIFI_SLEEP_POLICY_NEVER = 2; // 0x2
field public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1; // 0x1
+ field public static final java.lang.String WIFI_WAKEUP_ENABLED = "wifi_wakeup_enabled";
field public static final java.lang.String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
field public static final java.lang.String WINDOW_ANIMATION_SCALE = "window_animation_scale";
}
@@ -37572,7 +37656,8 @@
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
- method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.SaveCallback);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
}
@@ -37590,6 +37675,11 @@
method public android.service.autofill.FillCallback.FillData.Builder setTextField(int, java.lang.String);
}
+ public final class SaveCallback {
+ method public void onFailure(java.lang.CharSequence);
+ method public void onSuccess(int[]);
+ }
+
}
package android.service.carrier {
@@ -37795,18 +37885,19 @@
package android.service.notification {
public final class Adjustment implements android.os.Parcelable {
- ctor public Adjustment(java.lang.String, java.lang.String, int, android.os.Bundle, java.lang.CharSequence, android.net.Uri, int);
+ ctor public Adjustment(java.lang.String, java.lang.String, android.os.Bundle, java.lang.CharSequence, int);
ctor protected Adjustment(android.os.Parcel);
method public int describeContents();
method public java.lang.CharSequence getExplanation();
- method public int getImportance();
method public java.lang.String getKey();
method public java.lang.String getPackage();
- method public android.net.Uri getReference();
method public android.os.Bundle getSignals();
method public int getUser();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
+ field public static final java.lang.String KEY_CHANNEL_ID = "key_channel_id";
+ field public static final java.lang.String KEY_PEOPLE = "key_people";
+ field public static final java.lang.String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
}
public final class Condition implements android.os.Parcelable {
@@ -37859,8 +37950,12 @@
ctor public NotificationAssistantService();
method public final void adjustNotification(android.service.notification.Adjustment);
method public final void adjustNotifications(java.util.List<android.service.notification.Adjustment>);
+ method public void createNotificationChannel(java.lang.String, android.app.NotificationChannel);
+ method public void deleteNotificationChannel(java.lang.String, java.lang.String);
+ method public java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
method public final android.os.IBinder onBind(android.content.Intent);
method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+ method public void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
}
@@ -37935,11 +38030,14 @@
public static class NotificationListenerService.Ranking {
ctor public NotificationListenerService.Ranking();
+ method public java.util.List<java.lang.String> getAdditionalPeople();
+ method public android.app.NotificationChannel getChannel();
method public int getImportance();
method public java.lang.CharSequence getImportanceExplanation();
method public java.lang.String getKey();
method public java.lang.String getOverrideGroupKey();
method public int getRank();
+ method public java.util.List<android.service.notification.SnoozeCriterion> getSnoozeCriteria();
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
method public boolean matchesInterruptionFilter();
@@ -37953,6 +38051,17 @@
field public static final android.os.Parcelable.Creator<android.service.notification.NotificationListenerService.RankingMap> CREATOR;
}
+ public final class SnoozeCriterion implements android.os.Parcelable {
+ ctor public SnoozeCriterion(java.lang.String, java.lang.CharSequence, java.lang.CharSequence);
+ ctor protected SnoozeCriterion(android.os.Parcel);
+ method public int describeContents();
+ method public java.lang.CharSequence getConfirmation();
+ method public java.lang.CharSequence getExplanation();
+ method public java.lang.String getId();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.notification.SnoozeCriterion> CREATOR;
+ }
+
public class StatusBarNotification implements android.os.Parcelable {
ctor public deprecated StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
ctor public StatusBarNotification(android.os.Parcel);
@@ -37981,19 +38090,7 @@
package android.service.persistentdata {
- public abstract interface IPersistentDataBlockService implements android.os.IInterface {
- method public abstract int getDataBlockSize() throws android.os.RemoteException;
- method public abstract int getFlashLockState() throws android.os.RemoteException;
- method public abstract long getMaximumDataBlockSize() throws android.os.RemoteException;
- method public abstract boolean getOemUnlockEnabled() throws android.os.RemoteException;
- method public abstract byte[] read() throws android.os.RemoteException;
- method public abstract void setOemUnlockEnabled(boolean) throws android.os.RemoteException;
- method public abstract void wipe() throws android.os.RemoteException;
- method public abstract int write(byte[]) throws android.os.RemoteException;
- }
-
public class PersistentDataBlockManager {
- ctor public PersistentDataBlockManager(android.service.persistentdata.IPersistentDataBlockService);
method public int getDataBlockSize();
method public int getFlashLockState();
method public long getMaximumDataBlockSize();
@@ -40283,7 +40380,10 @@
field public static final java.lang.String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool";
field public static final java.lang.String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
field public static final java.lang.String KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
+ field public static final java.lang.String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int";
field public static final java.lang.String KEY_IMS_DTMF_TONE_DELAY_INT = "ims_dtmf_tone_delay_int";
+ field public static final java.lang.String KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL = "is_ims_conference_size_enforced_bool";
+ field public static final java.lang.String KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL = "mdn_is_additional_voicemail_number_bool";
field public static final java.lang.String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
field public static final java.lang.String KEY_MMS_ALIAS_MAX_CHARS_INT = "aliasMaxChars";
field public static final java.lang.String KEY_MMS_ALIAS_MIN_CHARS_INT = "aliasMinChars";
@@ -40666,6 +40766,7 @@
}
public final class SmsManager {
+ method public java.lang.String createAppSpecificSmsToken(android.app.PendingIntent);
method public java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
method public void downloadMultimediaMessage(android.content.Context, java.lang.String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
method public android.os.Bundle getCarrierConfigValues();
@@ -42288,6 +42389,12 @@
method public java.util.Map<java.lang.String, java.lang.Float> getTypeConfidence();
}
+ public final class TextClassificationManager implements android.text.TextAssistant {
+ method public void addLinks(android.text.Spannable, int);
+ method public java.util.List<android.text.TextLanguage> detectLanguages(java.lang.CharSequence);
+ method public android.text.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+ }
+
public abstract interface TextDirectionHeuristic {
method public abstract boolean isRtl(char[], int, int);
method public abstract boolean isRtl(java.lang.CharSequence, int, int);
@@ -42303,6 +42410,13 @@
field public static final android.text.TextDirectionHeuristic RTL;
}
+ public final class TextLanguage {
+ ctor public TextLanguage(int, int, java.util.Map<java.lang.String, java.lang.Float>);
+ method public int getEndIndex();
+ method public java.util.Map<java.lang.String, java.lang.Float> getLanguageConfidence();
+ method public int getStartIndex();
+ }
+
public class TextPaint extends android.graphics.Paint {
ctor public TextPaint();
ctor public TextPaint(int);
@@ -42997,12 +43111,6 @@
method public void writeToParcel(android.os.Parcel, int);
}
- public class RasterizerSpan extends android.text.style.CharacterStyle implements android.text.style.UpdateAppearance {
- ctor public RasterizerSpan(android.graphics.Rasterizer);
- method public android.graphics.Rasterizer getRasterizer();
- method public void updateDrawState(android.text.TextPaint);
- }
-
public class RelativeSizeSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
ctor public RelativeSizeSpan(float);
ctor public RelativeSizeSpan(android.os.Parcel);
@@ -45998,7 +46106,8 @@
method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
method public boolean dispatchNestedScroll(int, int, int, int, int[]);
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
- method public void dispatchProvideStructure(android.view.ViewStructure);
+ method public deprecated void dispatchProvideStructure(android.view.ViewStructure);
+ method public void dispatchProvideStructure(android.view.ViewStructure, int);
method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
method protected void dispatchSetActivated(boolean);
@@ -46095,11 +46204,13 @@
method public final int getMeasuredWidthAndState();
method public int getMinimumHeight();
method public int getMinimumWidth();
+ method public int getNextClusterForwardId();
method public int getNextFocusDownId();
method public int getNextFocusForwardId();
method public int getNextFocusLeftId();
method public int getNextFocusRightId();
method public int getNextFocusUpId();
+ method public int getNextSectionForwardId();
method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
method public android.view.ViewOutlineProvider getOutlineProvider();
method public int getOverScrollMode();
@@ -46202,6 +46313,8 @@
method public boolean isInEditMode();
method public boolean isInLayout();
method public boolean isInTouchMode();
+ method public final boolean isKeyboardNavigationCluster();
+ method public final boolean isKeyboardNavigationSection();
method public boolean isLaidOut();
method public boolean isLayoutDirectionResolved();
method public boolean isLayoutRequested();
@@ -46264,8 +46377,10 @@
method protected void onMeasure(int, int);
method protected void onOverScrolled(int, int, boolean, boolean);
method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
- method public void onProvideStructure(android.view.ViewStructure);
- method public void onProvideVirtualStructure(android.view.ViewStructure);
+ method public deprecated void onProvideStructure(android.view.ViewStructure);
+ method public void onProvideStructure(android.view.ViewStructure, int);
+ method public deprecated void onProvideVirtualStructure(android.view.ViewStructure);
+ method public void onProvideVirtualStructure(android.view.ViewStructure, int);
method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
method protected void onRestoreInstanceState(android.os.Parcelable);
method public void onRtlPropertiesChanged(int);
@@ -46368,6 +46483,8 @@
method public void setId(int);
method public void setImportantForAccessibility(int);
method public void setKeepScreenOn(boolean);
+ method public void setKeyboardNavigationCluster(boolean);
+ method public void setKeyboardNavigationSection(boolean);
method public void setLabelFor(int);
method public void setLayerPaint(android.graphics.Paint);
method public void setLayerType(int, android.graphics.Paint);
@@ -46379,11 +46496,13 @@
method public void setMinimumHeight(int);
method public void setMinimumWidth(int);
method public void setNestedScrollingEnabled(boolean);
+ method public void setNextClusterForwardId(int);
method public void setNextFocusDownId(int);
method public void setNextFocusForwardId(int);
method public void setNextFocusLeftId(int);
method public void setNextFocusRightId(int);
method public void setNextFocusUpId(int);
+ method public void setNextSectionForwardId(int);
method public void setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener);
method public void setOnClickListener(android.view.View.OnClickListener);
method public void setOnContextClickListener(android.view.View.OnContextClickListener);
@@ -46467,6 +46586,8 @@
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+ field public static final int ASSIST_FLAG_NON_SANITIZED_TEXT = 2; // 0x2
+ field public static final int ASSIST_FLAG_SANITIZED_TEXT = 1; // 0x1
field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
@@ -46573,6 +46694,7 @@
field public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024; // 0x400
field public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512; // 0x200
field public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256; // 0x100
+ field public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 16; // 0x10
field public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 8192; // 0x2000
field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
@@ -47493,7 +47615,7 @@
field public static final int FLAG_ALT_FOCUSABLE_IM = 131072; // 0x20000
field public static final deprecated int FLAG_BLUR_BEHIND = 4; // 0x4
field public static final int FLAG_DIM_BEHIND = 2; // 0x2
- field public static final int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
+ field public static final deprecated int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
field public static final deprecated int FLAG_DITHER = 4096; // 0x1000
field public static final int FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = -2147483648; // 0x80000000
field public static final int FLAG_FORCE_NOT_FULLSCREEN = 2048; // 0x800
@@ -49836,6 +49958,7 @@
method public abstract void onMeasure(int, int);
method public abstract void onOverScrolled(int, int, boolean, boolean);
method public abstract void onProvideVirtualStructure(android.view.ViewStructure);
+ method public default void onProvideVirtualStructure(android.view.ViewStructure, int);
method public abstract void onScrollChanged(int, int, int, int);
method public abstract void onSizeChanged(int, int, int, int);
method public abstract void onStartTemporaryDetach();
@@ -63285,6 +63408,10 @@
ctor public Locale(java.lang.String, java.lang.String);
ctor public Locale(java.lang.String);
method public java.lang.Object clone();
+ method public static java.util.List<java.util.Locale> filter(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.util.Locale>, java.util.Locale.FilteringMode);
+ method public static java.util.List<java.util.Locale> filter(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.util.Locale>);
+ method public static java.util.List<java.lang.String> filterTags(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.lang.String>, java.util.Locale.FilteringMode);
+ method public static java.util.List<java.lang.String> filterTags(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.lang.String>);
method public static java.util.Locale forLanguageTag(java.lang.String);
method public static java.util.Locale[] getAvailableLocales();
method public java.lang.String getCountry();
@@ -63313,6 +63440,8 @@
method public java.lang.String getUnicodeLocaleType(java.lang.String);
method public java.lang.String getVariant();
method public boolean hasExtensions();
+ method public static java.util.Locale lookup(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.util.Locale>);
+ method public static java.lang.String lookupTag(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.lang.String>);
method public static synchronized void setDefault(java.util.Locale);
method public static synchronized void setDefault(java.util.Locale.Category, java.util.Locale);
method public java.util.Locale stripExtensions();
@@ -63368,6 +63497,28 @@
enum_constant public static final java.util.Locale.Category FORMAT;
}
+ public static final class Locale.FilteringMode extends java.lang.Enum {
+ method public static java.util.Locale.FilteringMode valueOf(java.lang.String);
+ method public static final java.util.Locale.FilteringMode[] values();
+ enum_constant public static final java.util.Locale.FilteringMode AUTOSELECT_FILTERING;
+ enum_constant public static final java.util.Locale.FilteringMode EXTENDED_FILTERING;
+ enum_constant public static final java.util.Locale.FilteringMode IGNORE_EXTENDED_RANGES;
+ enum_constant public static final java.util.Locale.FilteringMode MAP_EXTENDED_RANGES;
+ enum_constant public static final java.util.Locale.FilteringMode REJECT_EXTENDED_RANGES;
+ }
+
+ public static final class Locale.LanguageRange {
+ ctor public Locale.LanguageRange(java.lang.String);
+ ctor public Locale.LanguageRange(java.lang.String, double);
+ method public java.lang.String getRange();
+ method public double getWeight();
+ method public static java.util.List<java.util.Locale.LanguageRange> mapEquivalents(java.util.List<java.util.Locale.LanguageRange>, java.util.Map<java.lang.String, java.util.List<java.lang.String>>);
+ method public static java.util.List<java.util.Locale.LanguageRange> parse(java.lang.String);
+ method public static java.util.List<java.util.Locale.LanguageRange> parse(java.lang.String, java.util.Map<java.lang.String, java.util.List<java.lang.String>>);
+ field public static final double MAX_WEIGHT = 1.0;
+ field public static final double MIN_WEIGHT = 0.0;
+ }
+
public class LongSummaryStatistics implements java.util.function.IntConsumer java.util.function.LongConsumer {
ctor public LongSummaryStatistics();
method public void accept(int);
@@ -66034,13 +66185,13 @@
ctor public Attributes.Name(java.lang.String);
field public static final java.util.jar.Attributes.Name CLASS_PATH;
field public static final java.util.jar.Attributes.Name CONTENT_TYPE;
- field public static final java.util.jar.Attributes.Name EXTENSION_INSTALLATION;
+ field public static final deprecated java.util.jar.Attributes.Name EXTENSION_INSTALLATION;
field public static final java.util.jar.Attributes.Name EXTENSION_LIST;
field public static final java.util.jar.Attributes.Name EXTENSION_NAME;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_TITLE;
- field public static final java.util.jar.Attributes.Name IMPLEMENTATION_URL;
+ field public static final deprecated java.util.jar.Attributes.Name IMPLEMENTATION_URL;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR;
- field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR_ID;
+ field public static final deprecated java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR_ID;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VERSION;
field public static final java.util.jar.Attributes.Name MAIN_CLASS;
field public static final java.util.jar.Attributes.Name MANIFEST_VERSION;
@@ -66107,11 +66258,11 @@
}
public static abstract interface Pack200.Packer {
- method public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void addPropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract void pack(java.util.jar.JarFile, java.io.OutputStream) throws java.io.IOException;
method public abstract void pack(java.util.jar.JarInputStream, java.io.OutputStream) throws java.io.IOException;
method public abstract java.util.SortedMap<java.lang.String, java.lang.String> properties();
- method public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void removePropertyChangeListener(java.beans.PropertyChangeListener);
field public static final java.lang.String CLASS_ATTRIBUTE_PFX = "pack.class.attribute.";
field public static final java.lang.String CODE_ATTRIBUTE_PFX = "pack.code.attribute.";
field public static final java.lang.String DEFLATE_HINT = "pack.deflate.hint";
@@ -66134,9 +66285,9 @@
}
public static abstract interface Pack200.Unpacker {
- method public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void addPropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract java.util.SortedMap<java.lang.String, java.lang.String> properties();
- method public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void removePropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract void unpack(java.io.InputStream, java.util.jar.JarOutputStream) throws java.io.IOException;
method public abstract void unpack(java.io.File, java.util.jar.JarOutputStream) throws java.io.IOException;
field public static final java.lang.String DEFLATE_HINT = "unpack.deflate.hint";
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 98e7953..0919b8f 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -76,10 +76,25 @@
enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET;
}
+ public deprecated class LayerRasterizer extends android.graphics.Rasterizer {
+ ctor public LayerRasterizer();
+ method public void addLayer(android.graphics.Paint, float, float);
+ method public void addLayer(android.graphics.Paint);
+ }
+
+ public class Paint {
+ method public deprecated android.graphics.Rasterizer getRasterizer();
+ method public deprecated android.graphics.Rasterizer setRasterizer(android.graphics.Rasterizer);
+ }
+
public deprecated class PixelXorXfermode extends android.graphics.Xfermode {
ctor public PixelXorXfermode(int);
}
+ public class Rasterizer {
+ ctor public Rasterizer();
+ }
+
}
package android.location {
@@ -387,6 +402,15 @@
}
+package android.text.style {
+
+ public class RasterizerSpan extends android.text.style.CharacterStyle implements android.text.style.UpdateAppearance {
+ ctor public RasterizerSpan(android.graphics.Rasterizer);
+ method public android.graphics.Rasterizer getRasterizer();
+ }
+
+}
+
package android.util {
public deprecated class FloatMath {
diff --git a/api/test-current.txt b/api/test-current.txt
index f269479..c8c0790 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -750,6 +750,8 @@
field public static final int keyWidth = 16843325; // 0x101023d
field public static final int keyboardLayout = 16843691; // 0x10103ab
field public static final int keyboardMode = 16843341; // 0x101024d
+ field public static final int keyboardNavigationCluster = 16844096; // 0x1010540
+ field public static final int keyboardNavigationSection = 16844097; // 0x1010541
field public static final int keycode = 16842949; // 0x10100c5
field public static final int killAfterRestore = 16843420; // 0x101029c
field public static final int label = 16842753; // 0x1010001
@@ -893,11 +895,13 @@
field public static final int negativeButtonText = 16843254; // 0x10101f6
field public static final int nestedScrollingEnabled = 16843830; // 0x1010436
field public static final int networkSecurityConfig = 16844071; // 0x1010527
+ field public static final int nextClusterForward = 16844098; // 0x1010542
field public static final int nextFocusDown = 16842980; // 0x10100e4
field public static final int nextFocusForward = 16843580; // 0x101033c
field public static final int nextFocusLeft = 16842977; // 0x10100e1
field public static final int nextFocusRight = 16842978; // 0x10100e2
field public static final int nextFocusUp = 16842979; // 0x10100e3
+ field public static final int nextSectionForward = 16844099; // 0x1010543
field public static final int noHistory = 16843309; // 0x101022d
field public static final int normalScreens = 16843397; // 0x1010285
field public static final int notificationTimeout = 16843651; // 0x1010383
@@ -1425,6 +1429,7 @@
field public static final int viewportWidth = 16843778; // 0x1010402
field public static final int visibility = 16842972; // 0x10100dc
field public static final int visible = 16843156; // 0x1010194
+ field public static final int visibleToEphemeral = 16844095; // 0x101053f
field public static final int vmSafeMode = 16843448; // 0x10102b8
field public static final int voiceIcon = 16843908; // 0x1010484
field public static final int voiceLanguage = 16843349; // 0x1010255
@@ -2804,9 +2809,14 @@
public static class GestureDescription.StrokeDescription {
ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long);
+ ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long, int, boolean);
+ method public int getContinuedStrokeId();
method public long getDuration();
+ method public int getId();
method public android.graphics.Path getPath();
method public long getStartTime();
+ method public boolean isContinued();
+ field public static final int INVALID_STROKE_ID = -1; // 0xffffffff
}
}
@@ -3476,6 +3486,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public void enterPictureInPictureMode(float);
+ method public void enterPictureInPictureModeOnMoveToBackground(boolean);
method public android.view.View findViewById(int);
method public void finish();
method public void finishActivity(int);
@@ -5958,6 +5969,13 @@
package android.app.admin {
+ public final class ConnectEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
+ method public java.lang.String getIpAddress();
+ method public int getPort();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.ConnectEvent> CREATOR;
+ }
+
public final class DeviceAdminInfo implements android.os.Parcelable {
ctor public DeviceAdminInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
@@ -5998,6 +6016,7 @@
method public void onEnabled(android.content.Context, android.content.Intent);
method public void onLockTaskModeEntering(android.content.Context, android.content.Intent, java.lang.String);
method public void onLockTaskModeExiting(android.content.Context, android.content.Intent);
+ method public void onNetworkLogsAvailable(android.content.Context, android.content.Intent, long, int);
method public void onPasswordChanged(android.content.Context, android.content.Intent);
method public void onPasswordExpiring(android.content.Context, android.content.Intent);
method public void onPasswordFailed(android.content.Context, android.content.Intent);
@@ -6107,6 +6126,7 @@
method public boolean isLockTaskPermitted(java.lang.String);
method public boolean isManagedProfile(android.content.ComponentName);
method public boolean isMasterVolumeMuted(android.content.ComponentName);
+ method public boolean isNetworkLoggingEnabled(android.content.ComponentName);
method public boolean isPackageSuspended(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
method public boolean isProfileOwnerApp(java.lang.String);
method public boolean isProvisioningAllowed(java.lang.String);
@@ -6120,6 +6140,7 @@
method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
method public boolean requestBugreport(android.content.ComponentName);
method public boolean resetPassword(java.lang.String, int);
+ method public java.util.List<android.app.admin.NetworkEvent> retrieveNetworkLogs(android.content.ComponentName, long);
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
@@ -6143,6 +6164,7 @@
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
+ method public void setNetworkLoggingEnabled(android.content.ComponentName, boolean);
method public void setOrganizationColor(android.content.ComponentName, int);
method public void setOrganizationName(android.content.ComponentName, java.lang.CharSequence);
method public java.lang.String[] setPackagesSuspended(android.content.ComponentName, java.lang.String[], boolean);
@@ -6207,6 +6229,7 @@
field public static final deprecated java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM";
field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS";
+ field public static final java.lang.String EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION = "android.app.extra.PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION";
field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
@@ -6256,6 +6279,22 @@
field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
}
+ public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable {
+ method public java.lang.String getHostname();
+ method public java.lang.String[] getIpAddresses();
+ method public int getIpAddressesCount();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.DnsEvent> CREATOR;
+ }
+
+ public abstract class NetworkEvent implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.lang.String getPackageName();
+ method public long getTimestamp();
+ method public abstract void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.admin.NetworkEvent> CREATOR;
+ }
+
public class SecurityLog {
ctor public SecurityLog();
field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
@@ -7966,6 +8005,7 @@
method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public abstract android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ method public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
method public boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
method protected final void setPathPermissions(android.content.pm.PathPermission[]);
method protected final void setReadPermission(java.lang.String);
@@ -7998,6 +8038,7 @@
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String) throws android.os.RemoteException;
method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal) throws android.os.RemoteException;
+ method public android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal) throws android.os.RemoteException;
method public deprecated boolean release();
method public final android.net.Uri uncanonicalize(android.net.Uri) throws android.os.RemoteException;
method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
@@ -8101,6 +8142,7 @@
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
+ method public final android.database.Cursor query(android.net.Uri, java.lang.String[], android.os.Bundle, android.os.CancellationSignal);
method public final boolean refresh(android.net.Uri, android.os.Bundle, android.os.CancellationSignal);
method public final void registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver);
method public void releasePersistableUriPermission(android.net.Uri, int);
@@ -8123,6 +8165,9 @@
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
+ field public static final java.lang.String QUERY_ARG_SELECTION = "android:query-selection";
+ field public static final java.lang.String QUERY_ARG_SELECTION_ARGS = "android:query-selection-args";
+ field public static final java.lang.String QUERY_ARG_SORT_ORDER = "android:query-sort-order";
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
field public static final java.lang.String SCHEME_CONTENT = "content";
field public static final java.lang.String SCHEME_FILE = "file";
@@ -8368,6 +8413,7 @@
field public static final java.lang.String TELECOM_SERVICE = "telecom";
field public static final java.lang.String TELEPHONY_SERVICE = "phone";
field public static final java.lang.String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
+ field public static final java.lang.String TEXT_CLASSIFICATION_SERVICE = "textclassification";
field public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
field public static final java.lang.String TV_INPUT_SERVICE = "tv_input";
field public static final java.lang.String UI_MODE_SERVICE = "uimode";
@@ -8841,6 +8887,7 @@
field public static final java.lang.String CATEGORY_SELECTED_ALTERNATIVE = "android.intent.category.SELECTED_ALTERNATIVE";
field public static final java.lang.String CATEGORY_TAB = "android.intent.category.TAB";
field public static final java.lang.String CATEGORY_TEST = "android.intent.category.TEST";
+ field public static final java.lang.String CATEGORY_TYPED_OPENABLE = "android.intent.category.TYPED_OPENABLE";
field public static final java.lang.String CATEGORY_UNIT_TEST = "android.intent.category.UNIT_TEST";
field public static final java.lang.String CATEGORY_VOICE = "android.intent.category.VOICE";
field public static final android.os.Parcelable.Creator<android.content.Intent> CREATOR;
@@ -11775,6 +11822,7 @@
enum_constant public static final android.graphics.Bitmap.Config ALPHA_8;
enum_constant public static final deprecated android.graphics.Bitmap.Config ARGB_4444;
enum_constant public static final android.graphics.Bitmap.Config ARGB_8888;
+ enum_constant public static final android.graphics.Bitmap.Config HARDWARE;
enum_constant public static final android.graphics.Bitmap.Config RGB_565;
}
@@ -12235,12 +12283,6 @@
enum_constant public static final android.graphics.Interpolator.Result NORMAL;
}
- public deprecated class LayerRasterizer extends android.graphics.Rasterizer {
- ctor public LayerRasterizer();
- method public void addLayer(android.graphics.Paint, float, float);
- method public void addLayer(android.graphics.Paint);
- }
-
public class LightingColorFilter extends android.graphics.ColorFilter {
ctor public LightingColorFilter(int, int);
}
@@ -12402,7 +12444,6 @@
method public int getOffsetForAdvance(char[], int, int, int, int, boolean, float);
method public int getOffsetForAdvance(java.lang.CharSequence, int, int, int, int, boolean, float);
method public android.graphics.PathEffect getPathEffect();
- method public deprecated android.graphics.Rasterizer getRasterizer();
method public float getRunAdvance(char[], int, int, int, int, boolean, int);
method public float getRunAdvance(java.lang.CharSequence, int, int, int, int, boolean, int);
method public android.graphics.Shader getShader();
@@ -12459,7 +12500,6 @@
method public void setLinearText(boolean);
method public android.graphics.MaskFilter setMaskFilter(android.graphics.MaskFilter);
method public android.graphics.PathEffect setPathEffect(android.graphics.PathEffect);
- method public deprecated android.graphics.Rasterizer setRasterizer(android.graphics.Rasterizer);
method public android.graphics.Shader setShader(android.graphics.Shader);
method public void setShadowLayer(float, float, float, int);
method public void setStrikeThruText(boolean);
@@ -12766,10 +12806,6 @@
ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
}
- public deprecated class Rasterizer {
- ctor public Rasterizer();
- }
-
public final class Rect implements android.os.Parcelable {
ctor public Rect();
ctor public Rect(int, int, int, int);
@@ -20286,8 +20322,8 @@
}
public class AudioTrack implements android.media.AudioRouting {
- ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
- ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+ ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
+ ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
@@ -21576,7 +21612,7 @@
method public void selectTrack(int) throws java.lang.IllegalStateException;
method public void setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
- method public void setAudioStreamType(int);
+ method public deprecated void setAudioStreamType(int);
method public void setAuxEffectSendLevel(float);
method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
@@ -29767,9 +29803,11 @@
method public deprecated void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
method public static boolean supportsMultipleUsers();
field public static final java.lang.String ALLOW_PARENT_PROFILE_APP_LINKING = "allow_parent_profile_app_linking";
+ field public static final java.lang.String DISALLOW_ADD_MANAGED_PROFILE = "no_add_managed_profile";
field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user";
field public static final java.lang.String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps";
+ field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
@@ -29790,6 +29828,7 @@
field public static final java.lang.String DISALLOW_NETWORK_RESET = "no_network_reset";
field public static final java.lang.String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
field public static final java.lang.String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
+ field public static final java.lang.String DISALLOW_REMOVE_MANAGED_PROFILE = "no_remove_managed_profile";
field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
field public static final java.lang.String DISALLOW_SAFE_BOOT = "no_safe_boot";
field public static final java.lang.String DISALLOW_SET_USER_ICON = "no_set_user_icon";
@@ -32823,6 +32862,7 @@
field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
+ field public static final java.lang.String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
field public static final java.lang.String ACTION_HARD_KEYBOARD_SETTINGS = "android.settings.HARD_KEYBOARD_SETTINGS";
field public static final java.lang.String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS";
field public static final java.lang.String ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS = "android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS";
@@ -34929,7 +34969,8 @@
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
- method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback);
+ method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.SaveCallback);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
}
@@ -34947,6 +34988,11 @@
method public android.service.autofill.FillCallback.FillData.Builder setTextField(int, java.lang.String);
}
+ public final class SaveCallback {
+ method public void onFailure(java.lang.CharSequence);
+ method public void onSuccess(int[]);
+ }
+
}
package android.service.carrier {
@@ -35152,18 +35198,19 @@
package android.service.notification {
public final class Adjustment implements android.os.Parcelable {
- ctor public Adjustment(java.lang.String, java.lang.String, int, android.os.Bundle, java.lang.CharSequence, android.net.Uri, int);
+ ctor public Adjustment(java.lang.String, java.lang.String, android.os.Bundle, java.lang.CharSequence, int);
ctor protected Adjustment(android.os.Parcel);
method public int describeContents();
method public java.lang.CharSequence getExplanation();
- method public int getImportance();
method public java.lang.String getKey();
method public java.lang.String getPackage();
- method public android.net.Uri getReference();
method public android.os.Bundle getSignals();
method public int getUser();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
+ field public static final java.lang.String KEY_CHANNEL_ID = "key_channel_id";
+ field public static final java.lang.String KEY_PEOPLE = "key_people";
+ field public static final java.lang.String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
}
public final class Condition implements android.os.Parcelable {
@@ -35216,8 +35263,12 @@
ctor public NotificationAssistantService();
method public final void adjustNotification(android.service.notification.Adjustment);
method public final void adjustNotifications(java.util.List<android.service.notification.Adjustment>);
+ method public void createNotificationChannel(java.lang.String, android.app.NotificationChannel);
+ method public void deleteNotificationChannel(java.lang.String, java.lang.String);
+ method public java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
method public final android.os.IBinder onBind(android.content.Intent);
method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+ method public void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
}
@@ -35285,11 +35336,14 @@
public static class NotificationListenerService.Ranking {
ctor public NotificationListenerService.Ranking();
+ method public java.util.List<java.lang.String> getAdditionalPeople();
+ method public android.app.NotificationChannel getChannel();
method public int getImportance();
method public java.lang.CharSequence getImportanceExplanation();
method public java.lang.String getKey();
method public java.lang.String getOverrideGroupKey();
method public int getRank();
+ method public java.util.List<android.service.notification.SnoozeCriterion> getSnoozeCriteria();
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
method public boolean matchesInterruptionFilter();
@@ -35303,6 +35357,17 @@
field public static final android.os.Parcelable.Creator<android.service.notification.NotificationListenerService.RankingMap> CREATOR;
}
+ public final class SnoozeCriterion implements android.os.Parcelable {
+ ctor public SnoozeCriterion(java.lang.String, java.lang.CharSequence, java.lang.CharSequence);
+ ctor protected SnoozeCriterion(android.os.Parcel);
+ method public int describeContents();
+ method public java.lang.CharSequence getConfirmation();
+ method public java.lang.CharSequence getExplanation();
+ method public java.lang.String getId();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.notification.SnoozeCriterion> CREATOR;
+ }
+
public class StatusBarNotification implements android.os.Parcelable {
ctor public deprecated StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
ctor public StatusBarNotification(android.os.Parcel);
@@ -37355,7 +37420,10 @@
field public static final java.lang.String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool";
field public static final java.lang.String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
field public static final java.lang.String KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
+ field public static final java.lang.String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int";
field public static final java.lang.String KEY_IMS_DTMF_TONE_DELAY_INT = "ims_dtmf_tone_delay_int";
+ field public static final java.lang.String KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL = "is_ims_conference_size_enforced_bool";
+ field public static final java.lang.String KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL = "mdn_is_additional_voicemail_number_bool";
field public static final java.lang.String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
field public static final java.lang.String KEY_MMS_ALIAS_MAX_CHARS_INT = "aliasMaxChars";
field public static final java.lang.String KEY_MMS_ALIAS_MIN_CHARS_INT = "aliasMinChars";
@@ -37738,6 +37806,7 @@
}
public final class SmsManager {
+ method public java.lang.String createAppSpecificSmsToken(android.app.PendingIntent);
method public java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
method public void downloadMultimediaMessage(android.content.Context, java.lang.String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
method public android.os.Bundle getCarrierConfigValues();
@@ -39280,6 +39349,12 @@
method public java.util.Map<java.lang.String, java.lang.Float> getTypeConfidence();
}
+ public final class TextClassificationManager implements android.text.TextAssistant {
+ method public void addLinks(android.text.Spannable, int);
+ method public java.util.List<android.text.TextLanguage> detectLanguages(java.lang.CharSequence);
+ method public android.text.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+ }
+
public abstract interface TextDirectionHeuristic {
method public abstract boolean isRtl(char[], int, int);
method public abstract boolean isRtl(java.lang.CharSequence, int, int);
@@ -39295,6 +39370,13 @@
field public static final android.text.TextDirectionHeuristic RTL;
}
+ public final class TextLanguage {
+ ctor public TextLanguage(int, int, java.util.Map<java.lang.String, java.lang.Float>);
+ method public int getEndIndex();
+ method public java.util.Map<java.lang.String, java.lang.Float> getLanguageConfidence();
+ method public int getStartIndex();
+ }
+
public class TextPaint extends android.graphics.Paint {
ctor public TextPaint();
ctor public TextPaint(int);
@@ -39989,12 +40071,6 @@
method public void writeToParcel(android.os.Parcel, int);
}
- public class RasterizerSpan extends android.text.style.CharacterStyle implements android.text.style.UpdateAppearance {
- ctor public RasterizerSpan(android.graphics.Rasterizer);
- method public android.graphics.Rasterizer getRasterizer();
- method public void updateDrawState(android.text.TextPaint);
- }
-
public class RelativeSizeSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
ctor public RelativeSizeSpan(float);
ctor public RelativeSizeSpan(android.os.Parcel);
@@ -41487,11 +41563,15 @@
public final class ProtoOutputStream {
ctor public ProtoOutputStream();
ctor public ProtoOutputStream(int);
+ ctor public ProtoOutputStream(java.io.OutputStream);
+ ctor public ProtoOutputStream(java.io.FileDescriptor);
method public static int checkFieldId(long, long);
method public static int convertObjectIdToOrdinal(int);
method public void dump(java.lang.String);
+ method public void end(long);
method public void endObject(long);
method public void endRepeatedObject(long);
+ method public void flush();
method public byte[] getBytes();
method public static int getDepthFromToken(long);
method public static int getObjectIdFromToken(long);
@@ -41500,9 +41580,17 @@
method public static int getTagSizeFromToken(long);
method public static long makeFieldId(int, long);
method public static long makeToken(int, boolean, int, int, int);
+ method public long start(long);
method public long startObject(long);
method public long startRepeatedObject(long);
method public static java.lang.String token2String(long);
+ method public void write(long, double);
+ method public void write(long, float);
+ method public void write(long, int);
+ method public void write(long, long);
+ method public void write(long, boolean);
+ method public void write(long, java.lang.String);
+ method public void write(long, byte[]);
method public void writeBool(long, boolean);
method public void writeBytes(long, byte[]);
method public void writeDouble(long, double);
@@ -41512,6 +41600,8 @@
method public void writeFloat(long, float);
method public void writeInt32(long, int);
method public void writeInt64(long, long);
+ method public void writeObject(long, byte[]);
+ method public void writeObjectImpl(int, byte[]);
method public void writePackedBool(long, boolean[]);
method public void writePackedDouble(long, double[]);
method public void writePackedEnum(long, int[]);
@@ -41535,6 +41625,8 @@
method public void writeRepeatedFloat(long, float);
method public void writeRepeatedInt32(long, int);
method public void writeRepeatedInt64(long, long);
+ method public void writeRepeatedObject(long, byte[]);
+ method public void writeRepeatedObjectImpl(int, byte[]);
method public void writeRepeatedSFixed32(long, int);
method public void writeRepeatedSFixed64(long, long);
method public void writeRepeatedSInt32(long, int);
@@ -43143,7 +43235,8 @@
method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
method public boolean dispatchNestedScroll(int, int, int, int, int[]);
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
- method public void dispatchProvideStructure(android.view.ViewStructure);
+ method public deprecated void dispatchProvideStructure(android.view.ViewStructure);
+ method public void dispatchProvideStructure(android.view.ViewStructure, int);
method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
method protected void dispatchSetActivated(boolean);
@@ -43240,11 +43333,13 @@
method public final int getMeasuredWidthAndState();
method public int getMinimumHeight();
method public int getMinimumWidth();
+ method public int getNextClusterForwardId();
method public int getNextFocusDownId();
method public int getNextFocusForwardId();
method public int getNextFocusLeftId();
method public int getNextFocusRightId();
method public int getNextFocusUpId();
+ method public int getNextSectionForwardId();
method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
method public android.view.ViewOutlineProvider getOutlineProvider();
method public int getOverScrollMode();
@@ -43348,6 +43443,8 @@
method public boolean isInEditMode();
method public boolean isInLayout();
method public boolean isInTouchMode();
+ method public final boolean isKeyboardNavigationCluster();
+ method public final boolean isKeyboardNavigationSection();
method public boolean isLaidOut();
method public boolean isLayoutDirectionResolved();
method public boolean isLayoutRequested();
@@ -43410,8 +43507,10 @@
method protected void onMeasure(int, int);
method protected void onOverScrolled(int, int, boolean, boolean);
method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
- method public void onProvideStructure(android.view.ViewStructure);
- method public void onProvideVirtualStructure(android.view.ViewStructure);
+ method public deprecated void onProvideStructure(android.view.ViewStructure);
+ method public void onProvideStructure(android.view.ViewStructure, int);
+ method public deprecated void onProvideVirtualStructure(android.view.ViewStructure);
+ method public void onProvideVirtualStructure(android.view.ViewStructure, int);
method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
method protected void onRestoreInstanceState(android.os.Parcelable);
method public void onRtlPropertiesChanged(int);
@@ -43514,6 +43613,8 @@
method public void setId(int);
method public void setImportantForAccessibility(int);
method public void setKeepScreenOn(boolean);
+ method public void setKeyboardNavigationCluster(boolean);
+ method public void setKeyboardNavigationSection(boolean);
method public void setLabelFor(int);
method public void setLayerPaint(android.graphics.Paint);
method public void setLayerType(int, android.graphics.Paint);
@@ -43525,11 +43626,13 @@
method public void setMinimumHeight(int);
method public void setMinimumWidth(int);
method public void setNestedScrollingEnabled(boolean);
+ method public void setNextClusterForwardId(int);
method public void setNextFocusDownId(int);
method public void setNextFocusForwardId(int);
method public void setNextFocusLeftId(int);
method public void setNextFocusRightId(int);
method public void setNextFocusUpId(int);
+ method public void setNextSectionForwardId(int);
method public void setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener);
method public void setOnClickListener(android.view.View.OnClickListener);
method public void setOnContextClickListener(android.view.View.OnContextClickListener);
@@ -43613,6 +43716,8 @@
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+ field public static final int ASSIST_FLAG_NON_SANITIZED_TEXT = 2; // 0x2
+ field public static final int ASSIST_FLAG_SANITIZED_TEXT = 1; // 0x1
field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
@@ -43719,6 +43824,7 @@
field public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024; // 0x400
field public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512; // 0x200
field public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256; // 0x100
+ field public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 16; // 0x10
field public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 8192; // 0x2000
field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
@@ -44640,7 +44746,7 @@
field public static final int FLAG_ALT_FOCUSABLE_IM = 131072; // 0x20000
field public static final deprecated int FLAG_BLUR_BEHIND = 4; // 0x4
field public static final int FLAG_DIM_BEHIND = 2; // 0x2
- field public static final int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
+ field public static final deprecated int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
field public static final deprecated int FLAG_DITHER = 4096; // 0x1000
field public static final int FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = -2147483648; // 0x80000000
field public static final int FLAG_FORCE_NOT_FULLSCREEN = 2048; // 0x800
@@ -60092,6 +60198,10 @@
ctor public Locale(java.lang.String, java.lang.String);
ctor public Locale(java.lang.String);
method public java.lang.Object clone();
+ method public static java.util.List<java.util.Locale> filter(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.util.Locale>, java.util.Locale.FilteringMode);
+ method public static java.util.List<java.util.Locale> filter(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.util.Locale>);
+ method public static java.util.List<java.lang.String> filterTags(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.lang.String>, java.util.Locale.FilteringMode);
+ method public static java.util.List<java.lang.String> filterTags(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.lang.String>);
method public static java.util.Locale forLanguageTag(java.lang.String);
method public static java.util.Locale[] getAvailableLocales();
method public java.lang.String getCountry();
@@ -60120,6 +60230,8 @@
method public java.lang.String getUnicodeLocaleType(java.lang.String);
method public java.lang.String getVariant();
method public boolean hasExtensions();
+ method public static java.util.Locale lookup(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.util.Locale>);
+ method public static java.lang.String lookupTag(java.util.List<java.util.Locale.LanguageRange>, java.util.Collection<java.lang.String>);
method public static synchronized void setDefault(java.util.Locale);
method public static synchronized void setDefault(java.util.Locale.Category, java.util.Locale);
method public java.util.Locale stripExtensions();
@@ -60175,6 +60287,28 @@
enum_constant public static final java.util.Locale.Category FORMAT;
}
+ public static final class Locale.FilteringMode extends java.lang.Enum {
+ method public static java.util.Locale.FilteringMode valueOf(java.lang.String);
+ method public static final java.util.Locale.FilteringMode[] values();
+ enum_constant public static final java.util.Locale.FilteringMode AUTOSELECT_FILTERING;
+ enum_constant public static final java.util.Locale.FilteringMode EXTENDED_FILTERING;
+ enum_constant public static final java.util.Locale.FilteringMode IGNORE_EXTENDED_RANGES;
+ enum_constant public static final java.util.Locale.FilteringMode MAP_EXTENDED_RANGES;
+ enum_constant public static final java.util.Locale.FilteringMode REJECT_EXTENDED_RANGES;
+ }
+
+ public static final class Locale.LanguageRange {
+ ctor public Locale.LanguageRange(java.lang.String);
+ ctor public Locale.LanguageRange(java.lang.String, double);
+ method public java.lang.String getRange();
+ method public double getWeight();
+ method public static java.util.List<java.util.Locale.LanguageRange> mapEquivalents(java.util.List<java.util.Locale.LanguageRange>, java.util.Map<java.lang.String, java.util.List<java.lang.String>>);
+ method public static java.util.List<java.util.Locale.LanguageRange> parse(java.lang.String);
+ method public static java.util.List<java.util.Locale.LanguageRange> parse(java.lang.String, java.util.Map<java.lang.String, java.util.List<java.lang.String>>);
+ field public static final double MAX_WEIGHT = 1.0;
+ field public static final double MIN_WEIGHT = 0.0;
+ }
+
public class LongSummaryStatistics implements java.util.function.IntConsumer java.util.function.LongConsumer {
ctor public LongSummaryStatistics();
method public void accept(int);
@@ -62841,13 +62975,13 @@
ctor public Attributes.Name(java.lang.String);
field public static final java.util.jar.Attributes.Name CLASS_PATH;
field public static final java.util.jar.Attributes.Name CONTENT_TYPE;
- field public static final java.util.jar.Attributes.Name EXTENSION_INSTALLATION;
+ field public static final deprecated java.util.jar.Attributes.Name EXTENSION_INSTALLATION;
field public static final java.util.jar.Attributes.Name EXTENSION_LIST;
field public static final java.util.jar.Attributes.Name EXTENSION_NAME;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_TITLE;
- field public static final java.util.jar.Attributes.Name IMPLEMENTATION_URL;
+ field public static final deprecated java.util.jar.Attributes.Name IMPLEMENTATION_URL;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR;
- field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR_ID;
+ field public static final deprecated java.util.jar.Attributes.Name IMPLEMENTATION_VENDOR_ID;
field public static final java.util.jar.Attributes.Name IMPLEMENTATION_VERSION;
field public static final java.util.jar.Attributes.Name MAIN_CLASS;
field public static final java.util.jar.Attributes.Name MANIFEST_VERSION;
@@ -62914,11 +63048,11 @@
}
public static abstract interface Pack200.Packer {
- method public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void addPropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract void pack(java.util.jar.JarFile, java.io.OutputStream) throws java.io.IOException;
method public abstract void pack(java.util.jar.JarInputStream, java.io.OutputStream) throws java.io.IOException;
method public abstract java.util.SortedMap<java.lang.String, java.lang.String> properties();
- method public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void removePropertyChangeListener(java.beans.PropertyChangeListener);
field public static final java.lang.String CLASS_ATTRIBUTE_PFX = "pack.class.attribute.";
field public static final java.lang.String CODE_ATTRIBUTE_PFX = "pack.code.attribute.";
field public static final java.lang.String DEFLATE_HINT = "pack.deflate.hint";
@@ -62941,9 +63075,9 @@
}
public static abstract interface Pack200.Unpacker {
- method public abstract void addPropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void addPropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract java.util.SortedMap<java.lang.String, java.lang.String> properties();
- method public abstract void removePropertyChangeListener(java.beans.PropertyChangeListener);
+ method public default deprecated void removePropertyChangeListener(java.beans.PropertyChangeListener);
method public abstract void unpack(java.io.InputStream, java.util.jar.JarOutputStream) throws java.io.IOException;
method public abstract void unpack(java.io.File, java.util.jar.JarOutputStream) throws java.io.IOException;
field public static final java.lang.String DEFLATE_HINT = "unpack.deflate.hint";
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 683a695..10e6eb5 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -78,10 +78,25 @@
enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET;
}
+ public deprecated class LayerRasterizer extends android.graphics.Rasterizer {
+ ctor public LayerRasterizer();
+ method public void addLayer(android.graphics.Paint, float, float);
+ method public void addLayer(android.graphics.Paint);
+ }
+
+ public class Paint {
+ method public deprecated android.graphics.Rasterizer getRasterizer();
+ method public deprecated android.graphics.Rasterizer setRasterizer(android.graphics.Rasterizer);
+ }
+
public deprecated class PixelXorXfermode extends android.graphics.Xfermode {
ctor public PixelXorXfermode(int);
}
+ public class Rasterizer {
+ ctor public Rasterizer();
+ }
+
}
package android.location {
@@ -393,6 +408,15 @@
}
+package android.text.style {
+
+ public class RasterizerSpan extends android.text.style.CharacterStyle implements android.text.style.UpdateAppearance {
+ ctor public RasterizerSpan(android.graphics.Rasterizer);
+ method public android.graphics.Rasterizer getRasterizer();
+ }
+
+}
+
package android.util {
public deprecated class FloatMath {
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 7967e2a..9fad7bf 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -608,9 +608,10 @@
return;
}
+ char* out = timeBuff[0] == ' ' ? &timeBuff[1] : &timeBuff[0];
int x = xPos;
int y = yPos;
- drawText(timeBuff, font, false, &x, &y);
+ drawText(out, font, false, &x, &y);
}
bool BootAnimation::parseAnimationDesc(Animation& animation)
diff --git a/cmds/bootanimation/bootanimation_main.cpp b/cmds/bootanimation/bootanimation_main.cpp
index 48a34e7..dca7ea6 100644
--- a/cmds/bootanimation/bootanimation_main.cpp
+++ b/cmds/bootanimation/bootanimation_main.cpp
@@ -37,6 +37,10 @@
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.nobootanimation", value, "0");
int noBootAnimation = atoi(value);
+ if (!noBootAnimation) {
+ property_get("ro.boot.quiescent", value, "0");
+ noBootAnimation = atoi(value);
+ }
ALOGI_IF(noBootAnimation, "boot animation disabled");
if (!noBootAnimation) {
@@ -47,7 +51,6 @@
sp<BootAnimation> boot = new BootAnimation();
IPCThreadState::self()->joinThreadPool();
-
}
return 0;
}
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 63641a8..3687f10 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -19,6 +19,7 @@
import android.app.ActivityManager;
import android.app.ContentProviderHolder;
import android.app.IActivityManager;
+import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.IContentProvider;
import android.database.Cursor;
@@ -589,8 +590,8 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- Cursor cursor = provider.query(resolveCallingPackage(), mUri, mProjection, mWhere,
- null, mSortOrder, null);
+ Cursor cursor = provider.query(resolveCallingPackage(), mUri, mProjection,
+ ContentResolver.createSqlQueryBundle(mWhere, null, mSortOrder), null);
if (cursor == null) {
System.out.println("No result found.");
return;
diff --git a/cmds/media/src/com/android/commands/media/Media.java b/cmds/media/src/com/android/commands/media/Media.java
index 0e0ecd0..4be4654 100644
--- a/cmds/media/src/com/android/commands/media/Media.java
+++ b/cmds/media/src/com/android/commands/media/Media.java
@@ -64,13 +64,15 @@
" media dispatch KEY\n" +
" media list-sessions\n" +
" media monitor <tag>\n" +
+ " media volume [options]\n" +
"\n" +
"media dispatch: dispatch a media key to the system.\n" +
" KEY may be: play, pause, play-pause, mute, headsethook,\n" +
" stop, next, previous, rewind, record, fast-forword.\n" +
"media list-sessions: print a list of the current sessions.\n" +
"media monitor: monitor updates to the specified session.\n" +
- " Use the tag from list-sessions.\n"
+ " Use the tag from list-sessions.\n" +
+ "media volume: " + VolumeCtrl.USAGE
);
}
@@ -92,6 +94,8 @@
runListSessions();
} else if (op.equals("monitor")) {
runMonitor();
+ } else if (op.equals("volume")) {
+ runVolume();
} else {
showError("Error: unknown command '" + op + "'");
return;
@@ -322,4 +326,10 @@
System.out.println("***Error listing sessions***");
}
}
+
+ //=================================
+ // "volume" command for stream volume control
+ private void runVolume() throws Exception {
+ VolumeCtrl.run(this);
+ }
}
diff --git a/cmds/media/src/com/android/commands/media/VolumeCtrl.java b/cmds/media/src/com/android/commands/media/VolumeCtrl.java
new file mode 100755
index 0000000..f54ae59
--- /dev/null
+++ b/cmds/media/src/com/android/commands/media/VolumeCtrl.java
@@ -0,0 +1,178 @@
+/*
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package com.android.commands.media;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioSystem;
+import android.media.IAudioService;
+import android.os.ServiceManager;
+import android.util.AndroidException;
+
+import com.android.internal.os.BaseCommand;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.lang.ArrayIndexOutOfBoundsException;
+
+/**
+ * Command line tool to exercise AudioService.setStreamVolume()
+ * and AudioService.adjustStreamVolume()
+ */
+public class VolumeCtrl {
+
+ private final static String TAG = "VolumeCtrl";
+
+ public final static String USAGE = new String(
+ "the options are as follows: \n" +
+ "\t\t--stream STREAM selects the stream to control, see AudioManager.STREAM_*\n" +
+ "\t\t controls AudioManager.STREAM_MUSIC if no stream is specified\n"+
+ "\t\t--index INDEX sets the volume index value\n" +
+ "\t\t--adj DIRECTION adjusts the volume, use raise|same|lower for the direction\n" +
+ "\t\t--show shows the UI during the volume change \n" +
+ "\texamples:\n" +
+ "\t\tadb shell media volume --show --stream 3 --index 11 \n" +
+ "\t\tadb shell media volume --stream 0 --adj lower \n"
+ );
+
+ private final static int VOLUME_CONTROL_MODE_SET = 0;
+ private final static int VOLUME_CONTROL_MODE_ADJUST = 1;
+
+ private final static String ADJUST_LOWER = "lower";
+ private final static String ADJUST_SAME = "same";
+ private final static String ADJUST_RAISE = "raise";
+
+ public static void run(BaseCommand cmd) throws Exception {
+ //----------------------------------------
+ // Default parameters
+ int stream = AudioManager.STREAM_MUSIC;
+ int volIndex = 5;
+ int mode = VOLUME_CONTROL_MODE_SET;
+ int adjDir = AudioManager.ADJUST_RAISE;
+ boolean showUi = false;
+
+ //----------------------------------------
+ // read options
+ String option;
+ String adjustment = null;
+ while ((option = cmd.nextOption()) != null) {
+ switch (option) {
+ case "--show":
+ showUi = true;
+ break;
+ case "--set":
+ mode = VOLUME_CONTROL_MODE_SET;
+ log(LOG_V, "will set volume");
+ break;
+ case "--adjust":
+ mode = VOLUME_CONTROL_MODE_ADJUST;
+ log(LOG_V, "will adjust volume");
+ break;
+ case "--stream":
+ stream = Integer.decode(cmd.nextArgRequired()).intValue();
+ log(LOG_V, "will control stream=" + stream + " (" + streamName(stream) + ")");
+ break;
+ case "--index":
+ volIndex = Integer.decode(cmd.nextArgRequired()).intValue();
+ mode = VOLUME_CONTROL_MODE_SET;
+ log(LOG_V, "will set volume to index=" + volIndex);
+ break;
+ case "--adj":
+ mode = VOLUME_CONTROL_MODE_ADJUST;
+ adjustment = cmd.nextArgRequired();
+ log(LOG_V, "will adjust volume");
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown argument " + option);
+ }
+ }
+
+ //------------------------------
+ // Read options: validation
+ if (mode == VOLUME_CONTROL_MODE_ADJUST) {
+ if (adjustment == null) {
+ cmd.showError("Error: no valid volume adjustment (null)");
+ return;
+ }
+ switch (adjustment) {
+ case ADJUST_RAISE: adjDir = AudioManager.ADJUST_RAISE; break;
+ case ADJUST_SAME: adjDir = AudioManager.ADJUST_SAME; break;
+ case ADJUST_LOWER: adjDir = AudioManager.ADJUST_LOWER; break;
+ default:
+ cmd.showError("Error: no valid volume adjustment, was " + adjustment
+ + ", expected " + ADJUST_LOWER + "|" + ADJUST_SAME + "|"
+ + ADJUST_RAISE);
+ return;
+ }
+ }
+
+ //----------------------------------------
+ // Test initialization
+ log(LOG_V, "Connecting to AudioService");
+ IAudioService audioService = IAudioService.Stub.asInterface(ServiceManager.checkService(
+ Context.AUDIO_SERVICE));
+ if (audioService == null) {
+ System.err.println(BaseCommand.NO_SYSTEM_ERROR_CODE);
+ throw new AndroidException(
+ "Can't connect to audio service; is the system running?");
+ }
+
+ if (mode == VOLUME_CONTROL_MODE_SET) {
+ if ((volIndex > audioService.getStreamMaxVolume(stream))
+ || (volIndex < audioService.getStreamMinVolume(stream))) {
+ cmd.showError(String.format("Error: invalid volume index %d for stream %d "
+ + "(should be in [%d..%d])", volIndex, stream,
+ audioService.getStreamMinVolume(stream),
+ audioService.getStreamMaxVolume(stream)));
+ return;
+ }
+ }
+
+ //----------------------------------------
+ // Non-interactive test
+ final int flag = showUi? AudioManager.FLAG_SHOW_UI : 0;
+ final String pack = cmd.getClass().getPackage().getName();
+ if (mode == VOLUME_CONTROL_MODE_SET) {
+ audioService.setStreamVolume(stream, volIndex, flag, pack/*callingPackage*/);
+ } else if (mode == VOLUME_CONTROL_MODE_ADJUST) {
+ audioService.adjustStreamVolume(stream, adjDir, flag, pack);
+ }
+ }
+
+ //--------------------------------------------
+ // Utilities
+
+ static final String LOG_V = "[v]";
+ static final String LOG_W = "[w]";
+ static final String LOG_OK = "[ok]";
+
+ static void log(String code, String msg) {
+ System.out.println(code + " " + msg);
+ }
+
+ static String streamName(int stream) {
+ try {
+ return AudioSystem.STREAM_NAMES[stream];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return "invalid stream";
+ }
+ }
+
+}
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 50f46f4..810d2018 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -553,7 +553,7 @@
sessionParams.abiOverride = checkAbiArgument(nextOptionData());
break;
case "--ephemeral":
- sessionParams.installFlags |= PackageManager.INSTALL_EPHEMERAL;
+ sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
break;
case "--user":
params.userId = UserHandle.parseUserArg(nextOptionData());
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index a41f122..377e29d 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -175,13 +175,20 @@
if (base != NULL) {
if (png) {
- const SkImageInfo info = SkImageInfo::Make(w, h, flinger2skia(f),
- kPremul_SkAlphaType);
- sk_sp<SkData> data(SkImageEncoder::EncodeData(info, base, s*bytesPerPixel(f),
- SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality));
- if (data.get()) {
- write(fd, data->data(), data->size());
- }
+ const SkImageInfo info =
+ SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType);
+ SkPixmap pixmap(info, base, s * bytesPerPixel(f));
+ struct FDWStream final : public SkWStream {
+ size_t fBytesWritten = 0;
+ int fFd;
+ FDWStream(int f) : fFd(f) {}
+ size_t bytesWritten() const override { return fBytesWritten; }
+ bool write(const void* buffer, size_t size) override {
+ fBytesWritten += size;
+ return size == 0 || ::write(fFd, buffer, size) > 0;
+ }
+ } fdStream(fd);
+ (void)SkEncodeImage(&fdStream, pixmap, SkEncodedImageFormat::kPNG, 100);
if (fn != NULL) {
notifyMediaScanner(fn);
}
diff --git a/cmds/uiautomator/library/Android.mk b/cmds/uiautomator/library/Android.mk
index d65b0833..af2e25a 100644
--- a/cmds/uiautomator/library/Android.mk
+++ b/cmds/uiautomator/library/Android.mk
@@ -18,7 +18,7 @@
uiautomator.core_src_files := $(call all-java-files-under, core-src) \
$(call all-java-files-under, testrunner-src)
-uiautomator.core_java_libraries := android.test.runner core-junit
+uiautomator.core_java_libraries := android.test.runner junit
uiautomator_internal_api_file := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/uiautomator_api.txt
uiautomator_internal_removed_api_file := \
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
index 32b4595..b0ab235 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
@@ -20,6 +20,7 @@
import android.app.ContentProviderHolder;
import android.app.IActivityManager;
import android.app.UiAutomation;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentProvider;
import android.database.Cursor;
@@ -69,10 +70,12 @@
cursor = provider.query(null, Settings.Secure.CONTENT_URI,
new String[] {
Settings.Secure.VALUE
- }, "name=?",
- new String[] {
- Settings.Secure.LONG_PRESS_TIMEOUT
- }, null, null);
+ },
+ ContentResolver.createSqlQueryBundle(
+ "name=?",
+ new String[] { Settings.Secure.LONG_PRESS_TIMEOUT },
+ null),
+ null);
if (cursor.moveToFirst()) {
longPressTimeout = cursor.getInt(0);
}
diff --git a/core/java/android/accessibilityservice/GestureDescription.java b/core/java/android/accessibilityservice/GestureDescription.java
index d9b03fa..c9da152 100644
--- a/core/java/android/accessibilityservice/GestureDescription.java
+++ b/core/java/android/accessibilityservice/GestureDescription.java
@@ -23,10 +23,6 @@
import android.graphics.RectF;
import android.os.Parcel;
import android.os.Parcelable;
-import android.view.InputDevice;
-import android.view.MotionEvent;
-import android.view.MotionEvent.PointerCoords;
-import android.view.MotionEvent.PointerProperties;
import java.util.ArrayList;
import java.util.List;
@@ -128,9 +124,14 @@
for (int i = 0; i < mStrokes.size(); i++) {
StrokeDescription strokeDescription = mStrokes.get(i);
if (strokeDescription.hasPointForTime(time)) {
- touchPoints[numPointsFound].mPathIndex = i;
- touchPoints[numPointsFound].mIsStartOfPath = (time == strokeDescription.mStartTime);
- touchPoints[numPointsFound].mIsEndOfPath = (time == strokeDescription.mEndTime);
+ touchPoints[numPointsFound].mStrokeId = strokeDescription.getId();
+ touchPoints[numPointsFound].mContinuedStrokeId =
+ strokeDescription.getContinuedStrokeId();
+ touchPoints[numPointsFound].mIsStartOfPath =
+ (strokeDescription.getContinuedStrokeId() < 0)
+ && (time == strokeDescription.mStartTime);
+ touchPoints[numPointsFound].mIsEndOfPath = !strokeDescription.isContinued()
+ && (time == strokeDescription.mEndTime);
strokeDescription.getPosForTime(time, mTempPos);
touchPoints[numPointsFound].mX = Math.round(mTempPos[0]);
touchPoints[numPointsFound].mY = Math.round(mTempPos[1]);
@@ -196,6 +197,10 @@
* Immutable description of stroke that can be part of a gesture.
*/
public static class StrokeDescription {
+ public static final int INVALID_STROKE_ID = -1;
+
+ static int sIdCounter;
+
Path mPath;
long mStartTime;
long mEndTime;
@@ -203,6 +208,9 @@
private PathMeasure mPathMeasure;
// The tap location is only set for zero-length paths
float[] mTapLocation;
+ int mId;
+ boolean mContinued;
+ int mContinuedStrokeId;
/**
* @param path The path to follow. Must have exactly one contour. The bounds of the path
@@ -216,6 +224,32 @@
public StrokeDescription(@NonNull Path path,
@IntRange(from = 0) long startTime,
@IntRange(from = 0) long duration) {
+ this(path, startTime, duration, INVALID_STROKE_ID, false);
+ }
+
+ /**
+ * @param path The path to follow. Must have exactly one contour. The bounds of the path
+ * must not be negative. The path must not be empty. If the path has zero length
+ * (for example, a single {@code moveTo()}), the stroke is a touch that doesn't move.
+ * @param startTime The time, in milliseconds, from the time the gesture starts to the
+ * time the stroke should start. Must not be negative.
+ * @param duration The duration, in milliseconds, the stroke takes to traverse the path.
+ * Must be positive.
+ * @param continuedStrokeId The ID of the stroke that this stroke continues, or
+ * {@link #INVALID_STROKE_ID} if it continues no stroke. The stroke it
+ * continues must have its isContinued flag set to {@code true} and must be in the
+ * gesture dispatched immediately before the one containing this stroke.
+ * @param isContinued {@code true} if this stroke will be continued by one in the
+ * next gesture {@code false} otherwise. Continued strokes keep their pointers down when
+ * the gesture completes.
+ */
+ public StrokeDescription(@NonNull Path path,
+ @IntRange(from = 0) long startTime,
+ @IntRange(from = 0) long duration,
+ @IntRange(from = 0) int continuedStrokeId,
+ boolean isContinued) {
+ mContinued = isContinued;
+ mContinuedStrokeId = continuedStrokeId;
if (duration <= 0) {
throw new IllegalArgumentException("Duration must be positive");
}
@@ -252,6 +286,7 @@
mStartTime = startTime;
mEndTime = startTime + duration;
mTimeToLengthConversion = getLength() / duration;
+ mId = sIdCounter++;
}
/**
@@ -281,6 +316,34 @@
return mEndTime - mStartTime;
}
+ /**
+ * Get the stroke's ID. The ID is used when a stroke is to be continued by another
+ * stroke in a future gesture.
+ *
+ * @return the ID of this stroke
+ */
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * Check if this stroke is marked to continue in the next gesture.
+ *
+ * @return {@code true} if the stroke is to be continued.
+ */
+ public boolean isContinued() {
+ return mContinued;
+ }
+
+ /**
+ * Get the ID of the stroke that this one will continue.
+ *
+ * @return The ID of the stroke that this stroke continues, or 0 if no such stroke exists.
+ */
+ public int getContinuedStrokeId() {
+ return mContinuedStrokeId;
+ }
+
float getLength() {
return mPathMeasure.getLength();
}
@@ -314,11 +377,12 @@
private static final int FLAG_IS_START_OF_PATH = 0x01;
private static final int FLAG_IS_END_OF_PATH = 0x02;
- int mPathIndex;
- boolean mIsStartOfPath;
- boolean mIsEndOfPath;
- float mX;
- float mY;
+ public int mStrokeId;
+ public int mContinuedStrokeId;
+ public boolean mIsStartOfPath;
+ public boolean mIsEndOfPath;
+ public float mX;
+ public float mY;
public TouchPoint() {
}
@@ -328,7 +392,8 @@
}
public TouchPoint(Parcel parcel) {
- mPathIndex = parcel.readInt();
+ mStrokeId = parcel.readInt();
+ mContinuedStrokeId = parcel.readInt();
int startEnd = parcel.readInt();
mIsStartOfPath = (startEnd & FLAG_IS_START_OF_PATH) != 0;
mIsEndOfPath = (startEnd & FLAG_IS_END_OF_PATH) != 0;
@@ -336,8 +401,9 @@
mY = parcel.readFloat();
}
- void copyFrom(TouchPoint other) {
- mPathIndex = other.mPathIndex;
+ public void copyFrom(TouchPoint other) {
+ mStrokeId = other.mStrokeId;
+ mContinuedStrokeId = other.mContinuedStrokeId;
mIsStartOfPath = other.mIsStartOfPath;
mIsEndOfPath = other.mIsEndOfPath;
mX = other.mX;
@@ -351,7 +417,8 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mPathIndex);
+ dest.writeInt(mStrokeId);
+ dest.writeInt(mContinuedStrokeId);
int startEnd = mIsStartOfPath ? FLAG_IS_START_OF_PATH : 0;
startEnd |= mIsEndOfPath ? FLAG_IS_END_OF_PATH : 0;
dest.writeInt(startEnd);
@@ -426,30 +493,15 @@
}
/**
- * Class to convert a GestureDescription to a series of MotionEvents.
+ * Class to convert a GestureDescription to a series of GestureSteps.
*
* @hide
*/
public static class MotionEventGenerator {
- /**
- * Constants used to initialize all MotionEvents
- */
- private static final int EVENT_META_STATE = 0;
- private static final int EVENT_BUTTON_STATE = 0;
- private static final int EVENT_DEVICE_ID = 0;
- private static final int EVENT_EDGE_FLAGS = 0;
- private static final int EVENT_SOURCE = InputDevice.SOURCE_TOUCHSCREEN;
- private static final int EVENT_FLAGS = 0;
- private static final float EVENT_X_PRECISION = 1;
- private static final float EVENT_Y_PRECISION = 1;
-
/* Lazily-created scratch memory for processing touches */
private static TouchPoint[] sCurrentTouchPoints;
- private static TouchPoint[] sLastTouchPoints;
- private static PointerCoords[] sPointerCoords;
- private static PointerProperties[] sPointerProps;
- static List<GestureStep> getGestureStepsFromGestureDescription(
+ public static List<GestureStep> getGestureStepsFromGestureDescription(
GestureDescription description, int sampleTimeMs) {
final List<GestureStep> gestureSteps = new ArrayList<>();
@@ -474,31 +526,6 @@
return gestureSteps;
}
- public static List<MotionEvent> getMotionEventsFromGestureSteps(List<GestureStep> steps) {
- final List<MotionEvent> motionEvents = new ArrayList<>();
-
- // Number of points in last touch event
- int lastTouchPointSize = 0;
- TouchPoint[] lastTouchPoints;
-
- for (int i = 0; i < steps.size(); i++) {
- GestureStep step = steps.get(i);
- int currentTouchPointSize = step.numTouchPoints;
- lastTouchPoints = getLastTouchPoints(
- Math.max(lastTouchPointSize, currentTouchPointSize));
-
- appendMoveEventIfNeeded(motionEvents, lastTouchPoints, lastTouchPointSize,
- step.touchPoints, currentTouchPointSize, step.timeSinceGestureStart);
- lastTouchPointSize = appendUpEvents(motionEvents, lastTouchPoints,
- lastTouchPointSize, step.touchPoints, currentTouchPointSize,
- step.timeSinceGestureStart);
- lastTouchPointSize = appendDownEvents(motionEvents, lastTouchPoints,
- lastTouchPointSize, step.touchPoints, currentTouchPointSize,
- step.timeSinceGestureStart);
- }
- return motionEvents;
- }
-
private static TouchPoint[] getCurrentTouchPoints(int requiredCapacity) {
if ((sCurrentTouchPoints == null) || (sCurrentTouchPoints.length < requiredCapacity)) {
sCurrentTouchPoints = new TouchPoint[requiredCapacity];
@@ -508,133 +535,5 @@
}
return sCurrentTouchPoints;
}
-
- private static TouchPoint[] getLastTouchPoints(int requiredCapacity) {
- if ((sLastTouchPoints == null) || (sLastTouchPoints.length < requiredCapacity)) {
- sLastTouchPoints = new TouchPoint[requiredCapacity];
- for (int i = 0; i < requiredCapacity; i++) {
- sLastTouchPoints[i] = new TouchPoint();
- }
- }
- return sLastTouchPoints;
- }
-
- private static PointerCoords[] getPointerCoords(int requiredCapacity) {
- if ((sPointerCoords == null) || (sPointerCoords.length < requiredCapacity)) {
- sPointerCoords = new PointerCoords[requiredCapacity];
- for (int i = 0; i < requiredCapacity; i++) {
- sPointerCoords[i] = new PointerCoords();
- }
- }
- return sPointerCoords;
- }
-
- private static PointerProperties[] getPointerProps(int requiredCapacity) {
- if ((sPointerProps == null) || (sPointerProps.length < requiredCapacity)) {
- sPointerProps = new PointerProperties[requiredCapacity];
- for (int i = 0; i < requiredCapacity; i++) {
- sPointerProps[i] = new PointerProperties();
- }
- }
- return sPointerProps;
- }
-
- private static void appendMoveEventIfNeeded(List<MotionEvent> motionEvents,
- TouchPoint[] lastTouchPoints, int lastTouchPointsSize,
- TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
- /* Look for pointers that have moved */
- boolean moveFound = false;
- for (int i = 0; i < currentTouchPointsSize; i++) {
- int lastPointsIndex = findPointByPathIndex(lastTouchPoints, lastTouchPointsSize,
- currentTouchPoints[i].mPathIndex);
- if (lastPointsIndex >= 0) {
- moveFound |= (lastTouchPoints[lastPointsIndex].mX != currentTouchPoints[i].mX)
- || (lastTouchPoints[lastPointsIndex].mY != currentTouchPoints[i].mY);
- lastTouchPoints[lastPointsIndex].copyFrom(currentTouchPoints[i]);
- }
- }
-
- if (moveFound) {
- long downTime = motionEvents.get(motionEvents.size() - 1).getDownTime();
- motionEvents.add(obtainMotionEvent(downTime, currentTime, MotionEvent.ACTION_MOVE,
- lastTouchPoints, lastTouchPointsSize));
- }
- }
-
- private static int appendUpEvents(List<MotionEvent> motionEvents,
- TouchPoint[] lastTouchPoints, int lastTouchPointsSize,
- TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
- /* Look for a pointer at the end of its path */
- for (int i = 0; i < currentTouchPointsSize; i++) {
- if (currentTouchPoints[i].mIsEndOfPath) {
- int indexOfUpEvent = findPointByPathIndex(lastTouchPoints, lastTouchPointsSize,
- currentTouchPoints[i].mPathIndex);
- if (indexOfUpEvent < 0) {
- continue; // Should not happen
- }
- long downTime = motionEvents.get(motionEvents.size() - 1).getDownTime();
- int action = (lastTouchPointsSize == 1) ? MotionEvent.ACTION_UP
- : MotionEvent.ACTION_POINTER_UP;
- action |= indexOfUpEvent << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- motionEvents.add(obtainMotionEvent(downTime, currentTime, action,
- lastTouchPoints, lastTouchPointsSize));
- /* Remove this point from lastTouchPoints */
- for (int j = indexOfUpEvent; j < lastTouchPointsSize - 1; j++) {
- lastTouchPoints[j].copyFrom(lastTouchPoints[j+1]);
- }
- lastTouchPointsSize--;
- }
- }
- return lastTouchPointsSize;
- }
-
- private static int appendDownEvents(List<MotionEvent> motionEvents,
- TouchPoint[] lastTouchPoints, int lastTouchPointsSize,
- TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
- /* Look for a pointer that is just starting */
- for (int i = 0; i < currentTouchPointsSize; i++) {
- if (currentTouchPoints[i].mIsStartOfPath) {
- /* Add the point to last coords and use the new array to generate the event */
- lastTouchPoints[lastTouchPointsSize++].copyFrom(currentTouchPoints[i]);
- int action = (lastTouchPointsSize == 1) ? MotionEvent.ACTION_DOWN
- : MotionEvent.ACTION_POINTER_DOWN;
- long downTime = (action == MotionEvent.ACTION_DOWN) ? currentTime :
- motionEvents.get(motionEvents.size() - 1).getDownTime();
- action |= i << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- motionEvents.add(obtainMotionEvent(downTime, currentTime, action,
- lastTouchPoints, lastTouchPointsSize));
- }
- }
- return lastTouchPointsSize;
- }
-
- private static MotionEvent obtainMotionEvent(long downTime, long eventTime, int action,
- TouchPoint[] touchPoints, int touchPointsSize) {
- PointerCoords[] pointerCoords = getPointerCoords(touchPointsSize);
- PointerProperties[] pointerProperties = getPointerProps(touchPointsSize);
- for (int i = 0; i < touchPointsSize; i++) {
- pointerProperties[i].id = touchPoints[i].mPathIndex;
- pointerProperties[i].toolType = MotionEvent.TOOL_TYPE_UNKNOWN;
- pointerCoords[i].clear();
- pointerCoords[i].pressure = 1.0f;
- pointerCoords[i].size = 1.0f;
- pointerCoords[i].x = touchPoints[i].mX;
- pointerCoords[i].y = touchPoints[i].mY;
- }
- return MotionEvent.obtain(downTime, eventTime, action, touchPointsSize,
- pointerProperties, pointerCoords, EVENT_META_STATE, EVENT_BUTTON_STATE,
- EVENT_X_PRECISION, EVENT_Y_PRECISION, EVENT_DEVICE_ID, EVENT_EDGE_FLAGS,
- EVENT_SOURCE, EVENT_FLAGS);
- }
-
- private static int findPointByPathIndex(TouchPoint[] touchPoints, int touchPointsSize,
- int pathIndex) {
- for (int i = 0; i < touchPointsSize; i++) {
- if (touchPoints[i].mPathIndex == pathIndex) {
- return i;
- }
- }
- return -1;
- }
}
}
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 0c21c4f..4707bed 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -38,8 +38,8 @@
*
* {@sample development/samples/ApiDemos/res/anim/object_animator.xml ObjectAnimatorResources}
*
- * <p>When using resource files, it is possible to use {@link PropertyValuesHolder} and
- * {@link Keyframe} to create more complex animations. Using PropertyValuesHolders
+ * <p>Starting from API 23, it is possible to use {@link PropertyValuesHolder} and
+ * {@link Keyframe} in resource files to create more complex animations. Using PropertyValuesHolders
* allows animators to animate several properties in parallel, as shown in this sample:</p>
*
* {@sample development/samples/ApiDemos/res/anim/object_animator_pvh.xml
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index ed7e89d..f0fc8af 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -49,8 +49,8 @@
*
* {@sample development/samples/ApiDemos/res/anim/animator.xml ValueAnimatorResources}
*
- * <p>It is also possible to use a combination of {@link PropertyValuesHolder} and
- * {@link Keyframe} resource tags to create a multi-step animation.
+ * <p>Starting from API 23, it is also possible to use a combination of {@link PropertyValuesHolder}
+ * and {@link Keyframe} resource tags to create a multi-step animation.
* Note that you can specify explicit fractional values (from 0 to 1) for
* each keyframe to determine when, in the overall duration, the animation should arrive at that
* value. Alternatively, you can leave the fractions off and the keyframes will be equally
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 90fff8d..2cdda3d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -75,6 +75,7 @@
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.TextAssistant;
+import android.text.TextClassificationManager;
import android.text.TextUtils;
import android.text.method.TextKeyListener;
import android.transition.Scene;
@@ -1402,7 +1403,7 @@
if (mTextAssistant != null) {
return mTextAssistant;
}
- return TextAssistant.NO_OP;
+ return getSystemService(TextClassificationManager.class);
}
/**
@@ -1737,8 +1738,8 @@
FillableInputField autoFillField = (FillableInputField) field;
final int viewId = autoFillField.getId();
final View view = root.findViewByAccessibilityIdTraversal(viewId);
- // TODO: should handle other types of view as well, but that will
- // require:
+ // TODO(b/33197203): should handle other types of view as well, but
+ // that will require:
// - a new interface like AutoFillable
// - a way for the views to define the type of the autofield value
if ((view instanceof EditText)) {
@@ -1751,7 +1752,7 @@
@Override
public void showError(String message) {
runOnUiThread(() -> {
- // TODO: temporary show a toast until it uses the Snack bar.
+ // TODO(b/33197203): temporary show a toast until it uses the Snack bar.
Toast.makeText(Activity.this, "Auto-fill request failed: " + message,
Toast.LENGTH_LONG).show();
});
@@ -2030,6 +2031,28 @@
}
/**
+ * Requests to the system that the activity can be automatically put into picture-in-picture
+ * mode when the user leaves the activity causing it normally to be hidden. This is a *not*
+ * a guarantee that the activity will actually be put in picture-in-picture mode, and depends
+ * on a number of factors, including whether there is already something in picture-in-picture.
+ *
+ * If {@param enterPictureInPictureOnMoveToBg} is true, then you may also call
+ * {@link #setPictureInPictureAspectRatio(float)} to specify the aspect ratio to automatically
+ * enter picture-in-picture with.
+ *
+ * @param enterPictureInPictureOnMoveToBg whether or not this activity can automatically enter
+ * picture-in-picture
+ */
+ public void enterPictureInPictureModeOnMoveToBackground(
+ boolean enterPictureInPictureOnMoveToBg) {
+ try {
+ ActivityManagerNative.getDefault().enterPictureInPictureModeOnMoveToBackground(mToken,
+ enterPictureInPictureOnMoveToBg);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Called by the system when the device configuration changes while your
* activity is running. Note that this will <em>only</em> be called if
* you have selected configurations you would like to handle with the
@@ -3044,8 +3067,11 @@
* @hide
*/
@Override
- public void onWindowDismissed(boolean finishTask) {
+ public void onWindowDismissed(boolean finishTask, boolean suppressWindowTransition) {
finish(finishTask ? FINISH_TASK_WITH_ACTIVITY : DONT_FINISH_TASK_WITH_ACTIVITY);
+ if (suppressWindowTransition) {
+ overridePendingTransition(0, 0);
+ }
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 65f74d1..f04455b 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -450,9 +450,6 @@
/** @hide requestType for assist context: generate full AssistStructure. */
public static final int ASSIST_CONTEXT_FULL = 1;
- /** @hide requestType for assist context: generate full AssistStructure for auto-fill. */
- public static final int ASSIST_CONTEXT_AUTOFILL = 2;
-
/** @hide Flag for registerUidObserver: report changes in process state. */
public static final int UID_OBSERVER_PROCSTATE = 1<<0;
@@ -561,8 +558,11 @@
/** ID of stack that always on top (always visible) when it exist. */
public static final int PINNED_STACK_ID = DOCKED_STACK_ID + 1;
+ /** Recents activity stack ID. */
+ public static final int RECENTS_STACK_ID = PINNED_STACK_ID + 1;
+
/** Last static stack stack ID. */
- public static final int LAST_STATIC_STACK_ID = PINNED_STACK_ID;
+ public static final int LAST_STATIC_STACK_ID = RECENTS_STACK_ID;
/** Start of ID range used by stacks that are created dynamically. */
public static final int FIRST_DYNAMIC_STACK_ID = LAST_STATIC_STACK_ID + 1;
@@ -735,6 +735,13 @@
}
/**
+ * Returns true if the input {@param stackId} is HOME_STACK_ID or RECENTS_STACK_ID
+ */
+ public static boolean isHomeOrRecentsStack(int stackId) {
+ return stackId == HOME_STACK_ID || stackId == RECENTS_STACK_ID;
+ }
+
+ /**
* Returns true if activities contained in this stack can request visible behind by
* calling {@link Activity#requestVisibleBehind}.
*/
@@ -760,7 +767,8 @@
/** Returns true if the input stack and its content can affect the device orientation. */
public static boolean canSpecifyOrientation(int stackId) {
- return stackId == HOME_STACK_ID || stackId == FULLSCREEN_WORKSPACE_STACK_ID;
+ return stackId == HOME_STACK_ID || stackId == RECENTS_STACK_ID
+ || stackId == FULLSCREEN_WORKSPACE_STACK_ID;
}
}
@@ -994,6 +1002,16 @@
}
/**
+ * Returns true if the system supports split screen multi-window.
+ * @hide
+ */
+ static public boolean supportsSplitScreenMultiWindow() {
+ return supportsMultiWindow()
+ && Resources.getSystem().getBoolean(
+ com.android.internal.R.bool.config_supportsSplitScreenMultiWindow);
+ }
+
+ /**
* Information you can set and retrieve about the current activity within the recent task list.
*/
public static class TaskDescription implements Parcelable {
@@ -1509,7 +1527,7 @@
* Ignores all tasks that are on the home stack.
* @hide
*/
- public static final int RECENT_IGNORE_HOME_STACK_TASKS = 0x0008;
+ public static final int RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS = 0x0008;
/**
* Ignores the top task in the docked stack.
@@ -2052,15 +2070,6 @@
}
}
- /** @hide */
- public boolean isInHomeStack(int taskId) {
- try {
- return getService().isInHomeStack(taskId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
/**
* Flag for {@link #moveTaskToFront(int, int)}: also move the "home"
* activity along with the task, so it is positioned immediately behind
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f052bf7..9a92764 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -88,6 +88,7 @@
import android.provider.Settings;
import android.security.NetworkSecurityPolicy;
import android.security.net.config.NetworkSecurityConfigProvider;
+import android.service.autofill.AutoFillService;
import android.service.autofill.IAutoFillCallback;
import android.service.voice.VoiceInteractionSession;
import android.util.AndroidRuntimeException;
@@ -640,6 +641,7 @@
IBinder requestToken;
int requestType;
int sessionId;
+ int flags;
}
static final class ActivityConfigChangeData {
@@ -1245,12 +1247,13 @@
@Override
public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken,
- int requestType, int sessionId) {
+ int requestType, int sessionId, int flags) {
RequestAssistContextExtras cmd = new RequestAssistContextExtras();
cmd.activityToken = activityToken;
cmd.requestToken = requestToken;
cmd.requestType = requestType;
cmd.sessionId = sessionId;
+ cmd.flags = flags;
sendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd);
}
@@ -2883,6 +2886,16 @@
}
public void handleRequestAssistContextExtras(RequestAssistContextExtras cmd) {
+ // Filling for auto-fill has a few differences:
+ // - it does not need an AssistContent
+ // - it does not call onProvideAssistData()
+ // - it needs an IAutoFillCallback
+ // - it sets the flags so views can provide autofill-specific data (such as passwords)
+ boolean forAutoFill = (cmd.flags
+ & (View.ASSIST_FLAG_SANITIZED_TEXT
+ | View.ASSIST_FLAG_NON_SANITIZED_TEXT)) != 0;
+
+ // TODO(b/33197203): decide if lastSessionId logic applies to auto-fill sessions
if (mLastSessionId != cmd.sessionId) {
// Clear the existing structures
mLastSessionId = cmd.sessionId;
@@ -2894,46 +2907,45 @@
mLastAssistStructures.remove(i);
}
}
- // Filling for auto-fill has a few differences:
- // - it does not need an AssistContent
- // - it does not call onProvideAssistData()
- // - it needs an IAutoFillCallback
- boolean forAutofill = cmd.requestType == ActivityManager.ASSIST_CONTEXT_AUTOFILL;
Bundle data = new Bundle();
AssistStructure structure = null;
- AssistContent content = forAutofill ? null : new AssistContent();
+ AssistContent content = forAutoFill ? null : new AssistContent();
ActivityClientRecord r = mActivities.get(cmd.activityToken);
Uri referrer = null;
if (r != null) {
- r.activity.getApplication().dispatchOnProvideAssistData(r.activity, data);
- if (!forAutofill) {
+ if (!forAutoFill) {
+ r.activity.getApplication().dispatchOnProvideAssistData(r.activity, data);
r.activity.onProvideAssistData(data);
}
referrer = r.activity.onProvideReferrer();
- if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL || forAutofill) {
- structure = new AssistStructure(r.activity);
+ if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL || forAutoFill) {
+ structure = new AssistStructure(r.activity, cmd.flags);
Intent activityIntent = r.activity.getIntent();
+ if (cmd.flags > 0) {
+ data.putInt(VoiceInteractionSession.KEY_FLAGS, cmd.flags);
+ }
+ // TODO(b/33197203): re-evaluate conditions below for auto-fill. In particular,
+ // FLAG_SECURE might be allowed on AUTO_FILL but not on AUTO_FILL_SAVE)
if (activityIntent != null && (r.window == null ||
(r.window.getAttributes().flags
& WindowManager.LayoutParams.FLAG_SECURE) == 0)) {
- Intent intent = new Intent(activityIntent);
- intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
- | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION));
- intent.removeUnsafeExtras();
- if (forAutofill) {
+ if (forAutoFill) {
IAutoFillCallback autoFillCallback = r.activity.getAutoFillCallback();
- data.putBinder(VoiceInteractionSession.KEY_AUTO_FILL_CALLBACK,
- autoFillCallback.asBinder());
+ data.putBinder(AutoFillService.KEY_CALLBACK, autoFillCallback.asBinder());
} else {
+ Intent intent = new Intent(activityIntent);
+ intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION));
+ intent.removeUnsafeExtras();
content.setDefaultIntent(intent);
}
} else {
- if (!forAutofill) {
+ if (!forAutoFill) {
content.setDefaultIntent(new Intent());
}
}
- if (!forAutofill) {
+ if (!forAutoFill) {
r.activity.onProvideAssistContent(content);
}
}
@@ -2941,6 +2953,7 @@
if (structure == null) {
structure = new AssistStructure();
}
+ // TODO(b/33197203): decide if lastSessionId logic applies to auto-fill sessions
mLastAssistStructures.add(new WeakReference<>(structure));
IActivityManager mgr = ActivityManager.getService();
try {
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 6cfa362..9f1a539 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -378,6 +378,11 @@
exceptionMessage = sanitizeString(exceptionMessage);
}
+ /** {@hide} */
+ public void appendStackTrace(String tr) {
+ stackTrace = sanitizeString(stackTrace + tr);
+ }
+
/**
* Ensure that the string is of reasonable size, truncating from the middle if needed.
*/
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index abb098f..105d2ca 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -16,6 +16,8 @@
package android.app;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -349,9 +351,7 @@
public BackStackRecord(FragmentManagerImpl manager) {
mManager = manager;
- int targetSdkVersion = manager.mHost.getContext().getApplicationInfo().targetSdkVersion;
- // TODO: make the check N_MR1 or O
- mAllowOptimization = targetSdkVersion > Build.VERSION_CODES.N;
+ mAllowOptimization = getTargetSdk() > Build.VERSION_CODES.N_MR1;
}
public int getId() {
@@ -367,14 +367,14 @@
}
public CharSequence getBreadCrumbTitle() {
- if (mBreadCrumbTitleRes != 0) {
+ if (mBreadCrumbTitleRes != 0 && mManager.mHost != null) {
return mManager.mHost.getContext().getText(mBreadCrumbTitleRes);
}
return mBreadCrumbTitleText;
}
public CharSequence getBreadCrumbShortTitle() {
- if (mBreadCrumbShortTitleRes != 0) {
+ if (mBreadCrumbShortTitleRes != 0 && mManager.mHost != null) {
return mManager.mHost.getContext().getText(mBreadCrumbShortTitleRes);
}
return mBreadCrumbShortTitleText;
@@ -404,14 +404,10 @@
}
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
- if (mManager.mHost.getContext() != null) {
- final int targetSdkVersion =
- mManager.mHost.getContext().getApplicationInfo().targetSdkVersion;
+ if (getTargetSdk() > Build.VERSION_CODES.N_MR1) {
final Class fragmentClass = fragment.getClass();
final int modifiers = fragmentClass.getModifiers();
- // TODO: make the check N_MR1 or O
- if (targetSdkVersion > Build.VERSION_CODES.N && (fragmentClass.isAnonymousClass()
- || !Modifier.isPublic(modifiers)
+ if ((fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers)
|| (fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers)))) {
throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName()
+ " must be a public static class to be properly recreated from"
@@ -917,4 +913,22 @@
public boolean isEmpty() {
return mOps.isEmpty();
}
+
+ /**
+ * @return the target SDK of the FragmentManager's application info. If the
+ * FragmentManager has been torn down, then 0 is returned.
+ */
+ private int getTargetSdk() {
+ FragmentHostCallback host = mManager.mHost;
+ if (host != null) {
+ Context context = host.getContext();
+ if (context != null) {
+ ApplicationInfo info = context.getApplicationInfo();
+ if (info != null) {
+ return info.targetSdkVersion;
+ }
+ }
+ }
+ return 0;
+ }
}
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 6e2c464..9c17780 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -200,6 +200,7 @@
@Nullable Message cancelCallback) {
this(context);
mCancelable = cancelable;
+ updateWindowForCancelable();
mCancelMessage = cancelCallback;
}
@@ -207,6 +208,7 @@
@Nullable OnCancelListener cancelListener) {
this(context);
mCancelable = cancelable;
+ updateWindowForCancelable();
setOnCancelListener(cancelListener);
}
@@ -742,7 +744,7 @@
/** @hide */
@Override
- public void onWindowDismissed(boolean finishTask) {
+ public void onWindowDismissed(boolean finishTask, boolean suppressWindowTransition) {
dismiss();
}
@@ -1187,6 +1189,7 @@
*/
public void setCancelable(boolean flag) {
mCancelable = flag;
+ updateWindowForCancelable();
}
/**
@@ -1200,6 +1203,7 @@
public void setCanceledOnTouchOutside(boolean cancel) {
if (cancel && !mCancelable) {
mCancelable = true;
+ updateWindowForCancelable();
}
mWindow.setCloseOnTouchOutside(cancel);
@@ -1351,4 +1355,8 @@
}
}
}
+
+ private void updateWindowForCancelable() {
+ mWindow.setCloseOnSwipeEnabled(mCancelable);
+ }
}
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 10d584f..b569b79 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -457,7 +457,7 @@
public void onSharedElementsReady() {
final View decorView = getDecor();
if (decorView != null) {
- OneShotPreDrawListener.add(decorView, () -> {
+ OneShotPreDrawListener.add(decorView, false, () -> {
startTransition(() -> {
startSharedElementTransition(sharedElementState);
});
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 21e3aee..2672798 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -124,13 +124,16 @@
}
public void resetViews() {
+ ViewGroup decorView = getDecor();
+ if (decorView != null) {
+ TransitionManager.endTransitions(decorView);
+ }
if (mTransitioningViews != null) {
showViews(mTransitioningViews, true);
setTransitioningViewsVisiblity(View.VISIBLE, true);
}
showViews(mSharedElements, true);
mIsHidden = true;
- ViewGroup decorView = getDecor();
if (!mIsReturning && decorView != null) {
decorView.suppressLayout(false);
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 1a36d1a..a10fffe 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -78,10 +78,12 @@
*/
interface IActivityManager {
// WARNING: when these transactions are updated, check if they are any callers on the native
- // side. If so, make sure they are using the correct transaction ids.
+ // side. If so, make sure they are using the correct transaction ids and arguments.
// If a transaction which will also be used on the native side is being inserted, add it to
// below block of transactions.
+ // Since these transactions are also called from native code, these must be kept in sync with
+ // the ones in frameworks/native/include/binder/IActivityManager.h
// =============== Beginning of transactions used on native side as well ======================
ParcelFileDescriptor openContentUri(in String uriString);
// =============== End of transactions used on native side as well ============================
@@ -370,7 +372,6 @@
// Start of L transactions
String getTagForIntentSender(in IIntentSender sender, in String prefix);
boolean startUserInBackground(int userid);
- boolean isInHomeStack(int taskId);
void startLockTaskModeById(int taskId);
void startLockTaskModeByToken(in IBinder token);
void stopLockTaskMode();
@@ -469,6 +470,10 @@
boolean isInPictureInPictureMode(in IBinder token);
void killPackageDependents(in String packageName, int userId);
void enterPictureInPictureMode(in IBinder token);
+ void enterPictureInPictureModeWithAspectRatio(in IBinder token, float aspectRatio);
+ void enterPictureInPictureModeOnMoveToBackground(in IBinder token,
+ boolean enterPictureInPictureOnMoveToBg);
+ void setPictureInPictureAspectRatio(in IBinder token, float aspectRatio);
void activityRelaunched(in IBinder token);
IBinder getUriPermissionOwnerForActivity(in IBinder activityToken);
/**
@@ -569,14 +574,12 @@
boolean updateDisplayOverrideConfiguration(in Configuration values, int displayId);
void unregisterTaskStackListener(ITaskStackListener listener);
void moveStackToDisplay(int stackId, int displayId);
- void enterPictureInPictureModeWithAspectRatio(in IBinder token, float aspectRatio);
- void setPictureInPictureAspectRatio(in IBinder token, float aspectRatio);
boolean requestAutoFillData(in IResultReceiver receiver, in Bundle receiverExtras,
- in IBinder activityToken);
+ in IBinder activityToken, int flags);
void dismissKeyguard(in IBinder token, in IKeyguardDismissCallback callback);
// WARNING: when these transactions are updated, check if they are any callers on the native
- // side. If so, make sure they are using the correct transaction ids.
+ // side. If so, make sure they are using the correct transaction ids and arguments.
// If a transaction which will also be used on the native side is being inserted, add it
// alongside with other transactions of this kind at the top of this file.
-}
\ No newline at end of file
+}
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 6b962b9..7f168c9 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -134,7 +134,7 @@
void dumpDbInfo(in ParcelFileDescriptor fd, in String[] args);
void unstableProviderDied(IBinder provider);
void requestAssistContextExtras(IBinder activityToken, IBinder requestToken,
- int requestType, int sessionId);
+ int requestType, int sessionId, int flags);
void scheduleTranslucentConversionComplete(IBinder token, boolean timeout);
void setProcessState(int state);
void scheduleInstallProvider(in ProviderInfo provider);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 927ef6c..2c4e7a0 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -99,8 +99,12 @@
void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim);
void setInterruptionFilter(String pkg, int interruptionFilter);
- void applyAdjustmentFromAssistantService(in INotificationListener token, in Adjustment adjustment);
- void applyAdjustmentsFromAssistantService(in INotificationListener token, in List<Adjustment> adjustments);
+ void applyAdjustmentFromAssistant(in INotificationListener token, in Adjustment adjustment);
+ void applyAdjustmentsFromAssistant(in INotificationListener token, in List<Adjustment> adjustments);
+ void createNotificationChannelFromAssistant(in INotificationListener token, String pkg, in NotificationChannel channel);
+ void updateNotificationChannelFromAssistant(in INotificationListener token, String pkg, in NotificationChannel channel);
+ void deleteNotificationChannelFromAssistant(in INotificationListener token, String pkg, String channelId);
+ ParceledListSlice getNotificationChannelsFromAssistant(in INotificationListener token, String pkg);
ComponentName getEffectsSuppressor();
boolean matchesCallFilter(in Bundle extras);
diff --git a/core/java/android/app/MediaRouteActionProvider.java b/core/java/android/app/MediaRouteActionProvider.java
index dffa969..85ca012 100644
--- a/core/java/android/app/MediaRouteActionProvider.java
+++ b/core/java/android/app/MediaRouteActionProvider.java
@@ -119,7 +119,6 @@
}
mButton = new MediaRouteButton(mContext);
- mButton.setCheatSheetEnabled(true);
mButton.setRouteTypes(mRouteTypes);
mButton.setExtendedSettingsClickListener(mExtendedSettingsListener);
mButton.setLayoutParams(new ViewGroup.LayoutParams(
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
index 70a5e15..09e95df 100644
--- a/core/java/android/app/MediaRouteButton.java
+++ b/core/java/android/app/MediaRouteButton.java
@@ -24,18 +24,13 @@
import android.content.ContextWrapper;
import android.content.res.TypedArray;
import android.graphics.Canvas;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.media.MediaRouter;
import android.media.MediaRouter.RouteGroup;
import android.media.MediaRouter.RouteInfo;
-import android.text.TextUtils;
import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.HapticFeedbackConstants;
import android.view.SoundEffectConstants;
import android.view.View;
-import android.widget.Toast;
public class MediaRouteButton extends View {
private final MediaRouter mRouter;
@@ -47,7 +42,6 @@
private Drawable mRemoteIndicator;
private boolean mRemoteActive;
- private boolean mCheatSheetEnabled;
private boolean mIsConnecting;
private int mMinWidth;
@@ -98,7 +92,6 @@
a.recycle();
setClickable(true);
- setLongClickable(true);
setRouteTypes(routeTypes);
}
@@ -178,12 +171,10 @@
throw new IllegalStateException("The MediaRouteButton's Context is not an Activity.");
}
- /**
- * Sets whether to enable showing a toast with the content descriptor of the
- * button when the button is long pressed.
- */
- void setCheatSheetEnabled(boolean enable) {
- mCheatSheetEnabled = enable;
+ @Override
+ public void setContentDescription(CharSequence contentDescription) {
+ super.setContentDescription(contentDescription);
+ setTooltip(contentDescription);
}
@Override
@@ -197,47 +188,6 @@
}
@Override
- public boolean performLongClick() {
- if (super.performLongClick()) {
- return true;
- }
-
- if (!mCheatSheetEnabled) {
- return false;
- }
-
- final CharSequence contentDesc = getContentDescription();
- if (TextUtils.isEmpty(contentDesc)) {
- // Don't show the cheat sheet if we have no description
- return false;
- }
-
- final int[] screenPos = new int[2];
- final Rect displayFrame = new Rect();
- getLocationOnScreen(screenPos);
- getWindowVisibleDisplayFrame(displayFrame);
-
- final Context context = getContext();
- final int width = getWidth();
- final int height = getHeight();
- final int midy = screenPos[1] + height / 2;
- final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
-
- Toast cheatSheet = Toast.makeText(context, contentDesc, Toast.LENGTH_SHORT);
- if (midy < displayFrame.height()) {
- // Show along the top; follow action buttons
- cheatSheet.setGravity(Gravity.TOP | Gravity.END,
- screenWidth - screenPos[0] - width / 2, height);
- } else {
- // Show along the bottom center
- cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
- }
- cheatSheet.show();
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- return true;
- }
-
- @Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 1fd082f4..c1e2072 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -37,6 +37,7 @@
import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
import android.media.AudioManager;
+import android.media.PlayerBase;
import android.media.session.MediaSession;
import android.net.Uri;
import android.os.BadParcelableException;
@@ -2821,6 +2822,7 @@
*/
@Deprecated
public Builder setSound(Uri sound, int streamType) {
+ PlayerBase.deprecateStreamTypeForPlayback(streamType, "Notification", "setSound()");
mN.sound = sound;
mN.audioStreamType = streamType;
return this;
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index c1180e2..f273cd8 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -26,6 +26,8 @@
import android.util.Log;
import com.google.android.collect.Maps;
+
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.XmlUtils;
import dalvik.system.BlockGuard;
@@ -72,6 +74,14 @@
private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
+ /** Current memory state (always increasing) */
+ @GuardedBy("this")
+ private long mCurrentMemoryStateGeneration;
+
+ /** Latest memory state that was committed to disk */
+ @GuardedBy("mWritingToDiskLock")
+ private long mDiskStateGeneration;
+
SharedPreferencesImpl(File file, int mode) {
mFile = file;
mBackupFile = makeBackupFile(file);
@@ -289,7 +299,7 @@
// Return value from EditorImpl#commitToMemory()
private static class MemoryCommitResult {
- public boolean changesMade; // any keys different?
+ public long memoryStateGeneration;
public List<String> keysModified; // may be null
public Set<OnSharedPreferenceChangeListener> listeners; // may be null
public Map<?, ?> mapToWriteToDisk;
@@ -412,9 +422,11 @@
}
synchronized (this) {
+ boolean changesMade = false;
+
if (mClear) {
if (!mMap.isEmpty()) {
- mcr.changesMade = true;
+ changesMade = true;
mMap.clear();
}
mClear = false;
@@ -441,13 +453,19 @@
mMap.put(k, v);
}
- mcr.changesMade = true;
+ changesMade = true;
if (hasListeners) {
mcr.keysModified.add(k);
}
}
mModified.clear();
+
+ if (changesMade) {
+ mCurrentMemoryStateGeneration++;
+ }
+
+ mcr.memoryStateGeneration = mCurrentMemoryStateGeneration;
}
}
return mcr;
@@ -509,10 +527,12 @@
*/
private void enqueueDiskWrite(final MemoryCommitResult mcr,
final Runnable postWriteRunnable) {
+ final boolean isFromSyncCommit = (postWriteRunnable == null);
+
final Runnable writeToDiskRunnable = new Runnable() {
public void run() {
synchronized (mWritingToDiskLock) {
- writeToFile(mcr);
+ writeToFile(mcr, isFromSyncCommit);
}
synchronized (SharedPreferencesImpl.this) {
mDiskWritesInFlight--;
@@ -523,8 +543,6 @@
}
};
- final boolean isFromSyncCommit = (postWriteRunnable == null);
-
// Typical #commit() path with fewer allocations, doing a write on
// the current thread.
if (isFromSyncCommit) {
@@ -538,6 +556,10 @@
}
}
+ if (DEBUG) {
+ Log.d(TAG, "added " + mcr.memoryStateGeneration + " -> " + mFile.getName());
+ }
+
QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
}
@@ -565,17 +587,34 @@
}
// Note: must hold mWritingToDiskLock
- private void writeToFile(MemoryCommitResult mcr) {
+ private void writeToFile(MemoryCommitResult mcr, boolean isFromSyncCommit) {
// Rename the current file so it may be used as a backup during the next read
if (mFile.exists()) {
- if (!mcr.changesMade) {
- // If the file already exists, but no changes were
- // made to the underlying map, it's wasteful to
- // re-write the file. Return as if we wrote it
- // out.
+ boolean needsWrite = false;
+
+ // Only need to write if the disk state is older than this commit
+ if (mDiskStateGeneration < mcr.memoryStateGeneration) {
+ if (isFromSyncCommit) {
+ needsWrite = true;
+ } else {
+ synchronized (this) {
+ // No need to persist intermediate states. Just wait for the latest state to
+ // be persisted.
+ if (mCurrentMemoryStateGeneration == mcr.memoryStateGeneration) {
+ needsWrite = true;
+ }
+ }
+ }
+ }
+
+ if (!needsWrite) {
+ if (DEBUG) {
+ Log.d(TAG, "skipped " + mcr.memoryStateGeneration + " -> " + mFile.getName());
+ }
mcr.setDiskWriteResult(true);
return;
}
+
if (!mBackupFile.exists()) {
if (!mFile.renameTo(mBackupFile)) {
Log.e(TAG, "Couldn't rename file " + mFile
@@ -599,6 +638,11 @@
}
XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
FileUtils.sync(str);
+
+ if (DEBUG) {
+ Log.d(TAG, "wrote " + mcr.memoryStateGeneration + " -> " + mFile.getName());
+ }
+
str.close();
ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
try {
@@ -612,7 +656,11 @@
}
// Writing was successful, delete the backup file if there is one.
mBackupFile.delete();
+
+ mDiskStateGeneration = mcr.memoryStateGeneration;
+
mcr.setDiskWriteResult(true);
+
return;
} catch (XmlPullParserException e) {
Log.w(TAG, "writeToFile: Got exception:", e);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 67ce342..e1bd93e 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -115,6 +115,7 @@
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.text.TextClassificationManager;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
@@ -221,6 +222,13 @@
return new HdmiControlManager(IHdmiControlService.Stub.asInterface(b));
}});
+ registerService(Context.TEXT_CLASSIFICATION_SERVICE, TextClassificationManager.class,
+ new StaticServiceFetcher<TextClassificationManager>() {
+ @Override
+ public TextClassificationManager createService() {
+ return new TextClassificationManager();
+ }});
+
registerService(Context.CLIPBOARD_SERVICE, ClipboardManager.class,
new CachedServiceFetcher<ClipboardManager>() {
@Override
diff --git a/core/java/android/app/admin/ConnectEvent.java b/core/java/android/app/admin/ConnectEvent.java
index c1646bb..5111443 100644
--- a/core/java/android/app/admin/ConnectEvent.java
+++ b/core/java/android/app/admin/ConnectEvent.java
@@ -21,7 +21,6 @@
/**
* A class that represents a connect library call event.
- * @hide
*/
public final class ConnectEvent extends NetworkEvent implements Parcelable {
@@ -31,6 +30,7 @@
/** The destination port number. */
private final int port;
+ /** @hide */
public ConnectEvent(String ipAddress, int port, String packageName, long timestamp) {
super(packageName, timestamp);
this.ipAddress = ipAddress;
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index b1eca5c..aae80ed 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -702,8 +702,6 @@
* @param batchToken The token representing the current batch of network logs.
* @param networkLogsCount The total count of events in the current batch of network logs.
* @see DevicePolicyManager#retrieveNetworkLogs(ComponentName)
- *
- * @hide
*/
public void onNetworkLogsAvailable(Context context, Intent intent, long batchToken,
int networkLogsCount) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 39c8b79..f77bed0 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -151,6 +151,7 @@
* <li>{@link #EXTRA_PROVISIONING_LOGO_URI}, optional</li>
* <li>{@link #EXTRA_PROVISIONING_MAIN_COLOR}, optional</li>
* <li>{@link #EXTRA_PROVISIONING_SKIP_USER_CONSENT}, optional</li>
+ * <li>{@link #EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION}, optional</li>
* </ul>
*
* <p>When managed provisioning has completed, broadcasts are sent to the application specified
@@ -513,6 +514,20 @@
= "android.app.extra.PROVISIONING_ACCOUNT_TO_MIGRATE";
/**
+ * Boolean extra to indicate that the migrated account should be kept. This is used in
+ * conjunction with {@link #EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE}. If it's set to {@code true},
+ * the account will not be removed from the primary user after it is migrated to the newly
+ * created user or profile.
+ *
+ * <p> Defaults to {@code false}
+ *
+ * <p> Use with {@link #ACTION_PROVISION_MANAGED_PROFILE} and
+ * {@link #EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE}
+ */
+ public static final String EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION
+ = "android.app.extra.PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION";
+
+ /**
* A String extra that, holds the email address of the account which a managed profile is
* created for. Used with {@link #ACTION_PROVISION_MANAGED_PROFILE} and
* {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}.
@@ -1095,6 +1110,172 @@
public @interface UserProvisioningState {}
/**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
+ * {@link #ACTION_PROVISION_MANAGED_PROFILE}, {@link #ACTION_PROVISION_MANAGED_USER} and
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when provisioning is allowed.
+ *
+ * @hide
+ */
+ public static final int CODE_OK = 0;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE} and
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when the device already has a device
+ * owner.
+ *
+ * @hide
+ */
+ public static final int CODE_HAS_DEVICE_OWNER = 1;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when the user has a profile owner and for
+ * {@link #ACTION_PROVISION_MANAGED_PROFILE} when the profile owner is already set.
+ *
+ * @hide
+ */
+ public static final int CODE_USER_HAS_PROFILE_OWNER = 2;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE} and
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} when the user isn't running.
+ *
+ * @hide
+ */
+ public static final int CODE_USER_NOT_RUNNING = 3;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} if the device has already been setup and
+ * for {@link #ACTION_PROVISION_MANAGED_USER} if the user has already been setup.
+ *
+ * @hide
+ */
+ public static final int CODE_USER_SETUP_COMPLETED = 4;
+
+ /**
+ * Code used to indicate that the device also has a user other than the system user.
+ *
+ * @hide
+ */
+ public static final int CODE_NONSYSTEM_USER_EXISTS = 5;
+
+ /**
+ * Code used to indicate that device has an account that prevents provisioning.
+ *
+ * @hide
+ */
+ public static final int CODE_ACCOUNTS_NOT_EMPTY = 6;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE} and
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} if the user is not a system user.
+ *
+ * @hide
+ */
+ public static final int CODE_NOT_SYSTEM_USER = 7;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} and {@link #ACTION_PROVISION_MANAGED_USER}
+ * when the device is a watch and is already paired.
+ *
+ * @hide
+ */
+ public static final int CODE_HAS_PAIRED = 8;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} and
+ * {@link #ACTION_PROVISION_MANAGED_USER} on devices which do not support managed users.
+ *
+ * @see {@link PackageManager#FEATURE_MANAGED_USERS}
+ * @hide
+ */
+ public static final int CODE_MANAGED_USERS_NOT_SUPPORTED = 9;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_USER} if the user is a system user.
+ *
+ * @hide
+ */
+ public static final int CODE_SYSTEM_USER = 10;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} when the user cannot have more
+ * managed profiles.
+ *
+ * @hide
+ */
+ public static final int CODE_CANNOT_ADD_MANAGED_PROFILE = 11;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_USER} and
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} on devices not running with split system
+ * user.
+ *
+ * @hide
+ */
+ public static final int CODE_NOT_SYSTEM_USER_SPLIT = 12;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE},
+ * {@link #ACTION_PROVISION_MANAGED_PROFILE}, {@link #ACTION_PROVISION_MANAGED_USER} and
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE} on devices which do no support device
+ * admins.
+ *
+ * @hide
+ */
+ public static final int CODE_DEVICE_ADMIN_NOT_SUPPORTED = 13;
+
+ /**
+ * Result code for {@link checkProvisioningPreCondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} when the device the user is a
+ * system user on a split system user device.
+ *
+ * @hide
+ */
+ public static final int CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER = 14;
+
+ /**
+ * Result codes for {@link checkProvisioningPreCondition} indicating all the provisioning pre
+ * conditions.
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({CODE_OK, CODE_HAS_DEVICE_OWNER, CODE_USER_HAS_PROFILE_OWNER, CODE_USER_NOT_RUNNING,
+ CODE_USER_SETUP_COMPLETED, CODE_NOT_SYSTEM_USER, CODE_HAS_PAIRED,
+ CODE_MANAGED_USERS_NOT_SUPPORTED, CODE_SYSTEM_USER, CODE_CANNOT_ADD_MANAGED_PROFILE,
+ CODE_NOT_SYSTEM_USER_SPLIT, CODE_DEVICE_ADMIN_NOT_SUPPORTED,
+ CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER})
+ public @interface ProvisioningPreCondition {}
+
+ /**
* Return true if the given administrator component is currently active (enabled) in the system.
*
* @param admin The administrator component to check for.
@@ -5964,6 +6145,24 @@
}
/**
+ * Checks if provisioning a managed profile or device is possible and returns one of the
+ * {@link ProvisioningPreCondition}.
+ *
+ * @param action One of {@link #ACTION_PROVISION_MANAGED_DEVICE},
+ * {@link #ACTION_PROVISION_MANAGED_PROFILE},
+ * {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE},
+ * {@link #ACTION_PROVISION_MANAGED_USER}
+ * @hide
+ */
+ public @ProvisioningPreCondition int checkProvisioningPreCondition(String action) {
+ try {
+ return mService.checkProvisioningPreCondition(action);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Return if this user is a managed profile of another user. An admin can become the profile
* owner of a managed profile with {@link #ACTION_PROVISION_MANAGED_PROFILE} and of a managed
* user with {@link #createAndManageUser}
@@ -6628,10 +6827,13 @@
}
/**
+ * Returns whether the device has been provisioned.
+ *
+ * <p>Not for use by third-party applications.
+ *
* @hide
- * @return whether {@link android.provider.Settings.Global#DEVICE_PROVISIONED} has ever been set
- * to 1.
*/
+ @SystemApi
public boolean isDeviceProvisioned() {
try {
return mService.isDeviceProvisioned();
@@ -6641,9 +6843,16 @@
}
/**
- * @hide
- * Writes that the provisioning configuration has been applied.
- */
+ * Writes that the provisioning configuration has been applied.
+ *
+ * <p>The caller must hold the {@link android.Manifest.permission#MANAGE_USERS}
+ * permission.
+ *
+ * <p>Not for use by third-party applications.
+ *
+ * @hide
+ */
+ @SystemApi
public void setDeviceProvisioningConfigApplied() {
try {
mService.setDeviceProvisioningConfigApplied();
@@ -6653,9 +6862,17 @@
}
/**
- * @hide
+ * Returns whether the provisioning configuration has been applied.
+ *
+ * <p>The caller must hold the {@link android.Manifest.permission#MANAGE_USERS} permission.
+ *
+ * <p>Not for use by third-party applications.
+ *
* @return whether the provisioning configuration has been applied.
+ *
+ * @hide
*/
+ @SystemApi
public boolean isDeviceProvisioningConfigApplied() {
try {
return mService.isDeviceProvisioningConfigApplied();
@@ -6727,8 +6944,6 @@
* @param enabled whether network logging should be enabled or not.
* @throws {@link SecurityException} if {@code admin} is not a device owner.
* @see #retrieveNetworkLogs
- *
- * @hide
*/
public void setNetworkLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
throwIfParentInstance("setNetworkLoggingEnabled");
@@ -6742,13 +6957,13 @@
/**
* Return whether network logging is enabled by a device owner.
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Can only
+ * be {@code null} if the caller has MANAGE_USERS permission.
* @return {@code true} if network logging is enabled by device owner, {@code false} otherwise.
- * @throws {@link SecurityException} if {@code admin} is not a device owner.
- *
- * @hide
+ * @throws {@link SecurityException} if {@code admin} is not a device owner and caller has
+ * no MANAGE_USERS permission
*/
- public boolean isNetworkLoggingEnabled(@NonNull ComponentName admin) {
+ public boolean isNetworkLoggingEnabled(@Nullable ComponentName admin) {
throwIfParentInstance("isNetworkLoggingEnabled");
try {
return mService.isNetworkLoggingEnabled(admin);
@@ -6778,8 +6993,6 @@
* logging is disabled.
* @throws {@link SecurityException} if {@code admin} is not a device owner.
* @see DeviceAdminReceiver#onNetworkLogsAvailable
- *
- * @hide
*/
public @Nullable List<NetworkEvent> retrieveNetworkLogs(@NonNull ComponentName admin,
long batchToken) {
diff --git a/core/java/android/app/admin/DnsEvent.java b/core/java/android/app/admin/DnsEvent.java
index 63ea8db..a3a3f58 100644
--- a/core/java/android/app/admin/DnsEvent.java
+++ b/core/java/android/app/admin/DnsEvent.java
@@ -21,7 +21,6 @@
/**
* A class that represents a DNS lookup event.
- * @hide
*/
public final class DnsEvent extends NetworkEvent implements Parcelable {
@@ -37,6 +36,7 @@
*/
private final int ipAddressesCount;
+ /** @hide */
public DnsEvent(String hostname, String[] ipAddresses, int ipAddressesCount,
String packageName, long timestamp) {
super(packageName, timestamp);
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index f303bbc..3e22825 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -270,6 +270,7 @@
String permission, int grantState);
int getPermissionGrantState(in ComponentName admin, String packageName, String permission);
boolean isProvisioningAllowed(String action);
+ int checkProvisioningPreCondition(String action);
void setKeepUninstalledPackages(in ComponentName admin,in List<String> packageList);
List<String> getKeepUninstalledPackages(in ComponentName admin);
boolean isManagedProfile(in ComponentName admin);
diff --git a/core/java/android/app/admin/NetworkEvent.java b/core/java/android/app/admin/NetworkEvent.java
index 1dbff20..2646c3f 100644
--- a/core/java/android/app/admin/NetworkEvent.java
+++ b/core/java/android/app/admin/NetworkEvent.java
@@ -16,17 +16,19 @@
package android.app.admin;
+import android.content.pm.PackageManager;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.ParcelFormatException;
/**
* An abstract class that represents a network event.
- * @hide
*/
public abstract class NetworkEvent implements Parcelable {
+ /** @hide */
static final int PARCEL_TOKEN_DNS_EVENT = 1;
+ /** @hide */
static final int PARCEL_TOKEN_CONNECT_EVENT = 2;
/** The package name of the UID that performed the query. */
@@ -35,21 +37,29 @@
/** The timestamp of the event being reported in milliseconds. */
long timestamp;
- protected NetworkEvent() {
+ /** @hide */
+ NetworkEvent() {
//empty constructor
}
- protected NetworkEvent(String packageName, long timestamp) {
+ /** @hide */
+ NetworkEvent(String packageName, long timestamp) {
this.packageName = packageName;
this.timestamp = timestamp;
}
- /** Returns the package name of the UID that performed the query. */
+ /**
+ * Returns the package name of the UID that performed the query, as returned by
+ * {@link PackageManager#getNameForUid}.
+ */
public String getPackageName() {
return packageName;
}
- /** Returns the timestamp of the event being reported in milliseconds. */
+ /**
+ * Returns the timestamp of the event being reported in milliseconds, the difference between
+ * the time the event was reported and midnight, January 1, 1970 UTC.
+ */
public long getTimestamp() {
return timestamp;
}
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index a6f2366..1988e42 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -400,7 +400,7 @@
final int mDisplayId;
final ViewNode mRoot;
- WindowNode(AssistStructure assist, ViewRootImpl root) {
+ WindowNode(AssistStructure assist, ViewRootImpl root, int flags) {
View view = root.getView();
Rect rect = new Rect();
view.getBoundsOnScreen(rect);
@@ -415,11 +415,22 @@
if ((root.getWindowFlags()& WindowManager.LayoutParams.FLAG_SECURE) != 0) {
// This is a secure window, so it doesn't want a screenshot, and that
// means we should also not copy out its view hierarchy.
- view.onProvideStructure(builder);
+
+ // Must explicitly set which method to calls since View subclasses might
+ // have implemented the deprecated method.
+ if (flags == 0) {
+ view.onProvideStructure(builder);
+ } else {
+ view.onProvideStructure(builder, flags);
+ }
builder.setAssistBlocked(true);
return;
}
- view.dispatchProvideStructure(builder);
+ if (flags == 0) {
+ view.dispatchProvideStructure(builder);
+ } else {
+ view.dispatchProvideStructure(builder, flags);
+ }
}
WindowNode(ParcelTransferReader reader) {
@@ -1351,14 +1362,14 @@
}
/** @hide */
- public AssistStructure(Activity activity) {
+ public AssistStructure(Activity activity, int flags) {
mHaveData = true;
mActivityComponent = activity.getComponentName();
ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
activity.getActivityToken());
for (int i=0; i<views.size(); i++) {
ViewRootImpl root = views.get(i);
- mWindowNodes.add(new WindowNode(this, root));
+ mWindowNodes.add(new WindowNode(this, root, flags));
}
}
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index 342c285..31b2359 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -34,4 +34,6 @@
boolean isAppInactive(String packageName, int userId);
void whitelistAppTemporarily(String packageName, long duration, int userId);
void onCarrierPrivilegedAppsChanged();
+ void reportChooserSelection(String packageName, int userId, String contentType,
+ in String[] annotations, String action);
}
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index a0da258..ce8b05a 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -86,6 +86,12 @@
public static final int SHORTCUT_INVOCATION = 8;
/**
+ * An event type denoting that a package was selected by the user for ChooserActivity.
+ * @hide
+ */
+ public static final int CHOOSER_ACTION = 9;
+
+ /**
* {@hide}
*/
public String mPackage;
@@ -119,6 +125,27 @@
public String mShortcutId;
/**
+ * Action type passed to ChooserActivity
+ * Only present for {@link #CHOOSER_ACTION} event types.
+ * {@hide}
+ */
+ public String mAction;
+
+ /**
+ * Content type passed to ChooserActivity.
+ * Only present for {@link #CHOOSER_ACTION} event types.
+ * {@hide}
+ */
+ public String mContentType;
+
+ /**
+ * Content annotations passed to ChooserActivity.
+ * Only present for {@link #CHOOSER_ACTION} event types.
+ * {@hide}
+ */
+ public String[] mContentAnnotations;
+
+ /**
* The package name of the source of this event.
*/
public String getPackageName() {
@@ -307,6 +334,11 @@
case Event.SHORTCUT_INVOCATION:
p.writeString(event.mShortcutId);
break;
+ case Event.CHOOSER_ACTION:
+ p.writeString(event.mAction);
+ p.writeString(event.mContentType);
+ p.writeStringArray(event.mContentAnnotations);
+ break;
}
}
@@ -333,6 +365,9 @@
// Fill out the event-dependant fields.
eventOut.mConfiguration = null;
eventOut.mShortcutId = null;
+ eventOut.mAction = null;
+ eventOut.mContentType = null;
+ eventOut.mContentAnnotations = null;
switch (eventOut.mEventType) {
case Event.CONFIGURATION_CHANGE:
@@ -342,6 +377,11 @@
case Event.SHORTCUT_INVOCATION:
eventOut.mShortcutId = p.readString();
break;
+ case Event.CHOOSER_ACTION:
+ eventOut.mAction = p.readString();
+ eventOut.mContentType = p.readString();
+ eventOut.mContentAnnotations = p.createStringArray();
+ break;
}
}
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 2937ccc..57f18f1 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -16,8 +16,10 @@
package android.app.usage;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.ArrayMap;
/**
* Contains usage statistics for an app package for a specific
@@ -64,6 +66,11 @@
/**
* {@hide}
*/
+ public ArrayMap<String, ArrayMap<String, Integer>> mChooserCounts;
+
+ /**
+ * {@hide}
+ */
public UsageStats() {
}
@@ -75,6 +82,7 @@
mTotalTimeInForeground = stats.mTotalTimeInForeground;
mLaunchCount = stats.mLaunchCount;
mLastEvent = stats.mLastEvent;
+ mChooserCounts = stats.mChooserCounts;
}
public String getPackageName() {
@@ -142,6 +150,26 @@
mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
mTotalTimeInForeground += right.mTotalTimeInForeground;
mLaunchCount += right.mLaunchCount;
+ if (mChooserCounts == null) {
+ mChooserCounts = right.mChooserCounts;
+ } else if (right.mChooserCounts != null) {
+ final int chooserCountsSize = right.mChooserCounts.size();
+ for (int i = 0; i < chooserCountsSize; i++) {
+ String action = right.mChooserCounts.keyAt(i);
+ ArrayMap<String, Integer> counts = right.mChooserCounts.valueAt(i);
+ if (!mChooserCounts.containsKey(action) || mChooserCounts.get(action) == null) {
+ mChooserCounts.put(action, counts);
+ continue;
+ }
+ final int annotationSize = counts.size();
+ for (int j = 0; j < annotationSize; j++) {
+ String key = counts.keyAt(j);
+ int rightValue = counts.valueAt(j);
+ int leftValue = mChooserCounts.get(action).getOrDefault(key, 0);
+ mChooserCounts.get(action).put(key, leftValue + rightValue);
+ }
+ }
+ }
}
@Override
@@ -158,6 +186,21 @@
dest.writeLong(mTotalTimeInForeground);
dest.writeInt(mLaunchCount);
dest.writeInt(mLastEvent);
+ Bundle allCounts = new Bundle();
+ if (mChooserCounts != null) {
+ final int chooserCountSize = mChooserCounts.size();
+ for (int i = 0; i < chooserCountSize; i++) {
+ String action = mChooserCounts.keyAt(i);
+ ArrayMap<String, Integer> counts = mChooserCounts.valueAt(i);
+ Bundle currentCounts = new Bundle();
+ final int annotationSize = counts.size();
+ for (int j = 0; j < annotationSize; j++) {
+ currentCounts.putInt(counts.keyAt(j), counts.valueAt(j));
+ }
+ allCounts.putBundle(action, currentCounts);
+ }
+ }
+ dest.writeBundle(allCounts);
}
public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() {
@@ -171,6 +214,25 @@
stats.mTotalTimeInForeground = in.readLong();
stats.mLaunchCount = in.readInt();
stats.mLastEvent = in.readInt();
+ Bundle allCounts = in.readBundle();
+ if (allCounts != null) {
+ stats.mChooserCounts = new ArrayMap<>();
+ for (String action : allCounts.keySet()) {
+ if (!stats.mChooserCounts.containsKey(action)) {
+ ArrayMap<String, Integer> newCounts = new ArrayMap<>();
+ stats.mChooserCounts.put(action, newCounts);
+ }
+ Bundle currentCounts = allCounts.getBundle(action);
+ if (currentCounts != null) {
+ for (String key : currentCounts.keySet()) {
+ int value = currentCounts.getInt(key);
+ if (value > 0) {
+ stats.mChooserCounts.get(action).put(key, value);
+ }
+ }
+ }
+ }
+ }
return stats;
}
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 2aeecfa..75a4a53 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -278,4 +278,23 @@
} catch (RemoteException re) {
}
}
+
+ /**
+ * Reports a Chooser action to the UsageStatsManager.
+ *
+ * @param packageName The package name of the app that is selected.
+ * @param userId The user id of who makes the selection.
+ * @param contentType The type of the content, e.g., Image, Video, App.
+ * @param annotations The annotations of the content, e.g., Game, Selfie.
+ * @param action The action type of Intent that invokes ChooserActivity.
+ * {@link UsageEvents}
+ * @hide
+ */
+ public void reportChooserSelection(String packageName, int userId, String contentType,
+ String[] annotations, String action) {
+ try {
+ mService.reportChooserSelection(packageName, userId, contentType, annotations, action);
+ } catch (RemoteException re) {
+ }
+ }
}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index f369409..cda98e5 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -97,6 +97,7 @@
* developer guide.</p>
*/
public abstract class ContentProvider implements ComponentCallbacks2 {
+
private static final String TAG = "ContentProvider";
/*
@@ -118,7 +119,7 @@
private boolean mNoPerms;
private boolean mSingleUser;
- private final ThreadLocal<String> mCallingPackage = new ThreadLocal<String>();
+ private final ThreadLocal<String> mCallingPackage = new ThreadLocal<>();
private Transport mTransport = new Transport();
@@ -205,9 +206,8 @@
}
@Override
- public Cursor query(String callingPkg, Uri uri, String[] projection,
- String selection, String[] selectionArgs, String sortOrder,
- ICancellationSignal cancellationSignal) {
+ public Cursor query(String callingPkg, Uri uri, @Nullable String[] projection,
+ @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) {
validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
@@ -225,9 +225,9 @@
// However, the caller may be expecting to access them my index. Hence,
// we have to execute the query as if allowed to get a cursor with the
// columns. We then use the column names to return an empty cursor.
- Cursor cursor = ContentProvider.this.query(uri, projection, selection,
- selectionArgs, sortOrder, CancellationSignal.fromTransport(
- cancellationSignal));
+ Cursor cursor = ContentProvider.this.query(
+ uri, projection, queryArgs,
+ CancellationSignal.fromTransport(cancellationSignal));
if (cursor == null) {
return null;
}
@@ -238,7 +238,7 @@
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.query(
- uri, projection, selection, selectionArgs, sortOrder,
+ uri, projection, queryArgs,
CancellationSignal.fromTransport(cancellationSignal));
} finally {
setCallingPackage(original);
@@ -893,6 +893,7 @@
* (Content providers do not usually care about things like screen
* orientation, but may want to know about locale changes.)
*/
+ @Override
public void onConfigurationChanged(Configuration newConfig) {
}
@@ -904,9 +905,11 @@
* <p>The default content provider implementation does nothing.
* Subclasses may override this method to take appropriate action.
*/
+ @Override
public void onLowMemory() {
}
+ @Override
public void onTrimMemory(int level) {
}
@@ -1039,6 +1042,45 @@
}
/**
+ * Implement this to handle query requests where the arguments are packed into a {@link Bundle}.
+ * Arguments may include traditional SQL style query arguments. When present these
+ * should be handled according to the contract established in
+ * {@link #query(Uri, String[], String, String[], String, CancellationSignal).
+ *
+ * <p>Traditional SQL arguments can be found in the bundle using the following keys:
+ * <li>{@link ContentResolver#QUERY_ARG_SELECTION}
+ * <li>{@link ContentResolver#QUERY_ARG_SELECTION_ARGS}
+ * <li>{@link ContentResolver#QUERY_ARG_SORT_ORDER}
+ *
+ * @see #query(Uri, String[], String, String[], String, CancellationSignal) for
+ * implementation details.
+ *
+ * @param uri The URI to query. This will be the full URI sent by the client.
+ * TODO: Me wonders about this use case, and how we adapt it.
+ * If the client is requesting a specific record, the URI will end
+ * in a record number that the implementation should parse and add
+ * to a WHERE or HAVING clause, specifying that _id value.
+ * @param projection The list of columns to put into the cursor.
+ * If {@code null} provide a default set of columns.
+ * @param queryArgs A Bundle containing all additional information necessary for the query.
+ * Values in the Bundle may include SQL style arguments.
+ * @param cancellationSignal A signal to cancel the operation in progress,
+ * or {@code null}.
+ * @return a Cursor or {@code null}.
+ */
+ public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+ @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal) {
+ queryArgs = queryArgs != null ? queryArgs : Bundle.EMPTY;
+ return query(
+ uri,
+ projection,
+ queryArgs.getString(ContentResolver.QUERY_ARG_SELECTION),
+ queryArgs.getStringArray(ContentResolver.QUERY_ARG_SELECTION_ARGS),
+ queryArgs.getString(ContentResolver.QUERY_ARG_SORT_ORDER),
+ cancellationSignal);
+ }
+
+ /**
* Implement this to handle requests for the MIME type of the data at the
* given URI. The returned MIME type should start with
* <code>vnd.android.cursor.item</code> for a single record,
@@ -1412,7 +1454,7 @@
* no file associated with the given URI or the mode is invalid.
* @throws SecurityException Throws SecurityException if the caller does
* not have permission to access the file.
- *
+ *
* @see #openFile(Uri, String)
* @see #openFileHelper(Uri, String)
* @see #getType(android.net.Uri)
@@ -1851,7 +1893,7 @@
/**
* Implement this to shut down the ContentProvider instance. You can then
* invoke this method in unit tests.
- *
+ *
* <p>
* Android normally handles ContentProvider startup and shutdown
* automatically. You do not need to start up or shut down a
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index fd6cddb..732666f 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -128,11 +128,20 @@
}
/** See {@link ContentProvider#query ContentProvider.query} */
- public @Nullable Cursor query(@NonNull Uri url, @Nullable String[] projection,
+ public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
@Nullable String selection, @Nullable String[] selectionArgs,
@Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal)
throws RemoteException {
- Preconditions.checkNotNull(url, "url");
+ Bundle queryArgs =
+ ContentResolver.createSqlQueryBundle(selection, selectionArgs, sortOrder);
+ return query(uri, projection, queryArgs, cancellationSignal);
+ }
+
+ /** See {@link ContentProvider#query ContentProvider.query} */
+ public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+ Bundle queryArgs, @Nullable CancellationSignal cancellationSignal)
+ throws RemoteException {
+ Preconditions.checkNotNull(uri, "url");
beforeRemote();
try {
@@ -142,8 +151,8 @@
remoteCancellationSignal = mContentProvider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
- final Cursor cursor = mContentProvider.query(mPackageName, url, projection, selection,
- selectionArgs, sortOrder, remoteCancellationSignal);
+ final Cursor cursor = mContentProvider.query(
+ mPackageName, uri, projection, queryArgs, remoteCancellationSignal);
if (cursor == null) {
return null;
}
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index eadc013..d428a3a 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -16,6 +16,7 @@
package android.content;
+import android.annotation.Nullable;
import android.content.res.AssetFileDescriptor;
import android.database.BulkCursorDescriptor;
import android.database.BulkCursorToCursorAdaptor;
@@ -92,25 +93,13 @@
}
}
- // String selection, String[] selectionArgs...
- String selection = data.readString();
- num = data.readInt();
- String[] selectionArgs = null;
- if (num > 0) {
- selectionArgs = new String[num];
- for (int i = 0; i < num; i++) {
- selectionArgs[i] = data.readString();
- }
- }
-
- String sortOrder = data.readString();
+ Bundle queryArgs = data.readBundle();
IContentObserver observer = IContentObserver.Stub.asInterface(
data.readStrongBinder());
ICancellationSignal cancellationSignal = ICancellationSignal.Stub.asInterface(
data.readStrongBinder());
- Cursor cursor = query(callingPkg, url, projection, selection, selectionArgs,
- sortOrder, cancellationSignal);
+ Cursor cursor = query(callingPkg, url, projection, queryArgs, cancellationSignal);
if (cursor != null) {
CursorToBulkCursorAdaptor adaptor = null;
@@ -185,7 +174,7 @@
String callingPkg = data.readString();
final int numOperations = data.readInt();
final ArrayList<ContentProviderOperation> operations =
- new ArrayList<ContentProviderOperation>(numOperations);
+ new ArrayList<>(numOperations);
for (int i = 0; i < numOperations; i++) {
operations.add(i, ContentProviderOperation.CREATOR.createFromParcel(data));
}
@@ -378,6 +367,7 @@
return super.onTransact(code, data, reply, flags);
}
+ @Override
public IBinder asBinder()
{
return this;
@@ -392,14 +382,16 @@
mRemote = remote;
}
+ @Override
public IBinder asBinder()
{
return mRemote;
}
- public Cursor query(String callingPkg, Uri url, String[] projection, String selection,
- String[] selectionArgs, String sortOrder, ICancellationSignal cancellationSignal)
- throws RemoteException {
+ @Override
+ public Cursor query(String callingPkg, Uri url, @Nullable String[] projection,
+ @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)
+ throws RemoteException {
BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -416,19 +408,10 @@
for (int i = 0; i < length; i++) {
data.writeString(projection[i]);
}
- data.writeString(selection);
- if (selectionArgs != null) {
- length = selectionArgs.length;
- } else {
- length = 0;
- }
- data.writeInt(length);
- for (int i = 0; i < length; i++) {
- data.writeString(selectionArgs[i]);
- }
- data.writeString(sortOrder);
+ data.writeBundle(queryArgs);
data.writeStrongBinder(adaptor.getObserver().asBinder());
- data.writeStrongBinder(cancellationSignal != null ? cancellationSignal.asBinder() : null);
+ data.writeStrongBinder(
+ cancellationSignal != null ? cancellationSignal.asBinder() : null);
mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
@@ -455,6 +438,7 @@
}
}
+ @Override
public String getType(Uri url) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -475,6 +459,7 @@
}
}
+ @Override
public Uri insert(String callingPkg, Uri url, ContentValues values) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -497,6 +482,7 @@
}
}
+ @Override
public int bulkInsert(String callingPkg, Uri url, ContentValues[] values) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -518,7 +504,8 @@
}
}
- public ContentProviderResult[] applyBatch(String callingPkg,
+ @Override
+ public ContentProviderResult[] applyBatch(String callingPkg,
ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
Parcel data = Parcel.obtain();
@@ -542,6 +529,7 @@
}
}
+ @Override
public int delete(String callingPkg, Uri url, String selection, String[] selectionArgs)
throws RemoteException {
Parcel data = Parcel.obtain();
@@ -565,6 +553,7 @@
}
}
+ @Override
public int update(String callingPkg, Uri url, ContentValues values, String selection,
String[] selectionArgs) throws RemoteException {
Parcel data = Parcel.obtain();
@@ -644,6 +633,7 @@
}
}
+ @Override
public Bundle call(String callingPkg, String method, String request, Bundle args)
throws RemoteException {
Parcel data = Parcel.obtain();
@@ -667,6 +657,7 @@
}
}
+ @Override
public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -715,6 +706,7 @@
}
}
+ @Override
public ICancellationSignal createCancellationSignal() throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -734,6 +726,7 @@
}
}
+ @Override
public Uri canonicalize(String callingPkg, Uri url) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -755,6 +748,7 @@
}
}
+ @Override
public Uri uncanonicalize(String callingPkg, Uri url) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -775,6 +769,7 @@
}
}
+ @Override
public boolean refresh(String callingPkg, Uri url, Bundle args, ICancellationSignal signal)
throws RemoteException {
Parcel data = Parcel.obtain();
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 54dcd0a..0fe5ce9 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -203,6 +203,26 @@
public static final String EXTRA_REFRESH_SUPPORTED = "android.content.extra.REFRESH_SUPPORTED";
/**
+ * Key for an SQL style selection string that may be present in the query Bundle argument
+ * passed to {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}
+ * when called by a legacy client.
+ */
+ public static final String QUERY_ARG_SELECTION = "android:query-selection";
+
+ /**
+ * Key for sql selection string arguments list.
+ * @see #QUERY_ARG_SELECTION
+ */
+ public static final String QUERY_ARG_SELECTION_ARGS = "android:query-selection-args";
+
+ /**
+ * Key for an SQL style sort string that may be present in the query Bundle argument
+ * passed to {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}
+ * when called by a legacy client.
+ */
+ public static final String QUERY_ARG_SORT_ORDER = "android:query-sort-order";
+
+ /**
* This is the Android platform's base MIME type for a content: URI
* containing a Cursor of a single item. Applications should use this
* as the base type along with their own sub-type of their content: URIs
@@ -517,10 +537,37 @@
* @return A Cursor object, which is positioned before the first entry, or null
* @see Cursor
*/
- public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
+ public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri,
@Nullable String[] projection, @Nullable String selection,
@Nullable String[] selectionArgs, @Nullable String sortOrder,
@Nullable CancellationSignal cancellationSignal) {
+ Bundle queryArgs = createSqlQueryBundle(selection, selectionArgs, sortOrder);
+ return query(uri, projection, queryArgs, cancellationSignal);
+ }
+
+ /**
+ * Query the given URI, returning a {@link Cursor} over the result set
+ * with support for cancellation.
+ *
+ * <p>For best performance, the caller should follow these guidelines:
+ *
+ * <li>Provide an explicit projection, to prevent reading data from storage
+ * that aren't going to be used.
+ *
+ * @param uri The URI, using the content:// scheme, for the content to
+ * retrieve.
+ * @param projection A list of which columns to return. Passing null will
+ * return all columns, which is inefficient.
+ * @param queryArgs A Bundle containing any arguments to the query.
+ * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
+ * If the operation is canceled, then {@link OperationCanceledException} will be thrown
+ * when the query is executed.
+ * @return A Cursor object, which is positioned before the first entry, or null
+ * @see Cursor
+ */
+ public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
+ @Nullable String[] projection, @Nullable Bundle queryArgs,
+ @Nullable CancellationSignal cancellationSignal) {
Preconditions.checkNotNull(uri, "uri");
IContentProvider unstableProvider = acquireUnstableProvider(uri);
if (unstableProvider == null) {
@@ -539,7 +586,7 @@
}
try {
qCursor = unstableProvider.query(mPackageName, uri, projection,
- selection, selectionArgs, sortOrder, remoteCancellationSignal);
+ queryArgs, remoteCancellationSignal);
} catch (DeadObjectException e) {
// The remote process has died... but we only hold an unstable
// reference though, so we might recover!!! Let's try!!!!
@@ -549,8 +596,8 @@
if (stableProvider == null) {
return null;
}
- qCursor = stableProvider.query(mPackageName, uri, projection,
- selection, selectionArgs, sortOrder, remoteCancellationSignal);
+ qCursor = stableProvider.query(
+ mPackageName, uri, projection, queryArgs, remoteCancellationSignal);
}
if (qCursor == null) {
return null;
@@ -559,7 +606,7 @@
// Force query execution. Might fail and throw a runtime exception here.
qCursor.getCount();
long durationMillis = SystemClock.uptimeMillis() - startTime;
- maybeLogQueryToEventLog(durationMillis, uri, projection, selection, sortOrder);
+ maybeLogQueryToEventLog(durationMillis, uri, projection, queryArgs);
// Wrap the cursor object into CursorWrapperInner object.
final IContentProvider provider = (stableProvider != null) ? stableProvider
@@ -2541,6 +2588,7 @@
}
try {
ISyncStatusObserver.Stub observer = new ISyncStatusObserver.Stub() {
+ @Override
public void onStatusChanged(int which) throws RemoteException {
callback.onStatusChanged(which);
}
@@ -2602,9 +2650,8 @@
return (int) (100 * durationMillis / SLOW_THRESHOLD_MILLIS) + 1;
}
- private void maybeLogQueryToEventLog(long durationMillis,
- Uri uri, String[] projection,
- String selection, String sortOrder) {
+ private void maybeLogQueryToEventLog(
+ long durationMillis, Uri uri, String[] projection, @Nullable Bundle queryArgs) {
if (!ENABLE_CONTENT_SAMPLE) return;
int samplePercent = samplePercentForDuration(durationMillis);
if (samplePercent < 100) {
@@ -2615,6 +2662,9 @@
}
}
+ // Ensure a non-null bundle.
+ queryArgs = (queryArgs != null) ? queryArgs : Bundle.EMPTY;
+
StringBuilder projectionBuffer = new StringBuilder(100);
if (projection != null) {
for (int i = 0; i < projection.length; ++i) {
@@ -2636,8 +2686,8 @@
EventLogTags.CONTENT_QUERY_SAMPLE,
uri.toString(),
projectionBuffer.toString(),
- selection != null ? selection : "",
- sortOrder != null ? sortOrder : "",
+ queryArgs.getString(QUERY_ARG_SELECTION, ""),
+ queryArgs.getString(QUERY_ARG_SORT_ORDER, ""),
durationMillis,
blockingPackage != null ? blockingPackage : "",
samplePercent);
@@ -2751,4 +2801,29 @@
public Drawable getTypeDrawable(String mimeType) {
return MimeIconUtils.loadMimeIcon(mContext, mimeType);
}
+
+ /**
+ * @hide
+ */
+ public static @Nullable Bundle createSqlQueryBundle(
+ @Nullable String selection,
+ @Nullable String[] selectionArgs,
+ @Nullable String sortOrder) {
+
+ if (selection == null && selectionArgs == null && sortOrder == null) {
+ return null;
+ }
+
+ Bundle queryArgs = new Bundle();
+ if (selection != null) {
+ queryArgs.putString(QUERY_ARG_SELECTION, selection);
+ }
+ if (selectionArgs != null) {
+ queryArgs.putStringArray(QUERY_ARG_SELECTION_ARGS, selectionArgs);
+ }
+ if (sortOrder != null) {
+ queryArgs.putString(QUERY_ARG_SORT_ORDER, sortOrder);
+ }
+ return queryArgs;
+ }
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5fa4275..b9783aa 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3309,6 +3309,15 @@
/**
* Use with {@link #getSystemService} to retrieve a
+ * {@link android.text.TextClassificationManager} for text classification services.
+ *
+ * @see #getSystemService
+ * @see android.text.TextClassificationManager
+ */
+ public static final String TEXT_CLASSIFICATION_SERVICE = "textclassification";
+
+ /**
+ * Use with {@link #getSystemService} to retrieve a
* {@link android.view.inputmethod.InputMethodManager} for accessing input
* methods.
*
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index ee8a22f..66087fb 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -35,9 +35,9 @@
* @hide
*/
public interface IContentProvider extends IInterface {
- public Cursor query(String callingPkg, Uri url, String[] projection, String selection,
- String[] selectionArgs, String sortOrder, ICancellationSignal cancellationSignal)
- throws RemoteException;
+ public Cursor query(String callingPkg, Uri url, @Nullable String[] projection,
+ @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)
+ throws RemoteException;
public String getType(Uri url) throws RemoteException;
public Uri insert(String callingPkg, Uri url, ContentValues initialValues)
throws RemoteException;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a5d7999..cda8176 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3483,6 +3483,21 @@
public static final String CATEGORY_OPENABLE = "android.intent.category.OPENABLE";
/**
+ * Used to indicate that an intent filter can accept files which are not necessarily
+ * openable by {@link ContentResolver#openFileDescriptor(Uri, String)}, but
+ * at least streamable via
+ * {@link ContentResolver#openTypedAssetFileDescriptor(Uri, String, Bundle)}
+ * using one of the stream types exposed via
+ * {@link ContentResolver#getStreamTypes(Uri, String)}.
+ *
+ * @see #ACTION_SEND
+ * @see #ACTION_SEND_MULTIPLE
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_TYPED_OPENABLE =
+ "android.intent.category.TYPED_OPENABLE";
+
+ /**
* To be used as code under test for framework instrumentation tests.
*/
public static final String CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST =
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index f5a79c8..2c97ec4 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -282,6 +282,10 @@
private int mVerifyState;
+ /** Whether or not the intent filter is visible to ephemeral apps. */
+ private boolean mVisibleToEphemeral;
+ /** Whether or not the intent filter is part of an ephemeral app. */
+ private boolean mEphemeral;
// These functions are the start of more optimized code for managing
// the string sets... not yet implemented.
@@ -647,6 +651,24 @@
if (verified) mVerifyState |= STATE_VERIFIED;
}
+ /** @hide */
+ public void setVisibleToEphemeral(boolean visibleToEmphemeral) {
+ mVisibleToEphemeral = visibleToEmphemeral;
+ }
+ /** @hide */
+ public boolean isVisibleToEphemeral() {
+ return mVisibleToEphemeral;
+ }
+
+ /** @hide */
+ public void setEphemeral(boolean ephemeral) {
+ mEphemeral = ephemeral;
+ }
+ /** @hide */
+ public boolean isEphemeral() {
+ return mEphemeral;
+ }
+
/**
* Add a new Intent action to match against. If any actions are included
* in the filter, then an Intent's action must be one of those values for
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index e2ebd46..44dff00 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -182,12 +182,30 @@
*/
public static final int RESIZE_MODE_RESIZEABLE_AND_PIPABLE = 3;
/**
- * Activity is does not support resizing, but we are forcing it to be resizeable. Only affects
+ * Activity does not support resizing, but we are forcing it to be resizeable. Only affects
* certain pre-N apps where we force them to be resizeable.
* @hide
*/
public static final int RESIZE_MODE_FORCE_RESIZEABLE = 4;
/**
+ * Activity does not support resizing, but we are forcing it to be resizeable as long
+ * as the size remains landscape.
+ * @hide
+ */
+ public static final int RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY = 5;
+ /**
+ * Activity does not support resizing, but we are forcing it to be resizeable as long
+ * as the size remains portrait.
+ * @hide
+ */
+ public static final int RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY = 6;
+ /**
+ * Activity does not support resizing, but we are forcing it to be resizeable as long
+ * as the bounds remain in the same orientation as they are.
+ * @hide
+ */
+ public static final int RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION = 7;
+ /**
* Value indicating if the resizing mode the activity supports.
* See {@link android.R.attr#resizeableActivity}.
* @hide
@@ -345,6 +363,12 @@
public static final int FLAG_ON_TOP_LAUNCHER = 0x80000;
/**
+ * Bit in {@link #flags} indicating if the activity is visible to ephemeral applications.
+ * @hide
+ */
+ public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000;
+
+ /**
* @hide Bit in {@link #flags}: If set, this component will only be seen
* by the system user. Only works with broadcast receivers. Set from the
* android.R.attr#systemUserOnly attribute.
@@ -859,26 +883,51 @@
* @hide
*/
boolean isFixedOrientation() {
- return screenOrientation == SCREEN_ORIENTATION_LANDSCAPE
- || screenOrientation == SCREEN_ORIENTATION_PORTRAIT
- || screenOrientation == SCREEN_ORIENTATION_SENSOR_LANDSCAPE
- || screenOrientation == SCREEN_ORIENTATION_SENSOR_PORTRAIT
- || screenOrientation == SCREEN_ORIENTATION_REVERSE_LANDSCAPE
- || screenOrientation == SCREEN_ORIENTATION_REVERSE_PORTRAIT
- || screenOrientation == SCREEN_ORIENTATION_USER_LANDSCAPE
- || screenOrientation == SCREEN_ORIENTATION_USER_PORTRAIT
+ return isFixedOrientationLandscape() || isFixedOrientationPortrait()
|| screenOrientation == SCREEN_ORIENTATION_LOCKED;
}
+ /**
+ * Returns true if the activity's orientation is fixed to landscape.
+ * @hide
+ */
+ boolean isFixedOrientationLandscape() {
+ return screenOrientation == SCREEN_ORIENTATION_LANDSCAPE
+ || screenOrientation == SCREEN_ORIENTATION_SENSOR_LANDSCAPE
+ || screenOrientation == SCREEN_ORIENTATION_REVERSE_LANDSCAPE
+ || screenOrientation == SCREEN_ORIENTATION_USER_LANDSCAPE;
+ }
+
+ /**
+ * Returns true if the activity's orientation is fixed to portrait.
+ * @hide
+ */
+ boolean isFixedOrientationPortrait() {
+ return screenOrientation == SCREEN_ORIENTATION_PORTRAIT
+ || screenOrientation == SCREEN_ORIENTATION_SENSOR_PORTRAIT
+ || screenOrientation == SCREEN_ORIENTATION_REVERSE_PORTRAIT
+ || screenOrientation == SCREEN_ORIENTATION_USER_PORTRAIT;
+ }
+
/** @hide */
public static boolean isResizeableMode(int mode) {
return mode == RESIZE_MODE_RESIZEABLE
|| mode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE
|| mode == RESIZE_MODE_FORCE_RESIZEABLE
+ || mode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
+ || mode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
+ || mode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION
|| mode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
}
/** @hide */
+ public static boolean isPreserveOrientationMode(int mode) {
+ return mode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
+ || mode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
+ || mode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
+ }
+
+ /** @hide */
public static String resizeModeToString(int mode) {
switch (mode) {
case RESIZE_MODE_UNRESIZEABLE:
@@ -891,6 +940,12 @@
return "RESIZE_MODE_RESIZEABLE_AND_PIPABLE";
case RESIZE_MODE_FORCE_RESIZEABLE:
return "RESIZE_MODE_FORCE_RESIZEABLE";
+ case RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY:
+ return "RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY";
+ case RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY:
+ return "RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY";
+ case RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION:
+ return "RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION";
default:
return "unknown=" + mode;
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index ed8143e..646bd3c 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1067,6 +1067,16 @@
}
/** {@hide} */
+ @SystemApi
+ public void setInstallAsInstantApp(boolean isInstantApp) {
+ if (isInstantApp) {
+ installFlags |= PackageManager.INSTALL_EPHEMERAL;
+ } else {
+ installFlags &= ~PackageManager.INSTALL_EPHEMERAL;
+ }
+ }
+
+ /** {@hide} */
public void dump(IndentingPrintWriter pw) {
pw.printPair("mode", mode);
pw.printHexPair("installFlags", installFlags);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3f052d38..2fbb5b1 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -436,9 +436,10 @@
/**
* Allows querying of packages installed for any user, not just the specific one. This flag
- * is only meant for use by apps that have INTERACT_ACROSS_USERS_FULL permission.
+ * is only meant for use by apps that have INTERACT_ACROSS_USERS permission.
* @hide
*/
+ @SystemApi
public static final int MATCH_ANY_USER = 0x00400000;
/**
@@ -449,6 +450,20 @@
public static final int MATCH_KNOWN_PACKAGES = MATCH_UNINSTALLED_PACKAGES | MATCH_ANY_USER;
/**
+ * Internal {@link PackageInfo} flag: include components that are part of an
+ * ephemeral app. By default, ephemeral components are not matched.
+ * @hide
+ */
+ public static final int MATCH_EPHEMERAL = 0x00800000;
+
+ /**
+ * Internal {@link PackageInfo} flag: include only components that are exposed to
+ * ephemeral apps.
+ * @hide
+ */
+ public static final int MATCH_VISIBLE_TO_EPHEMERAL_ONLY = 0x01000000;
+
+ /**
* Internal flag used to indicate that a system component has done their
* homework and verified that they correctly handle packages and components
* that come and go over time. In particular:
@@ -3304,7 +3319,8 @@
* Grant a runtime permission to an application which the application does not
* already have. The permission must have been requested by the application.
* If the application is not allowed to hold the permission, a {@link
- * java.lang.SecurityException} is thrown.
+ * java.lang.SecurityException} is thrown. If the package or permission is
+ * invalid, a {@link java.lang.IllegalArgumentException} is thrown.
* <p>
* <strong>Note: </strong>Using this API requires holding
* android.permission.GRANT_RUNTIME_PERMISSIONS and if the user id is
@@ -3328,7 +3344,8 @@
* #grantRuntimePermission(String, String, android.os.UserHandle)}. The
* permission must have been requested by and granted to the application.
* If the application is not allowed to hold the permission, a {@link
- * java.lang.SecurityException} is thrown.
+ * java.lang.SecurityException} is thrown. If the package or permission is
+ * invalid, a {@link java.lang.IllegalArgumentException} is thrown.
* <p>
* <strong>Note: </strong>Using this API requires holding
* android.permission.REVOKE_RUNTIME_PERMISSIONS and if the user id is
@@ -3472,15 +3489,15 @@
public abstract @Nullable String[] getPackagesForUid(int uid);
/**
- * Retrieve the official name associated with a user id. This name is
+ * Retrieve the official name associated with a uid. This name is
* guaranteed to never change, though it is possible for the underlying
- * user id to be changed. That is, if you are storing information about
- * user ids in persistent storage, you should use the string returned
- * by this function instead of the raw user-id.
+ * uid to be changed. That is, if you are storing information about
+ * uids in persistent storage, you should use the string returned
+ * by this function instead of the raw uid.
*
- * @param uid The user id for which you would like to retrieve a name.
- * @return Returns a unique name for the given user id, or null if the
- * user id is not currently assigned.
+ * @param uid The uid for which you would like to retrieve a name.
+ * @return Returns a unique name for the given uid, or null if the
+ * uid is not currently assigned.
*/
public abstract @Nullable String getNameForUid(int uid);
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index ad0a6b2..1ba68a6 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -197,15 +197,15 @@
boolean overridePolicy);
/**
- * Retrieve the official name associated with a user id. This name is
+ * Retrieve the official name associated with a uid. This name is
* guaranteed to never change, though it is possible for the underlying
- * user id to be changed. That is, if you are storing information about
- * user ids in persistent storage, you should use the string returned
- * by this function instead of the raw user-id.
+ * uid to be changed. That is, if you are storing information about
+ * uids in persistent storage, you should use the string returned
+ * by this function instead of the raw uid.
*
- * @param uid The user id for which you would like to retrieve a name.
- * @return Returns a unique name for the given user id, or null if the
- * user id is not currently assigned.
+ * @param uid The uid for which you would like to retrieve a name.
+ * @return Returns a unique name for the given uid, or null if the
+ * uid is not currently assigned.
*/
public abstract String getNameForUid(int uid);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index f363bd8..d7c3722 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -17,6 +17,7 @@
package android.content.pm;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.XmlUtils;
@@ -39,6 +40,9 @@
import android.os.PatternMatcher;
import android.os.Trace;
import android.os.UserHandle;
+import android.system.ErrnoException;
+import android.system.OsConstants;
+import android.system.StructStat;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -54,6 +58,8 @@
import android.view.Gravity;
import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
@@ -82,6 +88,9 @@
import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
import static android.content.pm.ActivityInfo.FLAG_ON_TOP_LAUNCHER;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
@@ -259,6 +268,7 @@
private String[] mSeparateProcesses;
private boolean mOnlyCoreApps;
private DisplayMetrics mMetrics;
+ private File mCacheDir;
private static final int SDK_VERSION = Build.VERSION.SDK_INT;
private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
@@ -453,6 +463,13 @@
mMetrics = metrics;
}
+ /**
+ * Sets the cache directory for this package parser.
+ */
+ public void setCacheDir(File cacheDir) {
+ mCacheDir = cacheDir;
+ }
+
public static final boolean isApkFile(File file) {
return isApkPath(file.getName());
}
@@ -806,13 +823,154 @@
* Note that this <em>does not</em> perform signature verification; that
* must be done separately in {@link #collectCertificates(Package, int)}.
*
+ * If {@code useCaches} is true, the package parser might return a cached
+ * result from a previous parse of the same {@code packageFile} with the same
+ * {@code flags}. Note that this method does not check whether {@code packageFile}
+ * has changed since the last parse, it's up to callers to do so.
+ *
* @see #parsePackageLite(File, int)
*/
- public Package parsePackage(File packageFile, int flags) throws PackageParserException {
+ public Package parsePackage(File packageFile, int flags, boolean useCaches)
+ throws PackageParserException {
+ Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
+ if (parsed != null) {
+ return parsed;
+ }
+
if (packageFile.isDirectory()) {
- return parseClusterPackage(packageFile, flags);
+ parsed = parseClusterPackage(packageFile, flags);
} else {
- return parseMonolithicPackage(packageFile, flags);
+ parsed = parseMonolithicPackage(packageFile, flags);
+ }
+
+ cacheResult(packageFile, flags, parsed);
+
+ return parsed;
+ }
+
+ /**
+ * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}.
+ */
+ public Package parsePackage(File packageFile, int flags) throws PackageParserException {
+ return parsePackage(packageFile, flags, false /* useCaches */);
+ }
+
+ /**
+ * Returns the cache key for a specificied {@code packageFile} and {@code flags}.
+ */
+ private String getCacheKey(File packageFile, int flags) {
+ StringBuilder sb = new StringBuilder(packageFile.getName());
+ sb.append('-');
+ sb.append(flags);
+
+ return sb.toString();
+ }
+
+ @VisibleForTesting
+ protected Package fromCacheEntry(byte[] bytes) throws IOException {
+ return null;
+ }
+
+ @VisibleForTesting
+ protected byte[] toCacheEntry(Package pkg) throws IOException {
+ return null;
+ }
+
+ /**
+ * Given a {@code packageFile} and a {@code cacheFile} returns whether the
+ * cache file is up to date based on the mod-time of both files.
+ */
+ private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
+ try {
+ // NOTE: We don't use the File.lastModified API because it has the very
+ // non-ideal failure mode of returning 0 with no excepions thrown.
+ // The nio2 Files API is a little better but is considerably more expensive.
+ final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
+ final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
+ return pkg.st_mtime < cache.st_mtime;
+ } catch (ErrnoException ee) {
+ // The most common reason why stat fails is that a given cache file doesn't
+ // exist. We ignore that here. It's easy to reason that it's safe to say the
+ // cache isn't up to date if we see any sort of exception here.
+ //
+ // (1) Exception while stating the package file : This should never happen,
+ // and if it does, we do a full package parse (which is likely to throw the
+ // same exception).
+ // (2) Exception while stating the cache file : If the file doesn't exist, the
+ // cache is obviously out of date. If the file *does* exist, we can't read it.
+ // We will attempt to delete and recreate it after parsing the package.
+ if (ee.errno != OsConstants.ENOENT) {
+ Slog.w("Error while stating package cache : ", ee);
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
+ * or {@code null} if no cached result exists.
+ */
+ private Package getCachedResult(File packageFile, int flags) {
+ if (mCacheDir == null) {
+ return null;
+ }
+
+ final String cacheKey = getCacheKey(packageFile, flags);
+ final File cacheFile = new File(mCacheDir, cacheKey);
+
+ // If the cache is not up to date, return null.
+ if (!isCacheUpToDate(packageFile, cacheFile)) {
+ return null;
+ }
+
+ try {
+ final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
+ return fromCacheEntry(bytes);
+ } catch (IOException ioe) {
+ Slog.w(TAG, "Error reading package cache: ", ioe);
+
+ // If something went wrong while reading the cache entry, delete the cache file
+ // so that we regenerate it the next time.
+ cacheFile.delete();
+ return null;
+ }
+ }
+
+ /**
+ * Caches the parse result for {@code packageFile} with flags {@code flags}.
+ */
+ private void cacheResult(File packageFile, int flags, Package parsed) {
+ if (mCacheDir == null) {
+ return;
+ }
+
+ final String cacheKey = getCacheKey(packageFile, flags);
+ final File cacheFile = new File(mCacheDir, cacheKey);
+
+ if (cacheFile.exists()) {
+ if (!cacheFile.delete()) {
+ Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
+ }
+ }
+
+ final byte[] cacheEntry;
+ try {
+ cacheEntry = toCacheEntry(parsed);
+ } catch (IOException ioe) {
+ Slog.e(TAG, "Unable to serialize parsed package for: " + packageFile);
+ return;
+ }
+
+ if (cacheEntry == null) {
+ return;
+ }
+
+ try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
+ fos.write(cacheEntry);
+ } catch (IOException ioe) {
+ Slog.w(TAG, "Error writing cache entry.", ioe);
+ cacheFile.delete();
}
}
@@ -3622,6 +3780,13 @@
ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
}
+ final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0);
+ final boolean visibleToEphemeral = isEphemeral
+ || sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToEphemeral, false);
+ if (visibleToEphemeral) {
+ a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+ }
+
sa.recycle();
if (receiver && (owner.applicationInfo.privateFlags
@@ -3648,9 +3813,12 @@
if (parser.getName().equals("intent-filter")) {
ActivityIntentInfo intent = new ActivityIntentInfo(a);
- if (!parseIntent(res, parser, true, true, intent, outError)) {
+ if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
+ intent, outError)) {
return null;
}
+ intent.setEphemeral(isEphemeral);
+ intent.setVisibleToEphemeral(visibleToEphemeral);
if (intent.countActions() == 0) {
Slog.w(TAG, "No actions in intent filter at "
+ mArchiveSourcePath + " "
@@ -3660,9 +3828,12 @@
}
} else if (!receiver && parser.getName().equals("preferred")) {
ActivityIntentInfo intent = new ActivityIntentInfo(a);
- if (!parseIntent(res, parser, false, false, intent, outError)) {
+ if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
+ intent, outError)) {
return null;
}
+ intent.setEphemeral(isEphemeral);
+ intent.setVisibleToEphemeral(visibleToEphemeral);
if (intent.countActions() == 0) {
Slog.w(TAG, "No actions in preferred at "
+ mArchiveSourcePath + " "
@@ -3741,8 +3912,15 @@
// resize preference isn't set and target sdk version doesn't support resizing apps by
// default. For the app to be resizeable if it isn't fixed orientation or immersive.
- aInfo.resizeMode = (aInfo.isFixedOrientation() || (aInfo.flags & FLAG_IMMERSIVE) != 0)
- ? RESIZE_MODE_UNRESIZEABLE : RESIZE_MODE_FORCE_RESIZEABLE;
+ if (aInfo.isFixedOrientationPortrait()) {
+ aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
+ } else if (aInfo.isFixedOrientationLandscape()) {
+ aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
+ } else if (aInfo.isFixedOrientation()) {
+ aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
+ } else {
+ aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
+ }
}
private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
@@ -3906,6 +4084,10 @@
}
}
+ final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0);
+ final boolean visibleToEphemeral = isEphemeral
+ || ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0);
+
sa.recycle();
if (outError[0] != null) {
@@ -3923,7 +4105,8 @@
if (parser.getName().equals("intent-filter")) {
ActivityIntentInfo intent = new ActivityIntentInfo(a);
- if (!parseIntent(res, parser, true, true, intent, outError)) {
+ if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
+ intent, outError)) {
return null;
}
if (intent.countActions() == 0) {
@@ -3931,6 +4114,8 @@
+ mArchiveSourcePath + " "
+ parser.getPositionDescription());
} else {
+ intent.setEphemeral(isEphemeral);
+ intent.setVisibleToEphemeral(visibleToEphemeral);
a.intents.add(intent);
}
} else if (parser.getName().equals("meta-data")) {
@@ -4068,6 +4253,13 @@
ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
}
+ final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0);
+ final boolean visibleToEphemeral = isEphemeral
+ || sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToEphemeral, false);
+ if (visibleToEphemeral) {
+ p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+ }
+
sa.recycle();
if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
@@ -4090,15 +4282,15 @@
}
p.info.authority = cpname.intern();
- if (!parseProviderTags(res, parser, p, outError)) {
+ if (!parseProviderTags(res, parser, isEphemeral, visibleToEphemeral, p, outError)) {
return null;
}
return p;
}
- private boolean parseProviderTags(Resources res,
- XmlResourceParser parser, Provider outInfo, String[] outError)
+ private boolean parseProviderTags(Resources res, XmlResourceParser parser,
+ boolean isEphemeral, boolean visibleToEphemeral, Provider outInfo, String[] outError)
throws XmlPullParserException, IOException {
int outerDepth = parser.getDepth();
int type;
@@ -4111,9 +4303,12 @@
if (parser.getName().equals("intent-filter")) {
ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
- if (!parseIntent(res, parser, true, false, intent, outError)) {
+ if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
+ intent, outError)) {
return false;
}
+ intent.setEphemeral(isEphemeral);
+ intent.setVisibleToEphemeral(visibleToEphemeral);
outInfo.intents.add(intent);
} else if (parser.getName().equals("meta-data")) {
@@ -4361,6 +4556,13 @@
ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
}
+ final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0);
+ final boolean visibleToEphemeral = isEphemeral
+ || sa.getBoolean(R.styleable.AndroidManifestService_visibleToEphemeral, false);
+ if (visibleToEphemeral) {
+ s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+ }
+
sa.recycle();
if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
@@ -4384,9 +4586,12 @@
if (parser.getName().equals("intent-filter")) {
ServiceIntentInfo intent = new ServiceIntentInfo(s);
- if (!parseIntent(res, parser, true, false, intent, outError)) {
+ if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
+ intent, outError)) {
return null;
}
+ intent.setEphemeral(isEphemeral);
+ intent.setVisibleToEphemeral(visibleToEphemeral);
s.intents.add(intent);
} else if (parser.getName().equals("meta-data")) {
@@ -4590,9 +4795,9 @@
private static final String ANDROID_RESOURCES
= "http://schemas.android.com/apk/res/android";
- private boolean parseIntent(Resources res, XmlResourceParser parser,
- boolean allowGlobs, boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
- throws XmlPullParserException, IOException {
+ private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs,
+ boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
+ throws XmlPullParserException, IOException {
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestIntentFilter);
diff --git a/core/java/android/content/pm/ProviderInfo.java b/core/java/android/content/pm/ProviderInfo.java
index 7e7b32f..8c21563 100644
--- a/core/java/android/content/pm/ProviderInfo.java
+++ b/core/java/android/content/pm/ProviderInfo.java
@@ -76,6 +76,12 @@
public int initOrder = 0;
/**
+ * Bit in {@link #flags} indicating if the provider is visible to ephemeral applications.
+ * @hide
+ */
+ public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000;
+
+ /**
* Bit in {@link #flags}: If set, a single instance of the provider will
* run for all users on the device. Set from the
* {@link android.R.attr#singleUser} attribute.
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index 6bd285a..f0766be 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -56,6 +56,12 @@
public static final int FLAG_EXTERNAL_SERVICE = 0x0004;
/**
+ * Bit in {@link #flags} indicating if the service is visible to ephemeral applications.
+ * @hide
+ */
+ public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000;
+
+ /**
* Bit in {@link #flags}: If set, a single instance of the service will
* run for all users on the device. Set from the
* {@link android.R.attr#singleUser} attribute.
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index a854b89..56f914e 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -314,9 +314,11 @@
*
* @hide
*/
- public void enforceMandatoryFields() {
+ public void enforceMandatoryFields(boolean forPinned) {
Preconditions.checkStringNotEmpty(mId, "Shortcut ID must be provided");
- Preconditions.checkNotNull(mActivity, "Activity must be provided");
+ if (!forPinned) {
+ Preconditions.checkNotNull(mActivity, "Activity must be provided");
+ }
if (mTitle == null && mTitleResId == 0) {
throw new IllegalArgumentException("Short label must be provided");
}
@@ -1055,6 +1057,11 @@
* Launcher apps should show the launcher icon for the returned activity alongside
* this shortcut.
*
+ * <p>When a shortcut is dynamic or manifest
+ * (i.e. either {@link #isDynamic()} or {@link #isDeclaredInManifest()} returns {@code TRUE}),
+ * then it should always have a non-null target activity.
+ * Otherwise it will return null.
+ *
* @see Builder#setActivity
*/
@Nullable
@@ -1361,7 +1368,7 @@
}
/**
- * @return true if pinned but neither static nor dynamic.
+ * Return {@code TRUE} if a shortcut is pinned but neither manifest nor dynamic.
* @hide
*/
public boolean isFloating() {
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index b0d0d79..db24ffe 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -815,9 +815,9 @@
/*package*/ static final int STYLE_DENSITY = 5;
@FastNative
- /*package*/ native static final boolean applyStyle(long theme,
+ /*package*/ native static final void applyStyle(long theme,
int defStyleAttr, int defStyleRes, long xmlParser,
- int[] inAttrs, int[] outValues, int[] outIndices);
+ int[] inAttrs, int length, long outValuesAddress, long outIndicesAddress);
@FastNative
/*package*/ native static final boolean resolveAttrs(long theme,
int defStyleAttr, int defStyleRes, int[] inValues,
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index ee1f190..227dc91 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1047,18 +1047,36 @@
changed |= ActivityInfo.CONFIG_ORIENTATION;
orientation = delta.orientation;
}
- if (getScreenLayoutNoDirection(delta.screenLayout) !=
- (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED)
- && (getScreenLayoutNoDirection(screenLayout) !=
- getScreenLayoutNoDirection(delta.screenLayout))) {
+
+ if (((delta.screenLayout & SCREENLAYOUT_SIZE_MASK) != SCREENLAYOUT_SIZE_UNDEFINED)
+ && (delta.screenLayout & SCREENLAYOUT_SIZE_MASK)
+ != (screenLayout & SCREENLAYOUT_SIZE_MASK)) {
changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
- // We need to preserve the previous layout dir bits if they were defined
- if ((delta.screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == 0) {
- screenLayout = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK)|delta.screenLayout;
- } else {
- screenLayout = delta.screenLayout;
- }
+ screenLayout = (screenLayout & ~SCREENLAYOUT_SIZE_MASK)
+ | (delta.screenLayout & SCREENLAYOUT_SIZE_MASK);
}
+ if (((delta.screenLayout & SCREENLAYOUT_LONG_MASK) != SCREENLAYOUT_LONG_UNDEFINED)
+ && (delta.screenLayout & SCREENLAYOUT_LONG_MASK)
+ != (screenLayout & SCREENLAYOUT_LONG_MASK)) {
+ changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
+ screenLayout = (screenLayout & ~SCREENLAYOUT_LONG_MASK)
+ | (delta.screenLayout & SCREENLAYOUT_LONG_MASK);
+ }
+ if (((delta.screenLayout & SCREENLAYOUT_ROUND_MASK) != SCREENLAYOUT_ROUND_UNDEFINED)
+ && (delta.screenLayout & SCREENLAYOUT_ROUND_MASK)
+ != (screenLayout & SCREENLAYOUT_ROUND_MASK)) {
+ changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
+ screenLayout = (screenLayout & ~SCREENLAYOUT_ROUND_MASK)
+ | (delta.screenLayout & SCREENLAYOUT_ROUND_MASK);
+ }
+ if ((delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED)
+ != (screenLayout & SCREENLAYOUT_COMPAT_NEEDED)
+ && delta.screenLayout != 0) {
+ changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
+ screenLayout = (screenLayout & ~SCREENLAYOUT_COMPAT_NEEDED)
+ | (delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED);
+ }
+
if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
&& uiMode != delta.uiMode) {
changed |= ActivityInfo.CONFIG_UI_MODE;
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index c46fe29..eb010e4 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -1126,7 +1126,7 @@
final XmlBlock.Parser parser = (XmlBlock.Parser) set;
AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
parser != null ? parser.mParseState : 0,
- attrs, array.mData, array.mIndices);
+ attrs, attrs.length, array.mDataAddress, array.mIndicesAddress);
array.mTheme = wrapper;
array.mXml = parser;
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 1e44a5c..ca95ce1 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -30,6 +30,8 @@
import com.android.internal.util.XmlUtils;
+import dalvik.system.VMRuntime;
+
import java.util.Arrays;
/**
@@ -44,28 +46,17 @@
public class TypedArray {
static TypedArray obtain(Resources res, int len) {
- final TypedArray attrs = res.mTypedArrayPool.acquire();
- if (attrs != null) {
- attrs.mLength = len;
- attrs.mRecycled = false;
-
- // Reset the assets, which may have changed due to configuration changes
- // or further resource loading.
- attrs.mAssets = res.getAssets();
-
- final int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
- if (attrs.mData.length >= fullLen) {
- return attrs;
- }
-
- attrs.mData = new int[fullLen];
- attrs.mIndices = new int[1 + len];
- return attrs;
+ TypedArray attrs = res.mTypedArrayPool.acquire();
+ if (attrs == null) {
+ attrs = new TypedArray(res);
}
- return new TypedArray(res,
- new int[len*AssetManager.STYLE_NUM_ENTRIES],
- new int[1+len], len);
+ attrs.mRecycled = false;
+ // Reset the assets, which may have changed due to configuration changes
+ // or further resource loading.
+ attrs.mAssets = res.getAssets();
+ attrs.resize(len);
+ return attrs;
}
private final Resources mResources;
@@ -77,10 +68,25 @@
/*package*/ XmlBlock.Parser mXml;
/*package*/ Resources.Theme mTheme;
/*package*/ int[] mData;
+ /*package*/ long mDataAddress;
/*package*/ int[] mIndices;
+ /*package*/ long mIndicesAddress;
/*package*/ int mLength;
/*package*/ TypedValue mValue = new TypedValue();
+ private void resize(int len) {
+ mLength = len;
+ final int dataLen = len * AssetManager.STYLE_NUM_ENTRIES;
+ final int indicesLen = len + 1;
+ final VMRuntime runtime = VMRuntime.getRuntime();
+ if (mData == null || mData.length < dataLen) {
+ mData = (int[]) runtime.newNonMovableArray(int.class, dataLen);
+ mDataAddress = runtime.addressOf(mData);
+ mIndices = (int[]) runtime.newNonMovableArray(int.class, indicesLen);
+ mIndicesAddress = runtime.addressOf(mIndices);
+ }
+ }
+
/**
* Returns the number of values in this array.
*
@@ -1217,13 +1223,11 @@
return mAssets.getPooledStringForCookie(cookie, data[index+AssetManager.STYLE_DATA]);
}
- /*package*/ TypedArray(Resources resources, int[] data, int[] indices, int len) {
+ /** @hide */
+ protected TypedArray(Resources resources) {
mResources = resources;
mMetrics = mResources.getDisplayMetrics();
mAssets = mResources.getAssets();
- mData = data;
- mIndices = indices;
- mLength = len;
}
@Override
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index 3e79118..1a05904 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -348,9 +348,7 @@
Size[] sizes = streamConfigurations.getOutputSizes(surfaceType);
if (sizes == null) {
- // WAR: Override default format to IMPLEMENTATION_DEFINED for b/9487482
- if ((surfaceType >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 &&
- surfaceType <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) {
+ if (surfaceType == ImageFormat.PRIVATE) {
// YUV_420_888 is always present in LEGACY for all
// IMPLEMENTATION_DEFINED output sizes, and is publicly visible in the
@@ -649,7 +647,16 @@
*/
public static int detectSurfaceType(Surface surface) throws BufferQueueAbandonedException {
checkNotNull(surface);
- return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceType(surface));
+ int surfaceType = nativeDetectSurfaceType(surface);
+
+ // TODO: remove this override since the default format should be
+ // ImageFormat.PRIVATE. b/9487482
+ if ((surfaceType >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 &&
+ surfaceType <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) {
+ surfaceType = ImageFormat.PRIVATE;
+ }
+
+ return LegacyExceptionUtils.throwOnError(surfaceType);
}
/**
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index dfa19b0..dbe1394 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -408,12 +408,6 @@
// See if consumer is flexible.
boolean isFlexible = SurfaceUtils.isFlexibleConsumer(surface);
- // Override RGB formats to IMPLEMENTATION_DEFINED, b/9487482
- if ((surfaceFormat >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 &&
- surfaceFormat <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) {
- surfaceFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
- }
-
StreamConfiguration[] configs =
surfaceDataspace != HAL_DATASPACE_DEPTH ? mConfigurations : mDepthConfigurations;
for (StreamConfiguration config : configs) {
diff --git a/core/java/android/hardware/camera2/utils/SurfaceUtils.java b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
index 4b958df..e1e1c4f 100644
--- a/core/java/android/hardware/camera2/utils/SurfaceUtils.java
+++ b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
@@ -118,15 +118,7 @@
* @param surface The high speed output surface to be checked.
*/
private static void checkHighSpeedSurfaceFormat(Surface surface) {
- // TODO: remove this override since the default format should be
- // ImageFormat.PRIVATE. b/9487482
- final int HAL_FORMAT_RGB_START = 1; // HAL_PIXEL_FORMAT_RGBA_8888 from graphics.h
- final int HAL_FORMAT_RGB_END = 5; // HAL_PIXEL_FORMAT_BGRA_8888 from graphics.h
int surfaceFormat = SurfaceUtils.getSurfaceFormat(surface);
- if (surfaceFormat >= HAL_FORMAT_RGB_START &&
- surfaceFormat <= HAL_FORMAT_RGB_END) {
- surfaceFormat = ImageFormat.PRIVATE;
- }
if (surfaceFormat != ImageFormat.PRIVATE) {
throw new IllegalArgumentException("Surface format(" + surfaceFormat + ") is not"
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 3636e4e..ae92457 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -183,6 +183,14 @@
public static final String USB_DATA_UNLOCKED = "unlocked";
/**
+ * Boolean extra indicating whether the intent represents a change in the usb
+ * configuration (as opposed to a state update).
+ *
+ * {@hide}
+ */
+ public static final String USB_CONFIG_CHANGED = "config_changed";
+
+ /**
* A placeholder indicating that no USB function is being specified.
* Used to distinguish between selecting no function vs. the default function in
* {@link #setCurrentFunction(String)}.
diff --git a/core/java/android/net/EventLogTags.logtags b/core/java/android/net/EventLogTags.logtags
new file mode 100644
index 0000000..d5ed014
--- /dev/null
+++ b/core/java/android/net/EventLogTags.logtags
@@ -0,0 +1,6 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package android.net
+
+50080 ntp_success (server|3),(rtt|2),(offset|2)
+50081 ntp_failure (server|3),(msg|3)
diff --git a/core/java/android/net/INetworkRecommendationProvider.aidl b/core/java/android/net/INetworkRecommendationProvider.aidl
new file mode 100644
index 0000000..052c92c
--- /dev/null
+++ b/core/java/android/net/INetworkRecommendationProvider.aidl
@@ -0,0 +1,53 @@
+/**
+ * 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.net;
+
+import android.net.NetworkKey;
+import android.net.RecommendationRequest;
+import android.os.IRemoteCallback;
+
+/**
+ * The service responsible for answering network recommendation requests.
+ * @hide
+ */
+oneway interface INetworkRecommendationProvider {
+
+ /**
+ * Request a recommendation for the best network to connect to
+ * taking into account the inputs from the {@link RecommendationRequest}.
+ *
+ * @param request a {@link RecommendationRequest} instance containing the details of the request
+ * @param callback a {@link IRemoteCallback} instance to invoke when the recommendation
+ * is available
+ * @param sequence an internal number used for tracking the request
+ * @hide
+ */
+ void requestRecommendation(in RecommendationRequest request,
+ in IRemoteCallback callback,
+ int sequence);
+
+ /**
+ * Request scoring for networks.
+ *
+ * Implementations should use {@link NetworkScoreManager#updateScores(ScoredNetwork[])} to
+ * respond to score requests.
+ *
+ * @param networks an array of {@link NetworkKey}s to score
+ * @hide
+ */
+ void requestScores(in NetworkKey[] networks);
+}
\ No newline at end of file
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index 43869264..932f031 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -17,6 +17,9 @@
package android.net;
import android.net.INetworkScoreCache;
+import android.net.NetworkKey;
+import android.net.RecommendationRequest;
+import android.net.RecommendationResult;
import android.net.ScoredNetwork;
/**
@@ -54,14 +57,47 @@
void disableScoring();
/**
- * Register a network subsystem for scoring.
+ * Register a cache to receive scoring updates.
+ *
+ * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
+ * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
+ * @param filterType the {@link CacheUpdateFilter} to apply
+ * @throws SecurityException if the caller is not the system
+ * @throws IllegalArgumentException if a score cache is already registed for this type
+ * @hide
+ */
+ void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache, int filterType);
+
+ /**
+ * Unregister a cache to receive scoring updates.
*
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
* @throws SecurityException if the caller is not the system.
- * @throws IllegalArgumentException if a score cache is already registed for this type.
* @hide
*/
- void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache);
+ void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache);
+ /**
+ * Request a recommendation for the best network to connect to
+ * taking into account the inputs from the {@link RecommendationRequest}.
+ *
+ * @param request a {@link RecommendationRequest} instance containing the details of the request
+ * @return a {@link RecommendationResult} containing the recommended network to connect to
+ * @throws SecurityException if the caller is not the system
+ */
+ RecommendationResult requestRecommendation(in RecommendationRequest request);
+
+ /**
+ * Request scoring for networks.
+ *
+ * Implementations should delegate to the registered network recommendation provider or
+ * fulfill the request locally if possible.
+ *
+ * @param networks an array of {@link NetworkKey}s to score
+ * @return true if the request was delegated or fulfilled locally, false otherwise
+ * @throws SecurityException if the caller is not the system
+ * @hide
+ */
+ boolean requestScores(in NetworkKey[] networks);
}
diff --git a/core/java/android/net/NetworkRecommendationProvider.java b/core/java/android/net/NetworkRecommendationProvider.java
new file mode 100644
index 0000000..af5a052c
--- /dev/null
+++ b/core/java/android/net/NetworkRecommendationProvider.java
@@ -0,0 +1,188 @@
+package android.net;
+
+import android.annotation.SystemApi;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.IRemoteCallback;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * The base class for implementing a network recommendation provider.
+ * @hide
+ */
+@SystemApi
+public abstract class NetworkRecommendationProvider {
+ private static final String TAG = "NetworkRecProvider";
+ /** The key into the callback Bundle where the RecommendationResult will be found. */
+ public static final String EXTRA_RECOMMENDATION_RESULT =
+ "android.net.extra.RECOMMENDATION_RESULT";
+ /** The key into the callback Bundle where the sequence will be found. */
+ public static final String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
+ private static final String EXTRA_RECOMMENDATION_REQUEST =
+ "android.net.extra.RECOMMENDATION_REQUEST";
+ private final IBinder mService;
+
+ /**
+ * Constructs a new instance.
+ * @param handler indicates which thread to use when handling requests. Cannot be {@code null}.
+ */
+ public NetworkRecommendationProvider(Handler handler) {
+ if (handler == null) {
+ throw new IllegalArgumentException("The provided handler cannot be null.");
+ }
+ mService = new ServiceWrapper(new ServiceHandler(handler.getLooper()));
+ }
+
+ /**
+ * Invoked when a recommendation has been requested.
+ *
+ * @param request a {@link RecommendationRequest} instance containing additional
+ * request details
+ * @param callback a {@link ResultCallback} instance. When a {@link RecommendationResult} is
+ * available it must be passed into
+ * {@link ResultCallback#onResult(RecommendationResult)}.
+ */
+ public abstract void onRequestRecommendation(RecommendationRequest request,
+ ResultCallback callback);
+
+ /**
+ * Invoked when network scores have been requested.
+ * <p>
+ * Use {@link NetworkScoreManager#updateScores(ScoredNetwork[])} to respond to score requests.
+ *
+ * @param networks a non-empty array of {@link NetworkKey}s to score.
+ */
+ public abstract void onRequestScores(NetworkKey[] networks);
+
+ /**
+ * Services that can handle {@link NetworkScoreManager#ACTION_RECOMMEND_NETWORKS} should
+ * return this Binder from their <code>onBind()</code> method.
+ */
+ public final IBinder getBinder() {
+ return mService;
+ }
+
+ /**
+ * A callback implementing applications should invoke when a {@link RecommendationResult}
+ * is available.
+ */
+ public static final class ResultCallback {
+ private final IRemoteCallback mCallback;
+ private final int mSequence;
+ private final AtomicBoolean mCallbackRun;
+
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public ResultCallback(IRemoteCallback callback, int sequence) {
+ mCallback = callback;
+ mSequence = sequence;
+ mCallbackRun = new AtomicBoolean(false);
+ }
+
+ /**
+ * Run the callback with the available {@link RecommendationResult}.
+ * @param result a {@link RecommendationResult} instance.
+ */
+ public void onResult(RecommendationResult result) {
+ if (!mCallbackRun.compareAndSet(false, true)) {
+ throw new IllegalStateException("The callback cannot be run more than once.");
+ }
+ final Bundle data = new Bundle();
+ data.putInt(EXTRA_SEQUENCE, mSequence);
+ data.putParcelable(EXTRA_RECOMMENDATION_RESULT, result);
+ try {
+ mCallback.sendResult(data);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Callback failed for seq: " + mSequence, e);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ResultCallback that = (ResultCallback) o;
+
+ return mSequence == that.mSequence
+ && Objects.equals(mCallback, that.mCallback);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mCallback, mSequence);
+ }
+ }
+
+ private final class ServiceHandler extends Handler {
+ static final int MSG_GET_RECOMMENDATION = 1;
+ static final int MSG_REQUEST_SCORES = 2;
+
+ ServiceHandler(Looper looper) {
+ super(looper, null /*callback*/, true /*async*/);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ final int what = msg.what;
+ switch (what) {
+ case MSG_GET_RECOMMENDATION:
+ final IRemoteCallback callback = (IRemoteCallback) msg.obj;
+ final int seq = msg.arg1;
+ final RecommendationRequest request =
+ msg.getData().getParcelable(EXTRA_RECOMMENDATION_REQUEST);
+ final ResultCallback resultCallback = new ResultCallback(callback, seq);
+ onRequestRecommendation(request, resultCallback);
+ break;
+
+ case MSG_REQUEST_SCORES:
+ final NetworkKey[] networks = (NetworkKey[]) msg.obj;
+ onRequestScores(networks);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown message: " + what);
+ }
+ }
+ }
+
+ /**
+ * A wrapper around INetworkRecommendationProvider that sends calls to the internal Handler.
+ */
+ private static final class ServiceWrapper extends INetworkRecommendationProvider.Stub {
+ private final Handler mHandler;
+
+ ServiceWrapper(Handler handler) {
+ mHandler = handler;
+ }
+
+ @Override
+ public void requestRecommendation(RecommendationRequest request, IRemoteCallback callback,
+ int sequence) throws RemoteException {
+ final Message msg = mHandler.obtainMessage(
+ ServiceHandler.MSG_GET_RECOMMENDATION, sequence, 0 /*arg2*/, callback);
+ final Bundle data = new Bundle();
+ data.putParcelable(EXTRA_RECOMMENDATION_REQUEST, request);
+ msg.setData(data);
+ msg.sendToTarget();
+ }
+
+ @Override
+ public void requestScores(NetworkKey[] networks) throws RemoteException {
+ if (networks != null && networks.length > 0) {
+ mHandler.obtainMessage(ServiceHandler.MSG_REQUEST_SCORES, networks).sendToTarget();
+ }
+ }
+ }
+}
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index a0f74ec..865b8dd 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -17,6 +17,7 @@
package android.net;
import android.Manifest;
+import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -28,6 +29,9 @@
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.UserHandle;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Class that manages communication between network subsystems and a network scorer.
*
@@ -117,12 +121,43 @@
public static final String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED";
/**
+ * Service action: Used to discover and bind to a network recommendation provider.
+ * Implementations should return {@link NetworkRecommendationProvider#getBinder()} from
+ * their <code>onBind()</code> method.
+ */
+ @SdkConstant(SdkConstantType.SERVICE_ACTION)
+ public static final String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS";
+
+ /**
* Extra used with {@link #ACTION_SCORER_CHANGED} to specify the newly selected scorer's package
* name. Will be null if scoring was disabled. Can be obtained with
* {@link android.content.Intent#getStringExtra(String)}.
*/
public static final String EXTRA_NEW_SCORER = "newScorer";
+ /** @hide */
+ @IntDef({CACHE_FILTER_NONE, CACHE_FILTER_CURRENT_NETWORK, CACHE_FILTER_SCAN_RESULTS})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CacheUpdateFilter {}
+
+ /**
+ * Do not filter updates sent to the cache.
+ * @hide
+ */
+ public static final int CACHE_FILTER_NONE = 0;
+
+ /**
+ * Only send cache updates when the network matches the connected network.
+ * @hide
+ */
+ public static final int CACHE_FILTER_CURRENT_NETWORK = 1;
+
+ /**
+ * Only send cache updates when the network is part of the current scan result set.
+ * @hide
+ */
+ public static final int CACHE_FILTER_SCAN_RESULTS = 2;
+
private final Context mContext;
private final INetworkScoreService mService;
@@ -260,11 +295,65 @@
* @throws SecurityException if the caller does not hold the
* {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
+ * @deprecated equivalent to registering for cache updates with CACHE_FILTER_NONE.
* @hide
*/
+ @Deprecated // migrate to registerNetworkScoreCache(int, INetworkScoreCache, int)
public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
+ registerNetworkScoreCache(networkType, scoreCache, CACHE_FILTER_NONE);
+ }
+
+ /**
+ * Register a network score cache.
+ *
+ * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
+ * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
+ * @param filterType the {@link CacheUpdateFilter} to apply
+ * @throws SecurityException if the caller does not hold the
+ * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
+ * @throws IllegalArgumentException if a score cache is already registered for this type.
+ * @hide
+ */
+ public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache,
+ @CacheUpdateFilter int filterType) {
try {
- mService.registerNetworkScoreCache(networkType, scoreCache);
+ mService.registerNetworkScoreCache(networkType, scoreCache, filterType);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Unregister a network score cache.
+ *
+ * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
+ * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
+ * @throws SecurityException if the caller does not hold the
+ * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
+ * @throws IllegalArgumentException if a score cache is already registered for this type.
+ * @hide
+ */
+ public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
+ try {
+ mService.unregisterNetworkScoreCache(networkType, scoreCache);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Request a recommendation for which network to connect to.
+ *
+ * @param request a {@link RecommendationRequest} instance containing additional
+ * request details
+ * @return a {@link RecommendationResult} instance containing the recommended network
+ * to connect to
+ * @throws SecurityException
+ */
+ public RecommendationResult requestRecommendation(RecommendationRequest request)
+ throws SecurityException {
+ try {
+ return mService.requestRecommendation(request);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/net/RecommendationRequest.aidl b/core/java/android/net/RecommendationRequest.aidl
new file mode 100644
index 0000000..76497b8
--- /dev/null
+++ b/core/java/android/net/RecommendationRequest.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.net;
+
+parcelable RecommendationRequest;
diff --git a/core/java/android/net/RecommendationRequest.java b/core/java/android/net/RecommendationRequest.java
new file mode 100644
index 0000000..05ca1aa
--- /dev/null
+++ b/core/java/android/net/RecommendationRequest.java
@@ -0,0 +1,137 @@
+/*
+ * 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.net;
+
+
+import android.annotation.SystemApi;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * A request for a network recommendation.
+ *
+ * @see {@link NetworkScoreManager#requestRecommendation(RecommendationRequest)}.
+ * @hide
+ */
+@SystemApi
+public final class RecommendationRequest implements Parcelable {
+ private final ScanResult[] mScanResults;
+ private final WifiConfiguration mCurrentSelectedConfig;
+ private final NetworkCapabilities mRequiredCapabilities;
+
+ /**
+ * Builder class for constructing {@link RecommendationRequest} instances.
+ * @hide
+ */
+ public static final class Builder {
+ private ScanResult[] mScanResults;
+ private WifiConfiguration mCurrentConfig;
+ private NetworkCapabilities mNetworkCapabilities;
+
+ public Builder setScanResults(ScanResult[] scanResults) {
+ mScanResults = scanResults;
+ return this;
+ }
+
+ public Builder setCurrentRecommendedWifiConfig(WifiConfiguration config) {
+ this.mCurrentConfig = config;
+ return this;
+ }
+
+ public Builder setNetworkCapabilities(NetworkCapabilities capabilities) {
+ mNetworkCapabilities = capabilities;
+ return this;
+ }
+
+ public RecommendationRequest build() {
+ return new RecommendationRequest(mScanResults, mCurrentConfig, mNetworkCapabilities);
+ }
+ }
+
+ /**
+ * @return the array of {@link ScanResult}s the recommendation must be constrained to i.e. if a
+ * non-null wifi config recommendation is returned then it must be able to connect to
+ * one of the networks in the results list.
+ *
+ * If the array is {@code null} or empty then there is no constraint.
+ */
+ public ScanResult[] getScanResults() {
+ return mScanResults;
+ }
+
+ /**
+ * @return The best recommendation at the time this {@code RecommendationRequest} instance
+ * was created. This may be null which indicates that no recommendation is available.
+ */
+ public WifiConfiguration getCurrentSelectedConfig() {
+ return mCurrentSelectedConfig;
+ }
+
+ /**
+ *
+ * @return The set of {@link NetworkCapabilities} the recommendation must be constrained to.
+ * This may be {@code null} which indicates that there are no constraints on the
+ * capabilities of the recommended network.
+ */
+ public NetworkCapabilities getRequiredCapabilities() {
+ return mRequiredCapabilities;
+ }
+
+ @VisibleForTesting
+ RecommendationRequest(ScanResult[] scanResults,
+ WifiConfiguration currentSelectedConfig,
+ NetworkCapabilities requiredCapabilities) {
+ mScanResults = scanResults;
+ mCurrentSelectedConfig = currentSelectedConfig;
+ mRequiredCapabilities = requiredCapabilities;
+ }
+
+ protected RecommendationRequest(Parcel in) {
+ mScanResults = (ScanResult[]) in.readParcelableArray(ScanResult.class.getClassLoader());
+ mCurrentSelectedConfig = in.readParcelable(WifiConfiguration.class.getClassLoader());
+ mRequiredCapabilities = in.readParcelable(NetworkCapabilities.class.getClassLoader());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelableArray(mScanResults, flags);
+ dest.writeParcelable(mCurrentSelectedConfig, flags);
+ dest.writeParcelable(mRequiredCapabilities, flags);
+ }
+
+ public static final Creator<RecommendationRequest> CREATOR =
+ new Creator<RecommendationRequest>() {
+ @Override
+ public RecommendationRequest createFromParcel(Parcel in) {
+ return new RecommendationRequest(in);
+ }
+
+ @Override
+ public RecommendationRequest[] newArray(int size) {
+ return new RecommendationRequest[size];
+ }
+ };
+}
diff --git a/core/java/android/net/RecommendationResult.aidl b/core/java/android/net/RecommendationResult.aidl
new file mode 100644
index 0000000..f36995b
--- /dev/null
+++ b/core/java/android/net/RecommendationResult.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.net;
+
+parcelable RecommendationResult;
diff --git a/core/java/android/net/RecommendationResult.java b/core/java/android/net/RecommendationResult.java
new file mode 100644
index 0000000..a330d84
--- /dev/null
+++ b/core/java/android/net/RecommendationResult.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.net;
+
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.net.wifi.WifiConfiguration;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * The result of a network recommendation.
+ *
+ * @see {@link NetworkScoreManager#requestRecommendation(RecommendationRequest)}.
+ * @hide
+ */
+@SystemApi
+public final class RecommendationResult implements Parcelable {
+ private final WifiConfiguration mWifiConfiguration;
+
+ public RecommendationResult(@Nullable WifiConfiguration wifiConfiguration) {
+ mWifiConfiguration = wifiConfiguration;
+ }
+
+ private RecommendationResult(Parcel in) {
+ mWifiConfiguration = in.readParcelable(WifiConfiguration.class.getClassLoader());
+ }
+
+ /**
+ * @return The recommended {@link WifiConfiguration} to connect to. A {@code null} value
+ * indicates that no WiFi connection should be attempted at this time.
+ */
+ public WifiConfiguration getWifiConfiguration() {
+ return mWifiConfiguration;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(mWifiConfiguration, flags);
+ }
+
+ public static final Creator<RecommendationResult> CREATOR =
+ new Creator<RecommendationResult>() {
+ @Override
+ public RecommendationResult createFromParcel(Parcel in) {
+ return new RecommendationResult(in);
+ }
+
+ @Override
+ public RecommendationResult[] newArray(int size) {
+ return new RecommendationResult[size];
+ }
+ };
+}
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index 8582150..cf81e91 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.SystemApi;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,6 +30,20 @@
*/
@SystemApi
public class ScoredNetwork implements Parcelable {
+ /**
+ * Extra used with {@link #attributes} to specify whether the
+ * network is believed to have a captive portal.
+ * <p>
+ * This data may be used, for example, to display a visual indicator
+ * in a network selection list.
+ * <p>
+ * Note that the this extra conveys the possible presence of a
+ * captive portal, not its state or the user's ability to open
+ * the portal.
+ * <p>
+ * If no value is associated with this key then it's unknown.
+ */
+ public static final String EXTRA_HAS_CAPTIVE_PORTAL = "android.net.extra.HAS_CAPTIVE_PORTAL";
/** A {@link NetworkKey} uniquely identifying this network. */
public final NetworkKey networkKey;
@@ -53,6 +68,14 @@
public final boolean meteredHint;
/**
+ * An additional collection of optional attributes set by
+ * the Network Recommendation Provider.
+ *
+ * @see #EXTRA_HAS_CAPTIVE_PORTAL
+ */
+ public final Bundle attributes;
+
+ /**
* Construct a new {@link ScoredNetwork}.
*
* @param networkKey the {@link NetworkKey} uniquely identifying this network.
@@ -81,9 +104,29 @@
* metered.
*/
public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve, boolean meteredHint) {
+ this(networkKey, rssiCurve, meteredHint, null /* attributes */);
+ }
+
+ /**
+ * Construct a new {@link ScoredNetwork}.
+ *
+ * @param networkKey the {@link NetworkKey} uniquely identifying this network
+ * @param rssiCurve the {@link RssiCurve} representing the scores for this network based on the
+ * RSSI. This field is optional, and may be skipped to represent a network which the scorer
+ * has opted not to score at this time. Passing a null value here is strongly preferred to
+ * not returning any {@link ScoredNetwork} for a given {@link NetworkKey} because it
+ * indicates to the system not to request scores for this network in the future, although
+ * the scorer may choose to issue an out-of-band update at any time.
+ * @param meteredHint a boolean value indicating whether or not the network is believed to be
+ * metered
+ * @param attributes optional provider specific attributes
+ */
+ public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve, boolean meteredHint,
+ Bundle attributes) {
this.networkKey = networkKey;
this.rssiCurve = rssiCurve;
this.meteredHint = meteredHint;
+ this.attributes = attributes;
}
private ScoredNetwork(Parcel in) {
@@ -94,6 +137,7 @@
rssiCurve = null;
}
meteredHint = in.readByte() != 0;
+ attributes = in.readBundle();
}
@Override
@@ -111,6 +155,8 @@
out.writeByte((byte) 0);
}
out.writeByte((byte) (meteredHint ? 1 : 0));
+ out.writeBundle(attributes);
+
}
@Override
@@ -121,19 +167,24 @@
ScoredNetwork that = (ScoredNetwork) o;
return Objects.equals(networkKey, that.networkKey)
- && Objects.equals(rssiCurve, that.rssiCurve)
- && Objects.equals(meteredHint, that.meteredHint);
+ && Objects.equals(rssiCurve, that.rssiCurve)
+ && Objects.equals(meteredHint, that.meteredHint)
+ && Objects.equals(attributes, that.attributes);
}
@Override
public int hashCode() {
- return Objects.hash(networkKey, rssiCurve, meteredHint);
+ return Objects.hash(networkKey, rssiCurve, meteredHint, attributes);
}
@Override
public String toString() {
- return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve
- + ",meteredHint=" + meteredHint + "]";
+ return "ScoredNetwork{" +
+ "networkKey=" + networkKey +
+ ", rssiCurve=" + rssiCurve +
+ ", meteredHint=" + meteredHint +
+ ", attributes=" + attributes +
+ '}';
}
public static final Parcelable.Creator<ScoredNetwork> CREATOR =
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index cf9243f..cea56b5 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -36,8 +36,7 @@
* }
* </pre>
*/
-public class SntpClient
-{
+public class SntpClient {
private static final String TAG = "SntpClient";
private static final boolean DBG = true;
@@ -88,6 +87,7 @@
try {
address = InetAddress.getByName(host);
} catch (Exception e) {
+ EventLogTags.writeNtpFailure(host, e.toString());
if (DBG) Log.d(TAG, "request time failed: " + e);
return false;
}
@@ -142,6 +142,7 @@
// = (transit + skew - transit + skew)/2
// = (2 * skew)/2 = skew
long clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime))/2;
+ EventLogTags.writeNtpSuccess(address.toString(), roundTripTime, clockOffset);
if (DBG) {
Log.d(TAG, "round trip: " + roundTripTime + "ms, " +
"clock offset: " + clockOffset + "ms");
@@ -153,6 +154,7 @@
mNtpTimeReference = responseTicks;
mRoundTripTime = roundTripTime;
} catch (Exception e) {
+ EventLogTags.writeNtpFailure(address.toString(), e.toString());
if (DBG) Log.d(TAG, "request time failed: " + e);
return false;
} finally {
diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java
index 3b3fa69..0667495 100644
--- a/core/java/android/net/metrics/NetworkEvent.java
+++ b/core/java/android/net/metrics/NetworkEvent.java
@@ -42,6 +42,15 @@
public static final int NETWORK_DISCONNECTED = 7;
/** {@hide} */
+ public static final int NETWORK_FIRST_VALIDATION_SUCCESS = 8;
+ /** {@hide} */
+ public static final int NETWORK_REVALIDATION_SUCCESS = 9;
+ /** {@hide} */
+ public static final int NETWORK_FIRST_VALIDATION_PORTAL_FOUND = 10;
+ /** {@hide} */
+ public static final int NETWORK_REVALIDATION_PORTAL_FOUND = 11;
+
+ /** {@hide} */
@IntDef(value = {
NETWORK_CONNECTED,
NETWORK_VALIDATED,
@@ -50,6 +59,10 @@
NETWORK_LINGER,
NETWORK_UNLINGER,
NETWORK_DISCONNECTED,
+ NETWORK_FIRST_VALIDATION_SUCCESS,
+ NETWORK_REVALIDATION_SUCCESS,
+ NETWORK_FIRST_VALIDATION_PORTAL_FOUND,
+ NETWORK_REVALIDATION_PORTAL_FOUND,
})
@Retention(RetentionPolicy.SOURCE)
public @interface EventType {}
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index 1a31b56..a724ec1 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -44,10 +44,8 @@
public static final int DNS_FAILURE = 0;
public static final int DNS_SUCCESS = 1;
- /** {@hide} */
- @IntDef(value = {PROBE_DNS, PROBE_HTTP, PROBE_HTTPS, PROBE_PAC})
- @Retention(RetentionPolicy.SOURCE)
- public @interface ProbeType {}
+ private static final int FIRST_VALIDATION = 1 << 8;
+ private static final int REVALIDATION = 2 << 8;
/** {@hide} */
@IntDef(value = {DNS_FAILURE, DNS_SUCCESS})
@@ -56,12 +54,17 @@
public final int netId;
public final long durationMs;
- public final @ProbeType int probeType;
+ // probeType byte format (MSB to LSB):
+ // byte 0: unused
+ // byte 1: unused
+ // byte 2: 0 = UNKNOWN, 1 = FIRST_VALIDATION, 2 = REVALIDATION
+ // byte 3: PROBE_* constant
+ public final int probeType;
public final @ReturnCode int returnCode;
/** {@hide} */
public ValidationProbeEvent(
- int netId, long durationMs, @ProbeType int probeType, @ReturnCode int returnCode) {
+ int netId, long durationMs, int probeType, @ReturnCode int returnCode) {
this.netId = netId;
this.durationMs = durationMs;
this.probeType = probeType;
@@ -100,8 +103,18 @@
};
/** @hide */
+ public static int makeProbeType(int probeType, boolean firstValidation) {
+ return (probeType & 0xff) | (firstValidation ? FIRST_VALIDATION : REVALIDATION);
+ }
+
+ /** @hide */
public static String getProbeName(int probeType) {
- return Decoder.constants.get(probeType, "PROBE_???");
+ return Decoder.constants.get(probeType & 0xff, "PROBE_???");
+ }
+
+ /** @hide */
+ public static String getValidationStage(int probeType) {
+ return Decoder.constants.get(probeType & 0xff00, "UNKNOWN");
}
public static void logEvent(int netId, long durationMs, int probeType, int returnCode) {
@@ -109,12 +122,13 @@
@Override
public String toString() {
- return String.format("ValidationProbeEvent(%d, %s:%d, %dms)",
- netId, getProbeName(probeType), returnCode, durationMs);
+ return String.format("ValidationProbeEvent(%d, %s:%d %s, %dms)", netId,
+ getProbeName(probeType), returnCode, getValidationStage(probeType), durationMs);
}
final static class Decoder {
static final SparseArray<String> constants = MessageUtils.findMessageNames(
- new Class[]{ValidationProbeEvent.class}, new String[]{"PROBE_"});
+ new Class[]{ValidationProbeEvent.class},
+ new String[]{"PROBE_", "FIRST_", "REVALIDATION"});
}
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 3d5d900..e5aeb4b 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -182,7 +182,7 @@
* New in version 19:
* - Wakelock data (wl) gets current and max times.
*/
- static final String CHECKIN_VERSION = "19";
+ static final String CHECKIN_VERSION = "20";
/**
* Old version, we hit 9 and ran out of room, need to remove.
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 9dafe29..d443b66 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -87,4 +87,6 @@
in String[] disallowedPackages);
boolean isUserUnlockingOrUnlocked(int userId);
int getManagedProfileBadge(int userId);
+ boolean isUserUnlocked(int userId);
+ boolean isUserRunning(int userId);
}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 85f999b..e15f086a 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1297,6 +1297,29 @@
}
/**
+ * Flatten a {@code List} containing arbitrary {@code Parcelable} objects into this parcel
+ * at the current position. They can later be retrieved using
+ * {@link #readParcelableList(List, ClassLoader)} if required.
+ *
+ * @see #readParcelableList(List, ClassLoader)
+ * @hide
+ */
+ public final <T extends Parcelable> void writeParcelableList(List<T> val, int flags) {
+ if (val == null) {
+ writeInt(-1);
+ return;
+ }
+
+ int N = val.size();
+ int i=0;
+ writeInt(N);
+ while (i < N) {
+ writeParcelable(val.get(i), flags);
+ i++;
+ }
+ }
+
+ /**
* Flatten a heterogeneous array containing a particular object type into
* the parcel, at
* the current dataPosition() and growing dataCapacity() if needed. The
@@ -2244,9 +2267,6 @@
* Read into the given List items IBinder objects that were written with
* {@link #writeBinderList} at the current dataPosition().
*
- * @return A newly created ArrayList containing strings with the same data
- * as those that were previously written.
- *
* @see #writeBinderList
*/
public final void readBinderList(List<IBinder> list) {
@@ -2265,6 +2285,34 @@
}
/**
+ * Read the list of {@code Parcelable} objects at the current data position into the
+ * given {@code list}. The contents of the {@code list} are replaced. If the serialized
+ * list was {@code null}, {@code list} is cleared.
+ *
+ * @see #writeParcelableList(List, int)
+ * @hide
+ */
+ public final <T extends Parcelable> void readParcelableList(List<T> list, ClassLoader cl) {
+ final int N = readInt();
+ if (N == -1) {
+ list.clear();
+ return;
+ }
+
+ final int M = list.size();
+ int i = 0;
+ for (; i < M && i < N; i++) {
+ list.set(i, (T) readParcelable(cl));
+ }
+ for (; i<N; i++) {
+ list.add((T) readParcelable(cl));
+ }
+ for (; i<M; i++) {
+ list.remove(N);
+ }
+ }
+
+ /**
* Read and return a new array containing a particular object type from
* the parcel at the current dataPosition(). Returns null if the
* previously written array was null. The array <em>must</em> have
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 8d4d0a5..9d04929 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -421,6 +421,12 @@
public static final String REBOOT_SAFE_MODE = "safemode";
/**
+ * The 'reason' value used when rebooting the device without turning on the screen.
+ * @hide
+ */
+ public static final String REBOOT_QUIESCENT = "quiescent";
+
+ /**
* The value to pass as the 'reason' argument to android_reboot().
* @hide
*/
diff --git a/core/java/android/os/ServiceSpecificException.java b/core/java/android/os/ServiceSpecificException.java
index 04fca19..3e0f6da 100644
--- a/core/java/android/os/ServiceSpecificException.java
+++ b/core/java/android/os/ServiceSpecificException.java
@@ -39,4 +39,9 @@
public ServiceSpecificException(int errorCode) {
this.errorCode = errorCode;
}
+
+ @Override
+ public String toString() {
+ return super.toString() + " (code " + errorCode + ")";
+ }
}
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index f2519be..fd0970e 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1474,9 +1474,6 @@
if (violations == null) {
violations = new ArrayList<ViolationInfo>(1);
gatheredViolations.set(violations);
- } else if (violations.size() >= 5) {
- // Too many. In a loop or something? Don't gather them all.
- return;
}
for (ViolationInfo previous : violations) {
if (info.crashInfo.stackTrace.equals(previous.crashInfo.stackTrace)) {
@@ -1990,18 +1987,14 @@
if (violations == null) {
p.writeInt(0);
} else {
- p.writeInt(violations.size());
- for (int i = 0; i < violations.size(); ++i) {
- int start = p.dataPosition();
- violations.get(i).writeToParcel(p, 0 /* unused flags? */);
- int size = p.dataPosition()-start;
- if (size > 10*1024) {
- Slog.d(TAG, "Wrote violation #" + i + " of " + violations.size() + ": "
- + (p.dataPosition()-start) + " bytes");
- }
+ // To avoid taking up too much transaction space, only include
+ // details for the first 3 violations. Deep inside, CrashInfo
+ // will truncate each stack trace to ~20kB.
+ final int size = Math.min(violations.size(), 3);
+ p.writeInt(size);
+ for (int i = 0; i < size; i++) {
+ violations.get(i).writeToParcel(p, 0);
}
- if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size());
- violations.clear(); // somewhat redundant, as we're about to null the threadlocal
}
gatheredViolations.set(null);
}
@@ -2015,40 +2008,19 @@
/* package */ static void readAndHandleBinderCallViolations(Parcel p) {
// Our own stack trace to append
StringWriter sw = new StringWriter();
+ sw.append("# via Binder call with stack:\n");
PrintWriter pw = new FastPrintWriter(sw, false, 256);
new LogStackTrace().printStackTrace(pw);
pw.flush();
String ourStack = sw.toString();
- int policyMask = getThreadPolicyMask();
- boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
+ final int policyMask = getThreadPolicyMask();
+ final boolean currentlyGathering = (policyMask & PENALTY_GATHER) != 0;
- int numViolations = p.readInt();
- for (int i = 0; i < numViolations; ++i) {
- if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i);
- ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
- if (info.crashInfo.stackTrace != null && info.crashInfo.stackTrace.length() > 30000) {
- String front = info.crashInfo.stackTrace.substring(0, 256);
- // 30000 characters is way too large for this to be any sane kind of
- // strict mode collection of stacks. We've had a problem where we leave
- // strict mode violations associated with the thread, and it keeps tacking
- // more and more stacks on to the violations. Looks like we're in this casse,
- // so we'll report it and bail on all of the current strict mode violations
- // we currently are maintaining for this thread.
- // First, drain the remaining violations from the parcel.
- i++; // Skip the current entry.
- for (; i < numViolations; i++) {
- info = new ViolationInfo(p, !currentlyGathering);
- }
- // Next clear out all gathered violations.
- clearGatheredViolations();
- // Now report the problem.
- Slog.wtfStack(TAG, "Stack is too large: numViolations=" + numViolations
- + " policy=#" + Integer.toHexString(policyMask)
- + " front=" + front);
- return;
- }
- info.crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack;
+ final int size = p.readInt();
+ for (int i = 0; i < size; i++) {
+ final ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
+ info.crashInfo.appendStackTrace(ourStack);
BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
if (policy instanceof AndroidBlockGuardPolicy) {
((AndroidBlockGuardPolicy) policy).handleViolationWithTimingAttempt(info);
@@ -2391,7 +2363,7 @@
* @hide
*/
public static class ViolationInfo implements Parcelable {
- public String message;
+ public final String message;
/**
* Stack and other stuff info.
@@ -2450,6 +2422,7 @@
* Create an uninitialized instance of ViolationInfo
*/
public ViolationInfo() {
+ message = null;
crashInfo = null;
policy = 0;
}
@@ -2496,7 +2469,9 @@
@Override
public int hashCode() {
int result = 17;
- result = 37 * result + crashInfo.stackTrace.hashCode();
+ if (crashInfo != null) {
+ result = 37 * result + crashInfo.stackTrace.hashCode();
+ }
if (numAnimationsRunning != 0) {
result *= 37;
}
@@ -2526,7 +2501,11 @@
*/
public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
message = in.readString();
- crashInfo = new ApplicationErrorReport.CrashInfo(in);
+ if (in.readInt() != 0) {
+ crashInfo = new ApplicationErrorReport.CrashInfo(in);
+ } else {
+ crashInfo = null;
+ }
int rawPolicy = in.readInt();
if (unsetGatheringBit) {
policy = rawPolicy & ~PENALTY_GATHER;
@@ -2548,7 +2527,12 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(message);
- crashInfo.writeToParcel(dest, flags);
+ if (crashInfo != null) {
+ dest.writeInt(1);
+ crashInfo.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
int start = dest.dataPosition();
dest.writeInt(policy);
dest.writeInt(durationMillis);
@@ -2576,7 +2560,9 @@
* Dump a ViolationInfo instance to a Printer.
*/
public void dump(Printer pw, String prefix) {
- crashInfo.dump(pw, prefix);
+ if (crashInfo != null) {
+ crashInfo.dump(pw, prefix);
+ }
pw.println(prefix + "policy: " + policy);
if (durationMillis != -1) {
pw.println(prefix + "durationMillis: " + durationMillis);
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 7e8cc0b8..6c01b36 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -85,6 +85,8 @@
public static final long TRACE_TAG_DATABASE = 1L << 20;
/** @hide */
public static final long TRACE_TAG_NETWORK = 1L << 21;
+ /** @hide */
+ public static final long TRACE_TAG_ADB = 1L << 22;
private static final long TRACE_TAG_NOT_READY = 1L << 63;
private static final int MAX_SECTION_NAME_LEN = 127;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index a79b0c4..0a32f0d 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -187,6 +187,8 @@
* Specifies if a user is disallowed from configuring bluetooth.
* This does <em>not</em> restrict the user from turning bluetooth on or off.
* The default value is <code>false</code>.
+ * <p>This restriction doesn't prevent the user from using bluetooth. For disallowing usage of
+ * bluetooth completely on the device, use {@link #DISALLOW_BLUETOOTH}.
* <p>This restriction has no effect in a managed profile.
*
* <p>Key for user restrictions.
@@ -198,6 +200,20 @@
public static final String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
/**
+ * Specifies if bluetooth is disallowed on the device.
+ *
+ * <p> This restriction can only be set by the device owner and the profile owner on the
+ * primary user and it applies globally - i.e. it disables bluetooth on the entire device.
+ * <p>The default value is <code>false</code>.
+ * <p>Key for user restrictions.
+ * <p>Type: Boolean
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_BLUETOOTH = "no_bluetooth";
+
+ /**
* Specifies if a user is disallowed from transferring files over
* USB. This can only be set by device owners and profile owners on the primary user.
* The default value is <code>false</code>.
@@ -237,6 +253,20 @@
public static final String DISALLOW_REMOVE_USER = "no_remove_user";
/**
+ * Specifies if managed profiles of this user can be removed, other than by its profile owner.
+ * The default value is <code>false</code>.
+ * <p>
+ * This restriction can only be set by device owners.
+ *
+ * <p>Key for user restrictions.
+ * <p>Type: Boolean
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_REMOVE_MANAGED_PROFILE = "no_remove_managed_profile";
+
+ /**
* Specifies if a user is disallowed from enabling or
* accessing debugging features. The default value is <code>false</code>.
*
@@ -306,8 +336,8 @@
public static final String DISALLOW_FACTORY_RESET = "no_factory_reset";
/**
- * Specifies if a user is disallowed from adding new users and
- * profiles. This can only be set by device owners and profile owners on the primary user.
+ * Specifies if a user is disallowed from adding new users. This can only be set by device
+ * owners and profile owners on the primary user.
* The default value is <code>false</code>.
* <p>This restriction has no effect on secondary users and managed profiles since only the
* primary user can add other users.
@@ -321,6 +351,20 @@
public static final String DISALLOW_ADD_USER = "no_add_user";
/**
+ * Specifies if a user is disallowed from adding managed profiles.
+ * <p>The default value for an unmanaged user is <code>false</code>.
+ * For users with a device owner set, the default is <code>true</code>
+ * <p>This restriction can only be set by device owners.
+ *
+ * <p>Key for user restrictions.
+ * <p>Type: Boolean
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_ADD_MANAGED_PROFILE = "no_add_managed_profile";
+
+ /**
* Specifies if a user is disallowed from disabling application
* verification. The default value is <code>false</code>.
*
@@ -618,11 +662,14 @@
* <code>false</code>. Setting this restriction has no effect if the bootloader is already
* unlocked.
*
+ * <p>Not for use by third-party applications.
+ *
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
* @see #getUserRestrictions()
* @hide
*/
+ @SystemApi
public static final String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
/**
@@ -996,10 +1043,9 @@
}
/** {@hide} */
- public boolean isUserRunning(int userId) {
- // TODO Switch to using UMS internal isUserRunning
+ public boolean isUserRunning(@UserIdInt int userId) {
try {
- return ActivityManager.getService().isUserRunning(userId, 0);
+ return mService.isUserRunning(userId);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -1096,8 +1142,7 @@
/** {@hide} */
public boolean isUserUnlocked(@UserIdInt int userId) {
try {
- return ActivityManager.getService().isUserRunning(userId,
- ActivityManager.FLAG_AND_UNLOCKED);
+ return mService.isUserUnlocked(userId);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -1389,7 +1434,7 @@
/**
* Similar to {@link #createProfileForUser(String, int, int, String[])}
- * except bypassing the checking of {@link UserManager#DISALLOW_ADD_USER}.
+ * except bypassing the checking of {@link UserManager#DISALLOW_ADD_MANAGED_PROFILE}.
* Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
*
* @see #createProfileForUser(String, int, int, String[])
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index 4bdb92b..466a7e3 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -120,7 +120,8 @@
public abstract void onEphemeralUserStop(int userId);
/**
- * Same as UserManager.createUser(), but bypasses the check for DISALLOW_ADD_USER.
+ * Same as UserManager.createUser(), but bypasses the check for
+ * {@link UserManager#DISALLOW_ADD_USER} and {@link UserManager#DISALLOW_ADD_MANAGED_PROFILE}
*
* <p>Called by the {@link com.android.server.devicepolicy.DevicePolicyManagerService} when
* createAndManageUser is called by the device owner.
@@ -129,7 +130,8 @@
/**
* Same as {@link UserManager#removeUser(int userHandle)}, but bypasses the check for
- * {@link UserManager#DISALLOW_REMOVE_USER} and does not require the
+ * {@link UserManager#DISALLOW_REMOVE_USER} and
+ * {@link UserManager#DISALLOW_REMOVE_MANAGED_PROFILE} and does not require the
* {@link android.Manifest.permission#MANAGE_USERS} permission.
*/
public abstract boolean removeUserEvenWhenDisallowed(int userId);
@@ -142,6 +144,12 @@
public abstract boolean isUserUnlockingOrUnlocked(int userId);
/**
+ * Return whether the given user is running in an
+ * {@code UserState.STATE_RUNNING_UNLOCKED} state.
+ */
+ public abstract boolean isUserUnlocked(int userId);
+
+ /**
* Return whether the given user is running
*/
public abstract boolean isUserRunning(int userId);
diff --git a/core/java/android/provider/SearchIndexablesContract.java b/core/java/android/provider/SearchIndexablesContract.java
index 93ac7f6..ff8b9dd 100644
--- a/core/java/android/provider/SearchIndexablesContract.java
+++ b/core/java/android/provider/SearchIndexablesContract.java
@@ -108,6 +108,8 @@
RawData.COLUMN_INTENT_TARGET_CLASS, // 11
RawData.COLUMN_KEY, // 12
RawData.COLUMN_USER_ID, // 13
+ RawData.PAYLOAD_TYPE, // 14
+ RawData.PAYLOAD // 15
};
/**
@@ -127,6 +129,14 @@
public static final int COLUMN_INDEX_RAW_INTENT_TARGET_CLASS = 11;
public static final int COLUMN_INDEX_RAW_KEY = 12;
public static final int COLUMN_INDEX_RAW_USER_ID = 13;
+ /**
+ * @hide
+ */
+ public static final int COLUMN_INDEX_RAW_PAYLOAD_TYPE = 14;
+ /**
+ * @hide
+ */
+ public static final int COLUMN_INDEX_RAW_PAYLOAD = 15;
/**
* Indexable raw data columns.
@@ -213,6 +223,18 @@
* UserId associated with the raw data.
*/
public static final String COLUMN_USER_ID = "user_id";
+
+ /**
+ * Identifier for the Payload object type.
+ * @hide
+ */
+ public static final String PAYLOAD_TYPE = "payload_type";
+
+ /**
+ * Generic payload for improving Search result expressiveness.
+ * @hide
+ */
+ public static final String PAYLOAD = "payload";
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0946906..37222ad 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -44,6 +44,7 @@
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
+import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.DropBoxManager;
import android.os.IBinder;
@@ -52,7 +53,6 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.os.Build.VERSION_CODES;
import android.speech.tts.TextToSpeech;
import android.text.TextUtils;
import android.util.AndroidException;
@@ -1321,6 +1321,20 @@
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_WEBVIEW_SETTINGS = "android.settings.WEBVIEW_SETTINGS";
+ /**
+ * Activity Action: Show enterprise privacy section.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS
+ = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
+
// End of Intent actions for Settings
/**
@@ -1566,12 +1580,13 @@
private final Uri mUri;
- private static final String[] SELECT_VALUE =
- new String[] { Settings.NameValueTable.VALUE };
+ private static final String[] SELECT_VALUE_PROJECTION = new String[] {
+ Settings.NameValueTable.VALUE
+ };
private static final String NAME_EQ_PLACEHOLDER = "name=?";
// Must synchronize on 'this' to access mValues and mValuesVersion.
- private final HashMap<String, String> mValues = new HashMap<String, String>();
+ private final HashMap<String, String> mValues = new HashMap<>();
// Initially null; set lazily and held forever. Synchronized on 'this'.
private IContentProvider mContentProvider = null;
@@ -1724,8 +1739,9 @@
Cursor c = null;
try {
- c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE, NAME_EQ_PLACEHOLDER,
- new String[]{name}, null, null);
+ Bundle queryArgs = ContentResolver.createSqlQueryBundle(
+ NAME_EQ_PLACEHOLDER, new String[]{name}, null);
+ c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs, null);
if (c == null) {
Log.w(TAG, "Can't get key " + name + " from " + mUri);
return null;
@@ -1793,7 +1809,7 @@
private static final HashSet<String> MOVED_TO_SECURE;
static {
- MOVED_TO_SECURE = new HashSet<String>(30);
+ MOVED_TO_SECURE = new HashSet<>(30);
MOVED_TO_SECURE.add(Secure.ANDROID_ID);
MOVED_TO_SECURE.add(Secure.HTTP_PROXY);
MOVED_TO_SECURE.add(Secure.LOCATION_PROVIDERS_ALLOWED);
@@ -1830,8 +1846,8 @@
private static final HashSet<String> MOVED_TO_GLOBAL;
private static final HashSet<String> MOVED_TO_SECURE_THEN_GLOBAL;
static {
- MOVED_TO_GLOBAL = new HashSet<String>();
- MOVED_TO_SECURE_THEN_GLOBAL = new HashSet<String>();
+ MOVED_TO_GLOBAL = new HashSet<>();
+ MOVED_TO_SECURE_THEN_GLOBAL = new HashSet<>();
// these were originally in system but migrated to secure in the past,
// so are duplicated in the Secure.* namespace
@@ -4149,12 +4165,12 @@
private static final HashSet<String> MOVED_TO_LOCK_SETTINGS;
private static final HashSet<String> MOVED_TO_GLOBAL;
static {
- MOVED_TO_LOCK_SETTINGS = new HashSet<String>(3);
+ MOVED_TO_LOCK_SETTINGS = new HashSet<>(3);
MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_ENABLED);
MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_VISIBLE);
MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
- MOVED_TO_GLOBAL = new HashSet<String>();
+ MOVED_TO_GLOBAL = new HashSet<>();
MOVED_TO_GLOBAL.add(Settings.Global.ADB_ENABLED);
MOVED_TO_GLOBAL.add(Settings.Global.ASSISTED_GPS_ENABLED);
MOVED_TO_GLOBAL.add(Settings.Global.BLUETOOTH_ON);
@@ -5189,6 +5205,7 @@
* @hide
* @deprecated
*/
+ @Deprecated
public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE =
"accessibility_display_magnification_auto_update";
@@ -6443,7 +6460,7 @@
* @hide
*/
public static final String DOWNLOADS_BACKUP_ENABLED = "downloads_backup_enabled";
-
+
/**
* Whether Downloads folder backup should only occur if the device is using a metered
* network.
@@ -7741,6 +7758,26 @@
public static final String WIFI_SCAN_ALWAYS_AVAILABLE =
"wifi_scan_always_enabled";
+ /**
+ * Value to specify if Wi-Fi Wakeup feature is enabled.
+ *
+ * Type: int (0 for false, 1 for true)
+ * @hide
+ */
+ @SystemApi
+ public static final String WIFI_WAKEUP_ENABLED = "wifi_wakeup_enabled";
+
+ /**
+ * Value to specify if network recommendations from
+ * {@link com.android.server.NetworkScoreService} are enabled.
+ *
+ * Type: int (0 for false, 1 for true)
+ * @hide
+ */
+ @SystemApi
+ public static final String NETWORK_RECOMMENDATIONS_ENABLED =
+ "network_recommendations_enabled";
+
/**
* Settings to allow BLE scans to be enabled even when Bluetooth is turned off for
* connectivity.
@@ -9105,7 +9142,7 @@
// Certain settings have been moved from global to the per-user secure namespace
private static final HashSet<String> MOVED_TO_SECURE;
static {
- MOVED_TO_SECURE = new HashSet<String>(1);
+ MOVED_TO_SECURE = new HashSet<>(1);
MOVED_TO_SECURE.add(Settings.Global.INSTALL_NON_MARKET_APPS);
}
diff --git a/core/java/android/security/net/config/ManifestConfigSource.java b/core/java/android/security/net/config/ManifestConfigSource.java
index 92bddb7..0f2994d 100644
--- a/core/java/android/security/net/config/ManifestConfigSource.java
+++ b/core/java/android/security/net/config/ManifestConfigSource.java
@@ -32,6 +32,7 @@
private final int mApplicationInfoFlags;
private final int mTargetSdkVersion;
private final int mConfigResourceId;
+ private final boolean mEphemeralApp;
private ConfigSource mConfigSource;
@@ -42,6 +43,7 @@
mApplicationInfoFlags = info.flags;
mTargetSdkVersion = info.targetSdkVersion;
mConfigResourceId = info.networkSecurityConfigRes;
+ mEphemeralApp = info.isEphemeralApp();
}
@Override
@@ -69,14 +71,18 @@
+ " debugBuild: " + debugBuild);
}
source = new XmlConfigSource(mContext, mConfigResourceId, debugBuild,
- mTargetSdkVersion);
+ mTargetSdkVersion, mEphemeralApp);
} else {
if (DBG) {
Log.d(LOG_TAG, "No Network Security Config specified, using platform default");
}
+ // the legacy FLAG_USES_CLEARTEXT_TRAFFIC is not supported for Ephemeral apps, they
+ // should use the network security config.
boolean usesCleartextTraffic =
- (mApplicationInfoFlags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0;
- source = new DefaultConfigSource(usesCleartextTraffic, mTargetSdkVersion);
+ (mApplicationInfoFlags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0
+ && !mEphemeralApp;
+ source = new DefaultConfigSource(usesCleartextTraffic, mTargetSdkVersion,
+ mEphemeralApp);
}
mConfigSource = source;
return mConfigSource;
@@ -87,8 +93,10 @@
private final NetworkSecurityConfig mDefaultConfig;
- public DefaultConfigSource(boolean usesCleartextTraffic, int targetSdkVersion) {
- mDefaultConfig = NetworkSecurityConfig.getDefaultBuilder(targetSdkVersion)
+ public DefaultConfigSource(boolean usesCleartextTraffic, int targetSdkVersion,
+ boolean ephemeralApp) {
+ mDefaultConfig = NetworkSecurityConfig.getDefaultBuilder(targetSdkVersion,
+ ephemeralApp)
.setCleartextTrafficPermitted(usesCleartextTraffic)
.build();
}
diff --git a/core/java/android/security/net/config/NetworkSecurityConfig.java b/core/java/android/security/net/config/NetworkSecurityConfig.java
index b3a37d0..7923702 100644
--- a/core/java/android/security/net/config/NetworkSecurityConfig.java
+++ b/core/java/android/security/net/config/NetworkSecurityConfig.java
@@ -164,7 +164,8 @@
* <p>
* The default configuration has the following properties:
* <ol>
- * <li>Cleartext traffic is permitted.</li>
+ * <li>Cleartext traffic is permitted for non-ephemeral apps.</li>
+ * <li>Cleartext traffic is not permitted for ephemeral apps.</li>
* <li>HSTS is not enforced.</li>
* <li>No certificate pinning is used.</li>
* <li>The system certificate store is trusted for connections.</li>
@@ -174,9 +175,9 @@
*
* @hide
*/
- public static final Builder getDefaultBuilder(int targetSdkVersion) {
+ public static final Builder getDefaultBuilder(int targetSdkVersion, boolean ephemeralApp) {
Builder builder = new Builder()
- .setCleartextTrafficPermitted(DEFAULT_CLEARTEXT_TRAFFIC_PERMITTED)
+ .setCleartextTrafficPermitted(!ephemeralApp)
.setHstsEnforced(DEFAULT_HSTS_ENFORCED)
// System certificate store, does not bypass static pins.
.addCertificatesEntryRef(
diff --git a/core/java/android/security/net/config/XmlConfigSource.java b/core/java/android/security/net/config/XmlConfigSource.java
index 4a5f827..38fe6b8 100644
--- a/core/java/android/security/net/config/XmlConfigSource.java
+++ b/core/java/android/security/net/config/XmlConfigSource.java
@@ -37,6 +37,7 @@
private final int mResourceId;
private final boolean mDebugBuild;
private final int mTargetSdkVersion;
+ private final boolean mEphemeralApp;
private boolean mInitialized;
private NetworkSecurityConfig mDefaultConfig;
@@ -53,12 +54,19 @@
this(context, resourceId, debugBuild, Build.VERSION_CODES.CUR_DEVELOPMENT);
}
+ @VisibleForTesting
public XmlConfigSource(Context context, int resourceId, boolean debugBuild,
int targetSdkVersion) {
+ this(context, resourceId, debugBuild, targetSdkVersion, false);
+ }
+
+ public XmlConfigSource(Context context, int resourceId, boolean debugBuild,
+ int targetSdkVersion, boolean ephemeralApp) {
mResourceId = resourceId;
mContext = context;
mDebugBuild = debugBuild;
mTargetSdkVersion = targetSdkVersion;
+ mEphemeralApp = ephemeralApp;
}
public Set<Pair<Domain, NetworkSecurityConfig>> getPerDomainConfigs() {
@@ -357,7 +365,7 @@
// Use the platform default as the parent of the base config for any values not provided
// there. If there is no base config use the platform default.
NetworkSecurityConfig.Builder platformDefaultBuilder =
- NetworkSecurityConfig.getDefaultBuilder(mTargetSdkVersion);
+ NetworkSecurityConfig.getDefaultBuilder(mTargetSdkVersion, mEphemeralApp);
addDebugAnchorsIfNeeded(debugConfigBuilder, platformDefaultBuilder);
if (baseConfigBuilder != null) {
baseConfigBuilder.setParent(platformDefaultBuilder);
diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java
index 5f27e34..a7941c7 100644
--- a/core/java/android/service/autofill/AutoFillService.java
+++ b/core/java/android/service/autofill/AutoFillService.java
@@ -15,6 +15,11 @@
*/
package android.service.autofill;
+import static android.service.voice.VoiceInteractionSession.KEY_FLAGS;
+import static android.service.voice.VoiceInteractionSession.KEY_STRUCTURE;
+import static android.view.View.ASSIST_FLAG_SANITIZED_TEXT;
+import static android.view.View.ASSIST_FLAG_NON_SANITIZED_TEXT;
+
import android.annotation.SdkConstant;
import android.app.Activity;
import android.app.Service;
@@ -26,13 +31,14 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
-import android.service.voice.VoiceInteractionSession;
import android.util.Log;
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.IResultReceiver;
import com.android.internal.os.SomeArgs;
+// TODO(b/33197203): improve javadoc (class and methods)
+
/**
* Top-level service of the current auto-fill service for a given user.
*
@@ -52,6 +58,11 @@
@SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
public static final String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
+ // Bundle keys.
+ /** @hide */
+ public static final String KEY_CALLBACK = "callback";
+
+ // Handler messages.
private static final int MSG_CONNECT = 1;
private static final int MSG_AUTO_FILL_ACTIVITY = 2;
private static final int MSG_DISCONNECT = 3;
@@ -59,14 +70,12 @@
private final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() {
@Override
public void send(int resultCode, Bundle resultData) throws RemoteException {
- final AssistStructure structure = resultData
- .getParcelable(VoiceInteractionSession.KEY_STRUCTURE);
-
- final IBinder binder = resultData
- .getBinder(VoiceInteractionSession.KEY_AUTO_FILL_CALLBACK);
+ final AssistStructure structure = resultData.getParcelable(KEY_STRUCTURE);
+ final IBinder binder = resultData.getBinder(KEY_CALLBACK);
+ final int flags = resultData.getInt(KEY_FLAGS, 0);
mHandlerCaller
- .obtainMessageOO(MSG_AUTO_FILL_ACTIVITY, structure, binder).sendToTarget();
+ .obtainMessageIOO(MSG_AUTO_FILL_ACTIVITY, flags, structure, binder).sendToTarget();
}
};
@@ -100,7 +109,8 @@
final SomeArgs args = (SomeArgs) msg.obj;
final AssistStructure structure = (AssistStructure) args.arg1;
final IBinder binder = (IBinder) args.arg2;
- requestAutoFill(structure, binder);
+ final int flags = msg.arg1;
+ requestAutoFill(structure, flags, binder);
break;
} case MSG_DISCONNECT: {
onDisconnected();
@@ -145,19 +155,46 @@
}
/**
- * Handles an auto-fill request.
+ * Called when user requests service to auto-fill an {@link Activity}.
*
* @param structure {@link Activity}'s view structure .
+ * @param data bundle with optional parameters (currently none) which is passed along on
+ * subsequent calls (so it can be used by the service to share data).
* @param cancellationSignal signal for observing cancel requests.
- * @param callback object used to fulllfill the request.
*/
public abstract void onFillRequest(AssistStructure structure,
- CancellationSignal cancellationSignal, FillCallback callback);
+ Bundle data, CancellationSignal cancellationSignal, FillCallback callback);
- private void requestAutoFill(AssistStructure structure, IBinder binder) {
- final FillCallback callback = new FillCallback(binder);
- // TODO: hook up the cancelationSignal
- onFillRequest(structure, new CancellationSignal(), callback);
+ /**
+ * Called when user requests service to save the fields of an {@link Activity}.
+ *
+ * @param structure {@link Activity}'s view structure.
+ * @param data same bundle passed to
+ * {@link #onFillRequest(AssistStructure, Bundle, CancellationSignal, FillCallback)};
+ * might also contain with optional parameters (currently none).
+ * @param cancellationSignal signal for observing cancel requests.
+ * @param callback object used to notify the result of the request.
+ */
+ public abstract void onSaveRequest(AssistStructure structure,
+ Bundle data, CancellationSignal cancellationSignal, SaveCallback callback);
+
+ private void requestAutoFill(AssistStructure structure, int flags, IBinder binder) {
+ // TODO(b/33197203): pass the Bundle received from mAssistReceiver instead?
+ final Bundle data = new Bundle();
+ switch (flags) {
+ case ASSIST_FLAG_SANITIZED_TEXT:
+ final FillCallback fillCallback = new FillCallback(binder);
+ // TODO(b/33197203): hook up the cancelationSignal
+ onFillRequest(structure, data, new CancellationSignal(), fillCallback);
+ break;
+ case ASSIST_FLAG_NON_SANITIZED_TEXT:
+ final SaveCallback saveCallback = new SaveCallback(binder);
+ // TODO(b/33197203): hook up the cancelationSignal
+ onSaveRequest(structure, null, new CancellationSignal(), saveCallback);
+ break;
+ default:
+ Log.w(TAG, "invalid flag on requestAutoFill(): " + flags);
+ }
}
/**
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index 2308440..3284b90 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -17,7 +17,6 @@
package android.service.autofill;
import static android.service.autofill.AutoFillService.DEBUG;
-import static android.service.autofill.AutoFillService.TAG;
import android.app.Activity;
import android.app.assist.AssistStructure.ViewNode;
@@ -38,6 +37,8 @@
*/
public final class FillCallback {
+ private static final String TAG = "FillCallback";
+
private final IAutoFillCallback mCallback;
/** @hide */
@@ -62,6 +63,13 @@
}
}
+ /**
+ * Notifies the {@link Activity} that the auto-fill request failed.
+ *
+ * @param message error message to be displayed.
+ *
+ * @throws RuntimeException if an error occurred while notifying the activity.
+ */
public void onFailure(CharSequence message) {
if (DEBUG) Log.d(TAG, "onFailure(): message=" + message);
diff --git a/core/java/android/service/autofill/IAutoFillManagerService.aidl b/core/java/android/service/autofill/IAutoFillManagerService.aidl
index 76a2561..f1251c0 100644
--- a/core/java/android/service/autofill/IAutoFillManagerService.aidl
+++ b/core/java/android/service/autofill/IAutoFillManagerService.aidl
@@ -25,11 +25,5 @@
*/
oneway interface IAutoFillManagerService {
- /**
- * Request auto-fill on the top activity of a given user.
- *
- * @param userId user handle.
- * @param activityToken optional token of activity that needs to be on top.
- */
- void requestAutoFill(int userId, IBinder activityToken);
+ void requestAutoFill(IBinder activityToken, int userId, int flags);
}
diff --git a/core/java/android/service/autofill/SaveCallback.java b/core/java/android/service/autofill/SaveCallback.java
new file mode 100644
index 0000000..4dc7392
--- /dev/null
+++ b/core/java/android/service/autofill/SaveCallback.java
@@ -0,0 +1,79 @@
+/*
+ * 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.service.autofill;
+
+import static android.service.autofill.AutoFillService.DEBUG;
+
+import android.app.Activity;
+import android.app.assist.AssistStructure.ViewNode;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Handles save requests from the {@link AutoFillService} into the {@link Activity} being
+ * auto-filled.
+ */
+public final class SaveCallback {
+
+ private static final String TAG = "SaveCallback";
+
+ private final IAutoFillCallback mCallback;
+
+ /** @hide */
+ SaveCallback(IBinder binder) {
+ mCallback = IAutoFillCallback.Stub.asInterface(binder);
+ }
+
+ /**
+ * Notifies the {@link Activity} that the save request succeeded.
+ *
+ * @param ids ids ({@link ViewNode#getAutoFillId()}) of the fields that were saved.
+ *
+ * @throws RuntimeException if an error occurred while saving the data.
+ */
+ public void onSuccess(int[] ids) {
+ Preconditions.checkArgument(ids != null, "ids cannot be null");
+
+ Preconditions.checkArgument(ids.length > 0, "ids cannot be empty");
+
+ if (DEBUG) Log.d(TAG, "onSuccess(): ids=" + ids.length);
+
+ // TODO(b/33197203): display which ids were saved
+ }
+
+ /**
+ * Notifies the {@link Activity} that the save request failed.
+ *
+ * @param message error message to be displayed.
+ *
+ * @throws RuntimeException if an error occurred while notifying the activity.
+ */
+ public void onFailure(CharSequence message) {
+ if (DEBUG) Log.d(TAG, "onFailure(): message=" + message);
+
+ Preconditions.checkArgument(message != null, "message cannot be null");
+
+ try {
+ mCallback.showError(message.toString());
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+}
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 4b272e9..7af93c2 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -15,8 +15,7 @@
*/
package android.service.notification;
-import android.annotation.SystemApi;
-import android.net.Uri;
+import android.app.NotificationChannel;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,33 +26,39 @@
public final class Adjustment implements Parcelable {
private final String mPackage;
private final String mKey;
- private final int mImportance;
private final CharSequence mExplanation;
- private final Uri mReference;
private final Bundle mSignals;
private final int mUser;
/**
+ * Data type: {@code String}. See {@link NotificationChannel#getId()}.
+ */
+ public static final String KEY_CHANNEL_ID = "key_channel_id";
+ /**
+ * Data type: ArrayList of {@code String}, where each is a representation of a
+ * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}.
+ * See {@link android.app.Notification.Builder#addPerson(String)}.
+ */
+ public static final String KEY_PEOPLE = "key_people";
+ /**
+ * Parcelable {@code ArrayList} of {@link SnoozeCriterion}.
+ */
+ public static final String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
+
+ /**
* Create a notification adjustment.
*
* @param pkg The package of the notification.
* @param key The notification key.
- * @param importance The recommended importance of the notification.
- * @param signals A bundle of signals that should inform notification grouping and ordering.
+ * @param signals A bundle of signals that should inform notification display, ordering, and
+ * interruptiveness.
* @param explanation A human-readable justification for the adjustment.
- * @param reference A reference to an external object that augments the
- * explanation, such as a
- * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI},
- * or null.
*/
- public Adjustment(String pkg, String key, int importance, Bundle signals,
- CharSequence explanation, Uri reference, int user) {
+ public Adjustment(String pkg, String key, Bundle signals, CharSequence explanation, int user) {
mPackage = pkg;
mKey = key;
- mImportance = importance;
mSignals = signals;
mExplanation = explanation;
- mReference = reference;
mUser = user;
}
@@ -68,13 +73,11 @@
} else {
mKey = null;
}
- mImportance = in.readInt();
if (in.readInt() == 1) {
mExplanation = in.readCharSequence();
} else {
mExplanation = null;
}
- mReference = in.readParcelable(Uri.class.getClassLoader());
mSignals = in.readBundle();
mUser = in.readInt();
}
@@ -99,18 +102,10 @@
return mKey;
}
- public int getImportance() {
- return mImportance;
- }
-
public CharSequence getExplanation() {
return mExplanation;
}
- public Uri getReference() {
- return mReference;
- }
-
public Bundle getSignals() {
return mSignals;
}
@@ -138,14 +133,12 @@
} else {
dest.writeInt(0);
}
- dest.writeInt(mImportance);
if (mExplanation != null) {
dest.writeInt(1);
dest.writeCharSequence(mExplanation);
} else {
dest.writeInt(0);
}
- dest.writeParcelable(mReference, flags);
dest.writeBundle(mSignals);
dest.writeInt(mUser);
}
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 4e00c64..51ba8c72 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -16,7 +16,10 @@
package android.service.notification;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.app.NotificationChannel;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
@@ -27,6 +30,7 @@
import android.util.Log;
import com.android.internal.os.SomeArgs;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -79,9 +83,10 @@
public final void adjustNotification(Adjustment adjustment) {
if (!isBound()) return;
try {
- getNotificationInterface().applyAdjustmentFromAssistantService(mWrapper, adjustment);
+ getNotificationInterface().applyAdjustmentFromAssistant(mWrapper, adjustment);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -95,12 +100,77 @@
public final void adjustNotifications(List<Adjustment> adjustments) {
if (!isBound()) return;
try {
- getNotificationInterface().applyAdjustmentsFromAssistantService(mWrapper, adjustments);
+ getNotificationInterface().applyAdjustmentsFromAssistant(mWrapper, adjustments);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
+ throw ex.rethrowFromSystemServer();
}
}
+ /**
+ * Creates a notification channel that notifications can be posted to for a given package.
+ *
+ * @param pkg The package to create a channel for.
+ * @param channel the channel to attempt to create.
+ */
+ public void createNotificationChannel(@NonNull String pkg,
+ @NonNull NotificationChannel channel) {
+ if (!isBound()) return;
+ try {
+ getNotificationInterface().createNotificationChannelFromAssistant(
+ mWrapper, pkg, channel);
+ } catch (RemoteException e) {
+ Log.v(TAG, "Unable to contact notification manager", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Updates a notification channel for a given package.
+ *
+ * @param pkg The package to the channel belongs to.
+ * @param channel the channel to attempt to update.
+ */
+ public void updateNotificationChannel(@NonNull String pkg,
+ @NonNull NotificationChannel channel) {
+ if (!isBound()) return;
+ try {
+ getNotificationInterface().updateNotificationChannelFromAssistant(
+ mWrapper, pkg, channel);
+ } catch (RemoteException e) {
+ Log.v(TAG, "Unable to contact notification manager", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns all notification channels belonging to the given package.
+ */
+ public List<NotificationChannel> getNotificationChannels(@NonNull String pkg) {
+ if (!isBound()) return null;
+ try {
+ return getNotificationInterface().getNotificationChannelsFromAssistant(
+ mWrapper, pkg).getList();
+ } catch (RemoteException e) {
+ Log.v(TAG, "Unable to contact notification manager", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Deletes the given notification channel.
+ */
+ public void deleteNotificationChannel(@NonNull String pkg, @NonNull String channelId) {
+ if (!isBound()) return;
+ try {
+ getNotificationInterface().deleteNotificationChannelFromAssistant(
+ mWrapper, pkg, channelId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+
private class NotificationAssistantServiceWrapper extends NotificationListenerWrapper {
@Override
public void onNotificationEnqueued(IStatusBarNotificationHolder sbnHolder,
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 37674a6..1bc605f 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -16,11 +16,11 @@
package android.service.notification;
+import android.app.NotificationChannel;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.annotation.SdkConstant;
import android.app.INotificationManager;
@@ -49,8 +49,7 @@
import android.widget.RemoteViews;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.SomeArgs;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -1112,7 +1111,10 @@
}
}
- private void applyUpdateLocked(NotificationRankingUpdate update) {
+ /**
+ * @hide
+ */
+ public final void applyUpdateLocked(NotificationRankingUpdate update) {
mRankingMap = new RankingMap(update);
}
@@ -1148,6 +1150,12 @@
private CharSequence mImportanceExplanation;
// System specified group key.
private String mOverrideGroupKey;
+ // Notification assistant channel override.
+ private NotificationChannel mOverrideChannel;
+ // Notification assistant people override.
+ private ArrayList<String> mOverridePeople;
+ // Notification assistant snooze criteria.
+ private ArrayList<SnoozeCriterion> mSnoozeCriteria;
public Ranking() {}
@@ -1217,7 +1225,7 @@
}
/**
- * If the importance has been overriden by user preference, then this will be non-null,
+ * If the importance has been overridden by user preference, then this will be non-null,
* and should be displayed to the user.
*
* @return the explanation for the importance, or null if it is the natural importance
@@ -1227,16 +1235,44 @@
}
/**
- * If the system has overriden the group key, then this will be non-null, and this
+ * If the system has overridden the group key, then this will be non-null, and this
* key should be used to bundle notifications.
*/
public String getOverrideGroupKey() {
return mOverrideGroupKey;
}
+ /**
+ * If the {@link NotificationAssistantService} has overridden the channel this notification
+ * was posted to, then this will not match the channel provided by the posting application
+ * and this should be used to determine the interruptiveness of the notification instead.
+ */
+ public NotificationChannel getChannel() {
+ return mOverrideChannel;
+ }
+
+ /**
+ * If the {@link NotificationAssistantService} has added people to this notification, then
+ * this will be non-null.
+ */
+ public List<String> getAdditionalPeople() {
+ return mOverridePeople;
+ }
+
+ /**
+ * Returns snooze criteria provided by the {@link NotificationAssistantService}. If your
+ * user interface displays options for snoozing notifications these criteria should be
+ * displayed as well.
+ */
+ public List<SnoozeCriterion> getSnoozeCriteria() {
+ return mSnoozeCriteria;
+ }
+
private void populate(String key, int rank, boolean matchesInterruptionFilter,
int visibilityOverride, int suppressedVisualEffects, int importance,
- CharSequence explanation, String overrideGroupKey) {
+ CharSequence explanation, String overrideGroupKey,
+ NotificationChannel overrideChannel, ArrayList<String> overridePeople,
+ ArrayList<SnoozeCriterion> snoozeCriteria) {
mKey = key;
mRank = rank;
mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW;
@@ -1246,6 +1282,9 @@
mImportance = importance;
mImportanceExplanation = explanation;
mOverrideGroupKey = overrideGroupKey;
+ mOverrideChannel = overrideChannel;
+ mOverridePeople = overridePeople;
+ mSnoozeCriteria = snoozeCriteria;
}
/**
@@ -1289,6 +1328,9 @@
private ArrayMap<String, Integer> mImportance;
private ArrayMap<String, String> mImportanceExplanation;
private ArrayMap<String, String> mOverrideGroupKeys;
+ private ArrayMap<String, NotificationChannel> mOverrideChannels;
+ private ArrayMap<String, ArrayList<String>> mOverridePeople;
+ private ArrayMap<String, ArrayList<SnoozeCriterion>> mSnoozeCriteria;
private RankingMap(NotificationRankingUpdate rankingUpdate) {
mRankingUpdate = rankingUpdate;
@@ -1315,7 +1357,8 @@
int rank = getRank(key);
outRanking.populate(key, rank, !isIntercepted(key),
getVisibilityOverride(key), getSuppressedVisualEffects(key),
- getImportance(key), getImportanceExplanation(key), getOverrideGroupKey(key));
+ getImportance(key), getImportanceExplanation(key), getOverrideGroupKey(key),
+ getOverrideChannel(key), getOverridePeople(key), getSnoozeCriteria(key));
return rank >= 0;
}
@@ -1395,6 +1438,33 @@
return mOverrideGroupKeys.get(key);
}
+ private NotificationChannel getOverrideChannel(String key) {
+ synchronized (this) {
+ if (mOverrideChannels == null) {
+ buildOverrideChannelsLocked();
+ }
+ }
+ return mOverrideChannels.get(key);
+ }
+
+ private ArrayList<String> getOverridePeople(String key) {
+ synchronized (this) {
+ if (mOverridePeople == null) {
+ buildOverridePeopleLocked();
+ }
+ }
+ return mOverridePeople.get(key);
+ }
+
+ private ArrayList<SnoozeCriterion> getSnoozeCriteria(String key) {
+ synchronized (this) {
+ if (mSnoozeCriteria == null) {
+ buildSnoozeCriteriaLocked();
+ }
+ }
+ return mSnoozeCriteria.get(key);
+ }
+
// Locked by 'this'
private void buildRanksLocked() {
String[] orderedKeys = mRankingUpdate.getOrderedKeys();
@@ -1458,6 +1528,33 @@
}
}
+ // Locked by 'this'
+ private void buildOverrideChannelsLocked() {
+ Bundle overrideChannels = mRankingUpdate.getOverrideChannels();
+ mOverrideChannels = new ArrayMap<>(overrideChannels.size());
+ for (String key : overrideChannels.keySet()) {
+ mOverrideChannels.put(key, overrideChannels.getParcelable(key));
+ }
+ }
+
+ // Locked by 'this'
+ private void buildOverridePeopleLocked() {
+ Bundle overridePeople = mRankingUpdate.getOverridePeople();
+ mOverridePeople = new ArrayMap<>(overridePeople.size());
+ for (String key : overridePeople.keySet()) {
+ mOverridePeople.put(key, overridePeople.getStringArrayList(key));
+ }
+ }
+
+ // Locked by 'this'
+ private void buildSnoozeCriteriaLocked() {
+ Bundle snoozeCriteria = mRankingUpdate.getSnoozeCriteria();
+ mSnoozeCriteria = new ArrayMap<>(snoozeCriteria.size());
+ for (String key : snoozeCriteria.keySet()) {
+ mSnoozeCriteria.put(key, snoozeCriteria.getParcelableArrayList(key));
+ }
+ }
+
// ----------- Parcelable
@Override
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index 788b5c0..a2cdeff 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -31,10 +31,14 @@
private final int[] mImportance;
private final Bundle mImportanceExplanation;
private final Bundle mOverrideGroupKeys;
+ private final Bundle mOverrideChannels;
+ private final Bundle mOverridePeople;
+ private final Bundle mSnoozeCriteria;
public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
Bundle visibilityOverrides, Bundle suppressedVisualEffects,
- int[] importance, Bundle explanation, Bundle overrideGroupKeys) {
+ int[] importance, Bundle explanation, Bundle overrideGroupKeys,
+ Bundle overrideChannels, Bundle overridePeople, Bundle snoozeCriteria) {
mKeys = keys;
mInterceptedKeys = interceptedKeys;
mVisibilityOverrides = visibilityOverrides;
@@ -42,6 +46,9 @@
mImportance = importance;
mImportanceExplanation = explanation;
mOverrideGroupKeys = overrideGroupKeys;
+ mOverrideChannels = overrideChannels;
+ mOverridePeople = overridePeople;
+ mSnoozeCriteria = snoozeCriteria;
}
public NotificationRankingUpdate(Parcel in) {
@@ -53,6 +60,9 @@
in.readIntArray(mImportance);
mImportanceExplanation = in.readBundle();
mOverrideGroupKeys = in.readBundle();
+ mOverrideChannels = in.readBundle();
+ mOverridePeople = in.readBundle();
+ mSnoozeCriteria = in.readBundle();
}
@Override
@@ -69,6 +79,9 @@
out.writeIntArray(mImportance);
out.writeBundle(mImportanceExplanation);
out.writeBundle(mOverrideGroupKeys);
+ out.writeBundle(mOverrideChannels);
+ out.writeBundle(mOverridePeople);
+ out.writeBundle(mSnoozeCriteria);
}
public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -109,4 +122,16 @@
public Bundle getOverrideGroupKeys() {
return mOverrideGroupKeys;
}
+
+ public Bundle getOverrideChannels() {
+ return mOverrideChannels;
+ }
+
+ public Bundle getOverridePeople() {
+ return mOverridePeople;
+ }
+
+ public Bundle getSnoozeCriteria() {
+ return mSnoozeCriteria;
+ }
}
diff --git a/core/java/android/service/notification/SnoozeCriterion.aidl b/core/java/android/service/notification/SnoozeCriterion.aidl
new file mode 100644
index 0000000..9b666d8
--- /dev/null
+++ b/core/java/android/service/notification/SnoozeCriterion.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.service.notification;
+
+parcelable SnoozeCriterion;
\ No newline at end of file
diff --git a/core/java/android/service/notification/SnoozeCriterion.java b/core/java/android/service/notification/SnoozeCriterion.java
new file mode 100644
index 0000000..f37f1ae
--- /dev/null
+++ b/core/java/android/service/notification/SnoozeCriterion.java
@@ -0,0 +1,139 @@
+/*
+ * 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.service.notification;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents an option to be shown to users for snoozing a notification until a given context
+ * instead of for a fixed amount of time.
+ */
+public final class SnoozeCriterion implements Parcelable {
+ private final String mId;
+ private final CharSequence mExplanation;
+ private final CharSequence mConfirmation;
+
+ public SnoozeCriterion(String id, CharSequence explanation, CharSequence confirmation) {
+ mId = id;
+ mExplanation = explanation;
+ mConfirmation = confirmation;
+ }
+
+ protected SnoozeCriterion(Parcel in) {
+ if (in.readByte() != 0) {
+ mId = in.readString();
+ } else {
+ mId = null;
+ }
+ if (in.readByte() != 0) {
+ mExplanation = in.readCharSequence();
+ } else {
+ mExplanation = null;
+ }
+ if (in.readByte() != 0) {
+ mConfirmation = in.readCharSequence();
+ } else {
+ mConfirmation = null;
+ }
+ }
+
+ /**
+ * Returns the id of this criterion.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * Returns the user visible explanation of how long a notification will be snoozed if
+ * this criterion is chosen.
+ */
+ public CharSequence getExplanation() {
+ return mExplanation;
+ }
+
+ /**
+ * Returns the user visible confirmation message shown when this criterion is chosen.
+ */
+ public CharSequence getConfirmation() {
+ return mConfirmation;
+ }
+
+ public static final Creator<SnoozeCriterion> CREATOR = new Creator<SnoozeCriterion>() {
+ @Override
+ public SnoozeCriterion createFromParcel(Parcel in) {
+ return new SnoozeCriterion(in);
+ }
+
+ @Override
+ public SnoozeCriterion[] newArray(int size) {
+ return new SnoozeCriterion[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (mId != null) {
+ dest.writeByte((byte) 1);
+ dest.writeString(mId);
+ } else {
+ dest.writeByte((byte) 0);
+ }
+ if (mExplanation != null) {
+ dest.writeByte((byte) 1);
+ dest.writeCharSequence(mExplanation);
+ } else {
+ dest.writeByte((byte) 0);
+ }
+ if (mConfirmation != null) {
+ dest.writeByte((byte) 1);
+ dest.writeCharSequence(mConfirmation);
+ } else {
+ dest.writeByte((byte) 0);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ SnoozeCriterion that = (SnoozeCriterion) o;
+
+ if (mId != null ? !mId.equals(that.mId) : that.mId != null) return false;
+ if (mExplanation != null ? !mExplanation.equals(that.mExplanation)
+ : that.mExplanation != null) {
+ return false;
+ }
+ return mConfirmation != null ? mConfirmation.equals(that.mConfirmation)
+ : that.mConfirmation == null;
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mId != null ? mId.hashCode() : 0;
+ result = 31 * result + (mExplanation != null ? mExplanation.hashCode() : 0);
+ result = 31 * result + (mConfirmation != null ? mConfirmation.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
index 8e8c019..cb021bc 100644
--- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java
+++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
@@ -68,6 +68,7 @@
@Retention(RetentionPolicy.SOURCE)
public @interface FlashLockState {}
+ /** @hide */
public PersistentDataBlockManager(IPersistentDataBlockService service) {
sService = service;
}
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 12aed25..48f3ac3 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -120,7 +120,7 @@
/** @hide */
public static final String KEY_RECEIVER_EXTRAS = "receiverExtras";
/** @hide */
- public static final String KEY_AUTO_FILL_CALLBACK = "autoFillCallback";
+ public static final String KEY_FLAGS = "flags";
final Context mContext;
final HandlerCaller mHandlerCaller;
diff --git a/core/java/android/text/TextClassificationManager.java b/core/java/android/text/TextClassificationManager.java
new file mode 100644
index 0000000..d4548f0
--- /dev/null
+++ b/core/java/android/text/TextClassificationManager.java
@@ -0,0 +1,62 @@
+/*
+ * 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.text;
+
+import android.annotation.NonNull;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Interface to the text classification service.
+ * This class uses machine learning techniques to infer things about text.
+ * Unless otherwise stated, methods of this class are blocking operations and should most likely not
+ * be called on the UI thread.
+ *
+ * <p> You do not instantiate this class directly; instead, retrieve it through
+ * {@link android.content.Context#getSystemService}.
+ *
+ * The TextClassificationManager serves as the default TextAssistant if none has been set.
+ * @see android.app.Activity#setTextAssistant(TextAssistant).
+ */
+public final class TextClassificationManager implements TextAssistant {
+ // TODO: Consider not making this class implement TextAssistant.
+
+ /** @hide */
+ public TextClassificationManager() {}
+
+ /**
+ * Returns information containing languages that were detected in the provided text.
+ * This is a blocking operation and should most likely not be called on the UI thread.
+ */
+ public List<TextLanguage> detectLanguages(@NonNull CharSequence text) {
+ // TODO: Implement this using the cld3 library.
+ return Collections.emptyList();
+ }
+
+ @Override
+ public TextSelection suggestSelection(
+ @NonNull CharSequence text, int selectionStartIndex, int selectionEndIndex) {
+ // TODO: Implement.
+ return TextAssistant.NO_OP.suggestSelection(text, selectionStartIndex, selectionEndIndex);
+ }
+
+ @Override
+ public void addLinks(@NonNull Spannable text, int linkMask) {
+ // TODO: Implement.
+ }
+}
diff --git a/core/java/android/text/TextLanguage.java b/core/java/android/text/TextLanguage.java
new file mode 100644
index 0000000..eb834f1
--- /dev/null
+++ b/core/java/android/text/TextLanguage.java
@@ -0,0 +1,85 @@
+/*
+ * 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.text;
+
+import android.annotation.NonNull;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Specifies detected languages for a section of text indicated by a start and end index.
+ */
+public final class TextLanguage {
+
+ private final int mStartIndex;
+ private final int mEndIndex;
+ private final Map<String, Float> mLanguageConfidence;
+
+ /**
+ * Initializes a TextLanguage object.
+ *
+ * @param startIndex the start index of the detected languages in the text provided to generate
+ * this object.
+ * @param endIndex the end index of the detected languages in the text provided to generate this
+ * object.
+ * @param languageConfidence a map of detected language to confidence score. The language string
+ * is a BCP-47 language tag.
+ * @throws NullPointerException if languageConfidence is null or contains a null key or value.
+ */
+ public TextLanguage(int startIndex, int endIndex,
+ @NonNull Map<String, Float> languageConfidence) {
+ mStartIndex = startIndex;
+ mEndIndex = endIndex;
+
+ Map<String, Float> map = new LinkedHashMap<>();
+ Preconditions.checkNotNull(languageConfidence).entrySet().stream()
+ .sorted(Map.Entry.comparingByValue())
+ .forEach(entry -> map.put(
+ Preconditions.checkNotNull(entry.getKey()),
+ Preconditions.checkNotNull(entry.getValue())));
+ mLanguageConfidence = Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * Returns the start index of the detected languages in the text provided to generate this
+ * object.
+ */
+ public int getStartIndex() {
+ return mStartIndex;
+ }
+
+ /**
+ * Returns the end index of the detected languages in the text provided to generate this object.
+ */
+ public int getEndIndex() {
+ return mEndIndex;
+ }
+
+ /**
+ * Returns an unmodifiable map of detected language to confidence score. The map entries are
+ * ordered from high confidence score (1) to low confidence score (0). The language string is a
+ * BCP-47 language tag.
+ */
+ @NonNull
+ public Map<String, Float> getLanguageConfidence() {
+ return mLanguageConfidence;
+ }
+}
diff --git a/core/java/android/text/style/RasterizerSpan.java b/core/java/android/text/style/RasterizerSpan.java
index cae9640..f0be50a 100644
--- a/core/java/android/text/style/RasterizerSpan.java
+++ b/core/java/android/text/style/RasterizerSpan.java
@@ -19,6 +19,9 @@
import android.graphics.Rasterizer;
import android.text.TextPaint;
+/**
+ * @removed Rasterizer is not supported for hw-accerlerated and PDF rendering
+ */
public class RasterizerSpan extends CharacterStyle implements UpdateAppearance {
private Rasterizer mRasterizer;
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index ccaf204..749cf08 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -19,7 +19,6 @@
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
-import android.os.Process;
import libcore.io.IoUtils;
import dalvik.system.CloseGuard;
@@ -37,13 +36,13 @@
* each other.
* <p>
* The data structure is designed to have one owner process that can
- * read/write. There may be multiple client processes that can only read or
- * read/write depending how the data structure was configured when
- * instantiated. The owner process is the process that created the array.
- * The shared memory is pinned (not reclaimed by the system) until the
- * owning process dies or the data structure is closed. This class
- * is <strong>not</strong> thread safe. You should not interact with
- * an instance of this class once it is closed.
+ * read/write. There may be multiple client processes that can only read.
+ * The owner process is the process that created the array. The shared
+ * memory is pinned (not reclaimed by the system) until the owning process
+ * dies or the data structure is closed. This class is <strong>not</strong>
+ * thread safe. You should not interact with an instance of this class
+ * once it is closed. If you pass back to the owner process an instance
+ * it will be read only even in the owning process.
* </p>
*
* @hide
@@ -55,8 +54,7 @@
private final CloseGuard mCloseGuard = CloseGuard.get();
- private final int mOwnerPid;
- private final boolean mClientWritable;
+ private final boolean mIsOwner;
private final long mMemoryAddr;
private int mFd;
@@ -65,35 +63,27 @@
*
* @param size The size of the array in terms of integer slots. Cannot be
* more than {@link #getMaxSize()}.
- * @param clientWritable Whether other processes can write to the array.
* @throws IOException If an error occurs while accessing the shared memory.
*/
- public MemoryIntArray(int size, boolean clientWritable) throws IOException {
+ public MemoryIntArray(int size) throws IOException {
if (size > MAX_SIZE) {
throw new IllegalArgumentException("Max size is " + MAX_SIZE);
}
- mOwnerPid = Process.myPid();
- mClientWritable = clientWritable;
+ mIsOwner = true;
final String name = UUID.randomUUID().toString();
mFd = nativeCreate(name, size);
- mMemoryAddr = nativeOpen(mFd, true, clientWritable);
+ mMemoryAddr = nativeOpen(mFd, mIsOwner);
mCloseGuard.open("close");
}
private MemoryIntArray(Parcel parcel) throws IOException {
- mOwnerPid = parcel.readInt();
- mClientWritable = (parcel.readInt() == 1);
+ mIsOwner = false;
ParcelFileDescriptor pfd = parcel.readParcelable(null);
if (pfd == null) {
throw new IOException("No backing file descriptor");
}
mFd = pfd.detachFd();
- final long memoryAddress = parcel.readLong();
- if (isOwner()) {
- mMemoryAddr = memoryAddress;
- } else {
- mMemoryAddr = nativeOpen(mFd, false, mClientWritable);
- }
+ mMemoryAddr = nativeOpen(mFd, mIsOwner);
mCloseGuard.open("close");
}
@@ -102,7 +92,7 @@
*/
public boolean isWritable() {
enforceNotClosed();
- return isOwner() || mClientWritable;
+ return mIsOwner;
}
/**
@@ -115,7 +105,7 @@
public int get(int index) throws IOException {
enforceNotClosed();
enforceValidIndex(index);
- return nativeGet(mFd, mMemoryAddr, index, isOwner());
+ return nativeGet(mFd, mMemoryAddr, index);
}
/**
@@ -131,7 +121,7 @@
enforceNotClosed();
enforceWritable();
enforceValidIndex(index);
- nativeSet(mFd, mMemoryAddr, index, value, isOwner());
+ nativeSet(mFd, mMemoryAddr, index, value);
}
/**
@@ -152,7 +142,7 @@
@Override
public void close() throws IOException {
if (!isClosed()) {
- nativeClose(mFd, mMemoryAddr, isOwner());
+ nativeClose(mFd, mMemoryAddr, mIsOwner);
mFd = -1;
mCloseGuard.close();
}
@@ -184,11 +174,8 @@
public void writeToParcel(Parcel parcel, int flags) {
ParcelFileDescriptor pfd = ParcelFileDescriptor.adoptFd(mFd);
try {
- parcel.writeInt(mOwnerPid);
- parcel.writeInt(mClientWritable ? 1 : 0);
// Don't let writing to a parcel to close our fd - plz
parcel.writeParcelable(pfd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- parcel.writeLong(mMemoryAddr);
} finally {
pfd.detachFd();
}
@@ -214,10 +201,6 @@
return mFd;
}
- private boolean isOwner() {
- return mOwnerPid == Process.myPid();
- }
-
private void enforceNotClosed() {
if (isClosed()) {
throw new IllegalStateException("cannot interact with a closed instance");
@@ -239,10 +222,10 @@
}
private native int nativeCreate(String name, int size);
- private native long nativeOpen(int fd, boolean owner, boolean writable);
+ private native long nativeOpen(int fd, boolean owner);
private native void nativeClose(int fd, long memoryAddr, boolean owner);
- private native int nativeGet(int fd, long memoryAddr, int index, boolean owner);
- private native void nativeSet(int fd, long memoryAddr, int index, int value, boolean owner);
+ private native int nativeGet(int fd, long memoryAddr, int index);
+ private native void nativeSet(int fd, long memoryAddr, int index, int value);
private native int nativeSize(int fd);
/**
@@ -259,8 +242,7 @@
try {
return new MemoryIntArray(parcel);
} catch (IOException ioe) {
- Log.e(TAG, "Error unparceling MemoryIntArray");
- return null;
+ throw new IllegalArgumentException("Error unparceling MemoryIntArray");
}
}
diff --git a/core/java/android/util/jar/StrictJarFile.java b/core/java/android/util/jar/StrictJarFile.java
index d9556aa..bc4a19d 100644
--- a/core/java/android/util/jar/StrictJarFile.java
+++ b/core/java/android/util/jar/StrictJarFile.java
@@ -134,6 +134,7 @@
} catch (IOException | SecurityException e) {
nativeClose(this.nativeHandle);
IoUtils.closeQuietly(fd);
+ closed = true;
throw e;
}
diff --git a/core/java/android/util/jar/StrictJarVerifier.java b/core/java/android/util/jar/StrictJarVerifier.java
index cb71ecc..debc170 100644
--- a/core/java/android/util/jar/StrictJarVerifier.java
+++ b/core/java/android/util/jar/StrictJarVerifier.java
@@ -17,7 +17,7 @@
package android.util.jar;
-import java.io.ByteArrayInputStream;
+import android.util.apk.ApkSignatureSchemeV2Verifier;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
@@ -33,13 +33,9 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.Set;
import java.util.StringTokenizer;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
-import android.util.ArraySet;
-import android.util.apk.ApkSignatureSchemeV2Verifier;
-import libcore.io.Base64;
import sun.security.jca.Providers;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
@@ -139,7 +135,7 @@
*/
void verify() {
byte[] d = digest.digest();
- if (!MessageDigest.isEqual(d, Base64.decode(hash))) {
+ if (!verifyMessageDigest(d, hash)) {
throw invalidDigest(JarFile.MANIFEST_NAME, name, name);
}
verifiedEntries.put(name, certChains);
@@ -490,12 +486,22 @@
md.update(data, start, end - start);
}
byte[] b = md.digest();
- byte[] hashBytes = hash.getBytes(StandardCharsets.ISO_8859_1);
- return MessageDigest.isEqual(b, Base64.decode(hashBytes));
+ byte[] encodedHashBytes = hash.getBytes(StandardCharsets.ISO_8859_1);
+ return verifyMessageDigest(b, encodedHashBytes);
}
return ignorable;
}
+ private static boolean verifyMessageDigest(byte[] expected, byte[] encodedActual) {
+ byte[] actual;
+ try {
+ actual = java.util.Base64.getDecoder().decode(encodedActual);
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ return MessageDigest.isEqual(expected, actual);
+ }
+
/**
* Returns all of the {@link java.security.cert.Certificate} chains that
* were used to verify the signature on the JAR entry called
diff --git a/core/java/android/util/proto/ProtoOutputStream.java b/core/java/android/util/proto/ProtoOutputStream.java
index 8f99399..81251fc 100644
--- a/core/java/android/util/proto/ProtoOutputStream.java
+++ b/core/java/android/util/proto/ProtoOutputStream.java
@@ -19,6 +19,10 @@
import android.annotation.TestApi;
import android.util.Log;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.List;
@@ -179,6 +183,11 @@
private EncodedBuffer mBuffer;
/**
+ * Our stream. If there is one.
+ */
+ private OutputStream mStream;
+
+ /**
* Current nesting depth of startObject calls.
*/
private int mDepth;
@@ -226,6 +235,690 @@
mBuffer = new EncodedBuffer(chunkSize);
}
+ /**
+ * Construct a ProtoOutputStream that sits on top of an OutputStream.
+ * @more
+ * The {@link #flush() flush()} method must be called when done writing
+ * to flush any remanining data, althought data *may* be written at intermediate
+ * points within the writing as well.
+ */
+ public ProtoOutputStream(OutputStream stream) {
+ this();
+ mStream = stream;
+ }
+
+ /**
+ * Construct a ProtoOutputStream that sits on top of a FileDescriptor.
+ * @more
+ * The {@link #flush() flush()} method must be called when done writing
+ * to flush any remanining data, althought data *may* be written at intermediate
+ * points within the writing as well.
+ */
+ public ProtoOutputStream(FileDescriptor fd) {
+ this(new FileOutputStream(fd));
+ }
+
+ /**
+ * Write a value for the given fieldId.
+ *
+ * Will automatically convert for the following field types, and
+ * throw an exception for others: double, float, int32, int64, uint32, uint64,
+ * sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @param val The value.
+ */
+ public void write(long fieldId, double val) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) {
+ // double
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeDoubleImpl(id, (double)val);
+ break;
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedDoubleImpl(id, (double)val);
+ break;
+ // float
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFloatImpl(id, (float)val);
+ break;
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFloatImpl(id, (float)val);
+ break;
+ // int32
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt32Impl(id, (int)val);
+ break;
+ // int64
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt64Impl(id, (long)val);
+ break;
+ // uint32
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt32Impl(id, (int)val);
+ break;
+ // uint64
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt64Impl(id, (long)val);
+ break;
+ // sint32
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt32Impl(id, (int)val);
+ break;
+ // sint64
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt64Impl(id, (long)val);
+ break;
+ // fixed32
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed32Impl(id, (int)val);
+ break;
+ // fixed64
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed64Impl(id, (long)val);
+ break;
+ // sfixed32
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed32Impl(id, (int)val);
+ break;
+ // sfixed64
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed64Impl(id, (long)val);
+ break;
+ // bool
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeBoolImpl(id, val != 0);
+ break;
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedBoolImpl(id, val != 0);
+ break;
+ // enum
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeEnumImpl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedEnumImpl(id, (int)val);
+ break;
+ // string, bytes, object not allowed here.
+ default: {
+ throw new IllegalArgumentException("Attempt to call write(long, double) with "
+ + getFieldIdString(fieldId));
+ }
+ }
+ }
+
+ /**
+ * Write a value for the given fieldId.
+ *
+ * Will automatically convert for the following field types, and
+ * throw an exception for others: double, float, int32, int64, uint32, uint64,
+ * sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @param val The value.
+ */
+ public void write(long fieldId, float val) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) {
+ // double
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeDoubleImpl(id, (double)val);
+ break;
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedDoubleImpl(id, (double)val);
+ break;
+ // float
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFloatImpl(id, (float)val);
+ break;
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFloatImpl(id, (float)val);
+ break;
+ // int32
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt32Impl(id, (int)val);
+ break;
+ // int64
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt64Impl(id, (long)val);
+ break;
+ // uint32
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt32Impl(id, (int)val);
+ break;
+ // uint64
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt64Impl(id, (long)val);
+ break;
+ // sint32
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt32Impl(id, (int)val);
+ break;
+ // sint64
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt64Impl(id, (long)val);
+ break;
+ // fixed32
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed32Impl(id, (int)val);
+ break;
+ // fixed64
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed64Impl(id, (long)val);
+ break;
+ // sfixed32
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed32Impl(id, (int)val);
+ break;
+ // sfixed64
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed64Impl(id, (long)val);
+ break;
+ // bool
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeBoolImpl(id, val != 0);
+ break;
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedBoolImpl(id, val != 0);
+ break;
+ // enum
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeEnumImpl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedEnumImpl(id, (int)val);
+ break;
+ // string, bytes, object not allowed here.
+ default: {
+ throw new IllegalArgumentException("Attempt to call write(long, float) with "
+ + getFieldIdString(fieldId));
+ }
+ }
+ }
+
+ /**
+ * Write a value for the given fieldId.
+ *
+ * Will automatically convert for the following field types, and
+ * throw an exception for others: double, float, int32, int64, uint32, uint64,
+ * sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @param val The value.
+ */
+ public void write(long fieldId, int val) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) {
+ // double
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeDoubleImpl(id, (double)val);
+ break;
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedDoubleImpl(id, (double)val);
+ break;
+ // float
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFloatImpl(id, (float)val);
+ break;
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFloatImpl(id, (float)val);
+ break;
+ // int32
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt32Impl(id, (int)val);
+ break;
+ // int64
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt64Impl(id, (long)val);
+ break;
+ // uint32
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt32Impl(id, (int)val);
+ break;
+ // uint64
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt64Impl(id, (long)val);
+ break;
+ // sint32
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt32Impl(id, (int)val);
+ break;
+ // sint64
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt64Impl(id, (long)val);
+ break;
+ // fixed32
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed32Impl(id, (int)val);
+ break;
+ // fixed64
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed64Impl(id, (long)val);
+ break;
+ // sfixed32
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed32Impl(id, (int)val);
+ break;
+ // sfixed64
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed64Impl(id, (long)val);
+ break;
+ // bool
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeBoolImpl(id, val != 0);
+ break;
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedBoolImpl(id, val != 0);
+ break;
+ // enum
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeEnumImpl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedEnumImpl(id, (int)val);
+ break;
+ // string, bytes, object not allowed here.
+ default: {
+ throw new IllegalArgumentException("Attempt to call write(long, int) with "
+ + getFieldIdString(fieldId));
+ }
+ }
+ }
+
+ /**
+ * Write a value for the given fieldId.
+ *
+ * Will automatically convert for the following field types, and
+ * throw an exception for others: double, float, int32, int64, uint32, uint64,
+ * sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @param val The value.
+ */
+ public void write(long fieldId, long val) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) {
+ // double
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeDoubleImpl(id, (double)val);
+ break;
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedDoubleImpl(id, (double)val);
+ break;
+ // float
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFloatImpl(id, (float)val);
+ break;
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFloatImpl(id, (float)val);
+ break;
+ // int32
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt32Impl(id, (int)val);
+ break;
+ // int64
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedInt64Impl(id, (long)val);
+ break;
+ // uint32
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt32Impl(id, (int)val);
+ break;
+ // uint64
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeUInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedUInt64Impl(id, (long)val);
+ break;
+ // sint32
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt32Impl(id, (int)val);
+ break;
+ // sint64
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSInt64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSInt64Impl(id, (long)val);
+ break;
+ // fixed32
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed32Impl(id, (int)val);
+ break;
+ // fixed64
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedFixed64Impl(id, (long)val);
+ break;
+ // sfixed32
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed32Impl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed32Impl(id, (int)val);
+ break;
+ // sfixed64
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeSFixed64Impl(id, (long)val);
+ break;
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedSFixed64Impl(id, (long)val);
+ break;
+ // bool
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeBoolImpl(id, val != 0);
+ break;
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedBoolImpl(id, val != 0);
+ break;
+ // enum
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeEnumImpl(id, (int)val);
+ break;
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedEnumImpl(id, (int)val);
+ break;
+ // string, bytes, object not allowed here.
+ default: {
+ throw new IllegalArgumentException("Attempt to call write(long, long) with "
+ + getFieldIdString(fieldId));
+ }
+ }
+ }
+
+ /**
+ * Write a boolean value for the given fieldId.
+ *
+ * If the field is not a bool field, an exception will be thrown.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @param val The value.
+ */
+ public void write(long fieldId, boolean val) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) {
+ // bool
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeBoolImpl(id, val);
+ break;
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedBoolImpl(id, val);
+ break;
+ // nothing else allowed
+ default: {
+ throw new IllegalArgumentException("Attempt to call write(long, boolean) with "
+ + getFieldIdString(fieldId));
+ }
+ }
+ }
+
+ /**
+ * Write a string value for the given fieldId.
+ *
+ * If the field is not a string field, an exception will be thrown.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @param val The value.
+ */
+ public void write(long fieldId, String val) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) {
+ // string
+ case (int)((FIELD_TYPE_STRING | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeStringImpl(id, val);
+ break;
+ case (int)((FIELD_TYPE_STRING | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_STRING | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedStringImpl(id, val);
+ break;
+ // nothing else allowed
+ default: {
+ throw new IllegalArgumentException("Attempt to call write(long, String) with "
+ + getFieldIdString(fieldId));
+ }
+ }
+ }
+
+ /**
+ * Write a byte[] value for the given fieldId.
+ *
+ * If the field is not a bytes or object field, an exception will be thrown.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @param val The value.
+ */
+ public void write(long fieldId, byte[] val) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) {
+ // bytes
+ case (int)((FIELD_TYPE_BYTES | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeBytesImpl(id, val);
+ break;
+ case (int)((FIELD_TYPE_BYTES | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_BYTES | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedBytesImpl(id, val);
+ break;
+ // Object
+ case (int)((FIELD_TYPE_OBJECT | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT):
+ writeObjectImpl(id, val);
+ break;
+ case (int)((FIELD_TYPE_OBJECT | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT):
+ case (int)((FIELD_TYPE_OBJECT | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT):
+ writeRepeatedObjectImpl(id, val);
+ break;
+ // nothing else allowed
+ default: {
+ throw new IllegalArgumentException("Attempt to call write(long, byte[]) with "
+ + getFieldIdString(fieldId));
+ }
+ }
+ }
+
+ /**
+ * Start a sub object.
+ */
+ public long start(long fieldId) {
+ assertNotCompacted();
+ final int id = (int)fieldId;
+
+ if ((fieldId & FIELD_TYPE_MASK) == FIELD_TYPE_OBJECT) {
+ final long count = fieldId & FIELD_COUNT_MASK;
+ if (count == FIELD_COUNT_SINGLE) {
+ return startObjectImpl(id, false);
+ } else if (count == FIELD_COUNT_REPEATED || count == FIELD_COUNT_PACKED) {
+ return startObjectImpl(id, true);
+ }
+ }
+ throw new IllegalArgumentException("Attempt to call start(long) with "
+ + getFieldIdString(fieldId));
+ }
+
+ /**
+ * End the object started by start() that returned token.
+ */
+ public void end(long token) {
+ endObjectImpl(token, getRepeatedFromToken(token));
+ }
+
//
// proto3 type: double
// java type: double
@@ -240,6 +933,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_DOUBLE);
+ writeDoubleImpl(id, val);
+ }
+
+ private void writeDoubleImpl(int id, double val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_FIXED64);
mBuffer.writeRawFixed64(Double.doubleToLongBits(val));
@@ -253,6 +950,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_DOUBLE);
+ writeRepeatedDoubleImpl(id, val);
+ }
+
+ private void writeRepeatedDoubleImpl(int id, double val) {
writeTag(id, WIRE_TYPE_FIXED64);
mBuffer.writeRawFixed64(Double.doubleToLongBits(val));
}
@@ -287,6 +988,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_FLOAT);
+ writeFloatImpl(id, val);
+ }
+
+ private void writeFloatImpl(int id, float val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_FIXED32);
mBuffer.writeRawFixed32(Float.floatToIntBits(val));
@@ -300,6 +1005,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_FLOAT);
+ writeRepeatedFloatImpl(id, val);
+ }
+
+ private void writeRepeatedFloatImpl(int id, float val) {
writeTag(id, WIRE_TYPE_FIXED32);
mBuffer.writeRawFixed32(Float.floatToIntBits(val));
}
@@ -357,6 +1066,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_INT32);
+ writeInt32Impl(id, val);
+ }
+
+ private void writeInt32Impl(int id, int val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_VARINT);
writeUnsignedVarintFromSignedInt(val);
@@ -374,6 +1087,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_INT32);
+ writeRepeatedInt32Impl(id, val);
+ }
+
+ private void writeRepeatedInt32Impl(int id, int val) {
writeTag(id, WIRE_TYPE_VARINT);
writeUnsignedVarintFromSignedInt(val);
}
@@ -418,6 +1135,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_INT64);
+ writeInt64Impl(id, val);
+ }
+
+ private void writeInt64Impl(int id, long val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawVarint64(val);
@@ -431,6 +1152,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_INT64);
+ writeRepeatedInt64Impl(id, val);
+ }
+
+ private void writeRepeatedInt64Impl(int id, long val) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawVarint64(val);
}
@@ -470,6 +1195,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_UINT32);
+ writeUInt32Impl(id, val);
+ }
+
+ private void writeUInt32Impl(int id, int val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawVarint32(val);
@@ -483,6 +1212,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_UINT32);
+ writeRepeatedUInt32Impl(id, val);
+ }
+
+ private void writeRepeatedUInt32Impl(int id, int val) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawVarint32(val);
}
@@ -522,6 +1255,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_UINT64);
+ writeUInt64Impl(id, val);
+ }
+
+ private void writeUInt64Impl(int id, long val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawVarint64(val);
@@ -535,6 +1272,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_UINT64);
+ writeRepeatedUInt64Impl(id, val);
+ }
+
+ private void writeRepeatedUInt64Impl(int id, long val) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawVarint64(val);
}
@@ -574,6 +1315,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SINT32);
+ writeSInt32Impl(id, val);
+ }
+
+ private void writeSInt32Impl(int id, int val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawZigZag32(val);
@@ -587,6 +1332,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SINT32);
+ writeRepeatedSInt32Impl(id, val);
+ }
+
+ private void writeRepeatedSInt32Impl(int id, int val) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawZigZag32(val);
}
@@ -626,6 +1375,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SINT64);
+ writeSInt64Impl(id, val);
+ }
+
+ private void writeSInt64Impl(int id, long val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawZigZag64(val);
@@ -639,6 +1392,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SINT64);
+ writeRepeatedSInt64Impl(id, val);
+ }
+
+ private void writeRepeatedSInt64Impl(int id, long val) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawZigZag64(val);
}
@@ -677,6 +1434,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_FIXED32);
+ writeFixed32Impl(id, val);
+ }
+
+ private void writeFixed32Impl(int id, int val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_FIXED32);
mBuffer.writeRawFixed32(val);
@@ -690,6 +1451,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_FIXED32);
+ writeRepeatedFixed32Impl(id, val);
+ }
+
+ private void writeRepeatedFixed32Impl(int id, int val) {
writeTag(id, WIRE_TYPE_FIXED32);
mBuffer.writeRawFixed32(val);
}
@@ -724,6 +1489,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_FIXED64);
+ writeFixed64Impl(id, val);
+ }
+
+ private void writeFixed64Impl(int id, long val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_FIXED64);
mBuffer.writeRawFixed64(val);
@@ -737,6 +1506,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_FIXED64);
+ writeRepeatedFixed64(id, val);
+ }
+
+ private void writeRepeatedFixed64Impl(int id, long val) {
writeTag(id, WIRE_TYPE_FIXED64);
mBuffer.writeRawFixed64(val);
}
@@ -770,6 +1543,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SFIXED32);
+ writeSFixed32Impl(id, val);
+ }
+
+ private void writeSFixed32Impl(int id, int val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_FIXED32);
mBuffer.writeRawFixed32(val);
@@ -783,6 +1560,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SFIXED32);
+ writeRepeatedSFixed32Impl(id, val);
+ }
+
+ private void writeRepeatedSFixed32Impl(int id, int val) {
writeTag(id, WIRE_TYPE_FIXED32);
mBuffer.writeRawFixed32(val);
}
@@ -817,6 +1598,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SFIXED64);
+ writeSFixed64Impl(id, val);
+ }
+
+ private void writeSFixed64Impl(int id, long val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_FIXED64);
mBuffer.writeRawFixed64(val);
@@ -830,6 +1615,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SFIXED64);
+ writeRepeatedSFixed64(id, val);
+ }
+
+ private void writeRepeatedSFixed64Impl(int id, long val) {
writeTag(id, WIRE_TYPE_FIXED64);
mBuffer.writeRawFixed64(val);
}
@@ -864,6 +1653,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_BOOL);
+ writeBoolImpl(id, val);
+ }
+
+ private void writeBoolImpl(int id, boolean val) {
if (val) {
writeTag(id, WIRE_TYPE_VARINT);
// 0 and 1 are the same as their varint counterparts
@@ -878,6 +1671,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_BOOL);
+ writeRepeatedBool(id, val);
+ }
+
+ private void writeRepeatedBoolImpl(int id, boolean val) {
writeTag(id, WIRE_TYPE_VARINT);
mBuffer.writeRawByte((byte)(val ? 1 : 0));
}
@@ -916,6 +1713,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_STRING);
+ writeStringImpl(id, val);
+ }
+
+ private void writeStringImpl(int id, String val) {
if (val != null && val.length() > 0) {
writeUtf8String(id, val);
}
@@ -928,6 +1729,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_STRING);
+ writeRepeatedStringImpl(id, val);
+ }
+
+ private void writeRepeatedStringImpl(int id, String val) {
if (val == null || val.length() == 0) {
writeKnownLengthHeader(id, 0);
} else {
@@ -963,6 +1768,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_BYTES);
+ writeBytesImpl(id, val);
+ }
+
+ private void writeBytesImpl(int id, byte[] val) {
if (val != null && val.length > 0) {
writeKnownLengthHeader(id, val.length);
mBuffer.writeRawBuffer(val);
@@ -976,6 +1785,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_BYTES);
+ writeRepeatedBytesImpl(id, val);
+ }
+
+ private void writeRepeatedBytesImpl(int id, byte[] val) {
writeKnownLengthHeader(id, val == null ? 0 : val.length);
mBuffer.writeRawBuffer(val);
}
@@ -995,6 +1808,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_ENUM);
+ writeEnumImpl(id, val);
+ }
+
+ private void writeEnumImpl(int id, int val) {
if (val != 0) {
writeTag(id, WIRE_TYPE_VARINT);
writeUnsignedVarintFromSignedInt(val);
@@ -1008,6 +1825,10 @@
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_ENUM);
+ writeRepeatedEnumImpl(id, val);
+ }
+
+ private void writeRepeatedEnumImpl(int id, int val) {
writeTag(id, WIRE_TYPE_VARINT);
writeUnsignedVarintFromSignedInt(val);
}
@@ -1239,6 +2060,38 @@
}
}
+ /**
+ * Write an object that has already been flattend.
+ */
+ public void writeObject(long fieldId, byte[] value) {
+ assertNotCompacted();
+ final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_OBJECT);
+
+ writeObjectImpl(id, value);
+ }
+
+ public void writeObjectImpl(int id, byte[] value) {
+ if (value != null && value.length != 0) {
+ writeKnownLengthHeader(id, value.length);
+ mBuffer.writeRawBuffer(value);
+ }
+ }
+
+ /**
+ * Write an object that has already been flattend.
+ */
+ public void writeRepeatedObject(long fieldId, byte[] value) {
+ assertNotCompacted();
+ final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_OBJECT);
+
+ writeRepeatedObjectImpl(id, value);
+ }
+
+ public void writeRepeatedObjectImpl(int id, byte[] value) {
+ writeKnownLengthHeader(id, value == null ? 0 : value.length);
+ mBuffer.writeRawBuffer(value);
+ }
+
//
// Tags
//
@@ -1358,6 +2211,25 @@
}
}
+ /**
+ * Get a debug string for a fieldId.
+ */
+ private String getFieldIdString(long fieldId) {
+ final long fieldCount = fieldId & FIELD_COUNT_MASK;
+ String countString = getFieldCountString(fieldCount);
+ if (countString == null) {
+ countString = "fieldCount=" + fieldCount;
+ }
+
+ final long fieldType = fieldId & FIELD_TYPE_MASK;
+ String typeString = getFieldTypeString(fieldType);
+ if (typeString == null) {
+ typeString = "fieldType=" + fieldType;
+ }
+
+ return fieldCount + " " + typeString + " tag=" + ((int)fieldId)
+ + " fieldId=0x" + Long.toHexString(fieldId);
+ }
/**
* Return how many bytes an encoded field tag will require.
@@ -1580,6 +2452,37 @@
}
/**
+ * Write remaining data to the output stream. If there is no output stream,
+ * this function does nothing. Any currently open objects (i.e. ones that
+ * have not had endObject called for them will not be written). Whether this
+ * writes objects that are closed if there are remaining open objects is
+ * undefined (current implementation does not write it, future ones will).
+ * For now, can either call getBytes() or flush(), but not both.
+ */
+ public void flush() {
+ if (mStream == null) {
+ return;
+ }
+ if (mDepth != 0) {
+ // TODO: The compacting code isn't ready yet to compact unless we're done.
+ // TODO: Fix that.
+ return;
+ }
+ if (mCompacted) {
+ // If we're compacted, we already wrote it finished.
+ return;
+ }
+ compactIfNecessary();
+ final byte[] data = mBuffer.getBytes(mBuffer.getReadableSize());
+ try {
+ mStream.write(data);
+ mStream.flush();
+ } catch (IOException ex) {
+ throw new RuntimeException("Error flushing proto to stream", ex);
+ }
+ }
+
+ /**
* Read a raw tag from the buffer.
*/
private int readRawTag() {
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index bd1ad8e..21875fe 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -89,51 +89,33 @@
void addWindowToken(IBinder token, int type, int displayId);
void removeWindowToken(IBinder token, int displayId);
/**
- * Adds an application token to the specified task Id.
+ * Creates the object representation for the application token in the window manager and adds it
+ * to the specified task Id.
+ *
* @param addPos The position to add the token to in the task.
* @param token The token to add.
* @param taskId The Id of the task we are adding the token to.
- * @param stackId Stack Id to create a new Task with the input task Id on
- * if the task doesn't exist yet.
* @param requestedOrientation Orientation to use.
* @param fullscreen True if the application token is fullscreen.
* @param showWhenLocked True if the application token should be shown when locked.
- * @param userId Id of user to associate the token with.
* @param configChanges Input configuration changes.
* @param voiceInteraction True if the token is in voice interaction mode.
* @param launchTaskBehind True if the token is been launched from behind.
- * @param taskBounds Bounds to use when creating a new Task with the input task Id if
- * the task doesn't exist yet.
- * @param overrideConfig Override configuration that is being used with this task.
- * @param taskResizeMode The resize mode of the task.
* @param alwaysFocusable True if the app windows are always focusable regardless of the stack
* they are in.
- * @param homeTask True if this is the task.
* @param targetSdkVersion The application's target SDK version
- * @param isOnTopLauncher True if this task is an on-top launcher.
*/
- void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
- int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
- int configChanges, boolean voiceInteraction, boolean launchTaskBehind,
- in Rect taskBounds, in Configuration overrideConfig, int taskResizeMode,
- boolean alwaysFocusable, boolean homeTask, int targetSdkVersion,
- int rotationAnimationHint, boolean isOnTopLauncher);
+ void addAppToken(int addPos, IApplicationToken token, int taskId, int requestedOrientation,
+ boolean fullscreen, boolean showWhenLocked, int configChanges, boolean voiceInteraction,
+ boolean launchTaskBehind, boolean alwaysFocusable, int targetSdkVersion,
+ int rotationAnimationHint);
/**
+ * Adds an already existing application token on the window manager side to the input task id.
*
* @param token The token we are adding to the input task Id.
* @param taskId The Id of the task we are adding the token to.
- * @param stackId Stack Id to create a new Task with the input task Id on
- * if the task doesn't exist yet.
- * @param taskBounds Bounds to use when creating a new Task with the input task Id if
- * the task doesn't exist yet.
- * @param overrideConfig Override configuration that is being used with this task.
- * @param taskResizeMode The resize mode of the task.
- * @param homeTask True if this is the task.
- * @param isOnTopLauncher True if this task is an on-top launcher.
*/
- void setAppTask(IBinder token, int taskId, int stackId, in Rect taskBounds,
- in Configuration overrideConfig, int taskResizeMode, boolean homeTask,
- boolean isOnTopLauncher);
+ void addAppToTask(IBinder token, int taskId);
void setAppOrientation(IApplicationToken token, int requestedOrientation);
int getAppOrientation(IApplicationToken token);
void setFocusedApp(IBinder token, boolean moveFocusNow);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f9a03c0..9e4bb4c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2474,7 +2474,9 @@
* 1 PFLAG3_SCROLL_INDICATOR_START
* 1 PFLAG3_SCROLL_INDICATOR_END
* 1 PFLAG3_ASSIST_BLOCKED
- * xxxxxxxx * NO LONGER NEEDED, SHOULD BE REUSED *
+ * 1 PFLAG3_CLUSTER
+ * 1 PFLAG3_SECTION
+ * xxxxxx * NO LONGER NEEDED, SHOULD BE REUSED *
* 1 PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
* 1 PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
* 1 PFLAG3_TEMPORARY_DETACH
@@ -2673,6 +2675,22 @@
static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
/**
+ * Flag indicating that the view is a root of a keyboard navigation cluster.
+ *
+ * @see #isKeyboardNavigationCluster()
+ * @see #setKeyboardNavigationCluster(boolean)
+ */
+ private static final int PFLAG3_CLUSTER = 0x8000;
+
+ /**
+ * Flag indicating that the view is a root of a keyboard navigation section.
+ *
+ * @see #isKeyboardNavigationSection()
+ * @see #setKeyboardNavigationSection(boolean)
+ */
+ private static final int PFLAG3_SECTION = 0x10000;
+
+ /**
* Whether this view has rendered elements that overlap (see {@link
* #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
* {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
@@ -2912,6 +2930,30 @@
public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
/**
+ * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
+ * trigger undefined behavior on older platforms with apps compiled against a new SDK.
+ */
+ private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
+
+ /**
+ * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
+ * trigger undefined behavior on older platforms with apps compiled against a new SDK.
+ */
+ private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
+
+ /**
+ * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
+ * that is compatible with light navigation bar backgrounds.
+ *
+ * <p>For this to take effect, the window must request
+ * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
+ * FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
+ * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
+ * FLAG_TRANSLUCENT_NAVIGATION}.
+ */
+ public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
+
+ /**
* @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
*/
@Deprecated
@@ -3104,7 +3146,7 @@
*
* Makes status bar transparent (but not the navigation bar).
*/
- public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
+ public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
/**
* @hide
@@ -3716,6 +3758,16 @@
*/
int mNextFocusForwardId = View.NO_ID;
+ /**
+ * User-specified next keyboard navigation cluster.
+ */
+ int mNextClusterForwardId = View.NO_ID;
+
+ /**
+ * User-specified next keyboard navigation section.
+ */
+ int mNextSectionForwardId = View.NO_ID;
+
private CheckForLongPress mPendingCheckForLongPress;
private CheckForTap mPendingCheckForTap = null;
private PerformClick mPerformClick;
@@ -3940,6 +3992,21 @@
int mLayerType = LAYER_TYPE_NONE;
Paint mLayerPaint;
+
+ /**
+ * <p>When setting a {@link android.app.assist.AssistStructure}, its nodes should not contain
+ * PII (Personally Identifiable Information).
+ */
+ // TODO(b/33197203) (b/33269702): improve documentation: mention all cases, show examples, etc.
+ public static final int ASSIST_FLAG_SANITIZED_TEXT = 0x1;
+
+ /**
+ * <p>When setting a {@link android.app.assist.AssistStructure}, its nodes should contain all
+ * type of data, even sensitive PII (Personally Identifiable Information) like passwords or
+ * credit card numbers.
+ */
+ public static final int ASSIST_FLAG_NON_SANITIZED_TEXT = 0x2;
+
/**
* Set to true when drawing cache is enabled and cannot be created.
*
@@ -4492,6 +4559,12 @@
case R.styleable.View_nextFocusForward:
mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
break;
+ case R.styleable.View_nextClusterForward:
+ mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
+ break;
+ case R.styleable.View_nextSectionForward:
+ mNextSectionForwardId = a.getResourceId(attr, View.NO_ID);
+ break;
case R.styleable.View_minWidth:
mMinWidth = a.getDimensionPixelSize(attr, 0);
break;
@@ -4628,10 +4701,19 @@
forceHasOverlappingRendering(a.getBoolean(attr, true));
}
break;
-
case R.styleable.View_tooltip:
setTooltip(a.getText(attr));
break;
+ case R.styleable.View_keyboardNavigationCluster:
+ if (a.peekValue(attr) != null) {
+ setKeyboardNavigationCluster(a.getBoolean(attr, true));
+ }
+ break;
+ case R.styleable.View_keyboardNavigationSection:
+ if (a.peekValue(attr) != null) {
+ setKeyboardNavigationSection(a.getBoolean(attr, true));
+ }
+ break;
}
}
@@ -6757,8 +6839,35 @@
* {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
* @param structure Fill in with structured view data. The default implementation
* fills in all data that can be inferred from the view itself.
+ *
+ * @deprecated As of API O sub-classes should override
+ * {@link #onProvideStructure(ViewStructure, int)} instead.
*/
+ // TODO(b/33197203): set proper API above
+ @Deprecated
public void onProvideStructure(ViewStructure structure) {
+ onProvideStructure(structure, 0);
+ }
+
+ /**
+ * Called when assist structure is being retrieved from a view as part of
+ * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} or as part
+ * of an auto-fill request.
+ *
+ * <p>The default implementation fills in all data that can be inferred from the view itself.
+ *
+ * <p>The structure must be filled according to the request type, which is set in the
+ * {@code flags} parameter - see the documentation on each flag for more details.
+ *
+ * @param structure Fill in with structured view data. The default implementation
+ * fills in all data that can be inferred from the view itself.
+ * @param flags optional flags (see {@link #ASSIST_FLAG_SANITIZED_TEXT} and
+ * {@link #ASSIST_FLAG_NON_SANITIZED_TEXT} for more info).
+ */
+ public void onProvideStructure(ViewStructure structure, int flags) {
+ boolean forAutoFill = (flags
+ & (View.ASSIST_FLAG_SANITIZED_TEXT
+ | View.ASSIST_FLAG_NON_SANITIZED_TEXT)) != 0;
final int id = mID;
if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
&& (id&0x0000ffff) != 0) {
@@ -6776,9 +6885,11 @@
structure.setId(id, null, null, null);
}
- // The auto-fill id needs to be unique, but its value doesn't matter, so it's better to
- // reuse the accessibility id to save space.
- structure.setAutoFillId(getAccessibilityViewId());
+ if (forAutoFill) {
+ // The auto-fill id needs to be unique, but its value doesn't matter, so it's better to
+ // reuse the accessibility id to save space.
+ structure.setAutoFillId(getAccessibilityViewId());
+ }
structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
if (!hasIdentityMatrix()) {
@@ -6828,20 +6939,52 @@
* uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
* view's virtual accessibility nodes, if any. You can override this for a more
* optimal implementation providing this data.
+ *
+ * @deprecated As of API O, sub-classes should override
+ * {@link #onProvideVirtualStructure(ViewStructure, int)} instead.
*/
+ // TODO(b/33197203): set proper API above
+ @Deprecated
public void onProvideVirtualStructure(ViewStructure structure) {
+ onProvideVirtualStructure(structure, 0);
+ }
+
+ /**
+ * Called when assist structure is being retrieved from a view as part of
+ * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} or as part
+ * of an auto-fill request to generate additional virtual structure under this view.
+ *
+ * <p>The defaullt implementation uses {@link #getAccessibilityNodeProvider()} to try to
+ * generate this from the view's virtual accessibility nodes, if any. You can override this
+ * for a more optimal implementation providing this data.
+ *
+ * <p>The structure must be filled according to the request type, which is set in the
+ * {@code flags} parameter - see the documentation on each flag for more details.
+ *
+ * @param structure Fill in with structured view data.
+ * @param flags optional flags (see {@link #ASSIST_FLAG_SANITIZED_TEXT} and
+ * {@link #ASSIST_FLAG_NON_SANITIZED_TEXT} for more info).
+ */
+ public void onProvideVirtualStructure(ViewStructure structure, int flags) {
+ boolean sanitize = (flags & View.ASSIST_FLAG_SANITIZED_TEXT) != 0;
+
+ if (sanitize) {
+ // TODO(b/33197203): change populateVirtualStructure so it sanitizes data in this case.
+ return;
+ }
+
AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
if (provider != null) {
AccessibilityNodeInfo info = createAccessibilityNodeInfo();
structure.setChildCount(1);
ViewStructure root = structure.newChild(0);
- populateVirtualStructure(root, provider, info);
+ populateVirtualStructure(root, provider, info, flags);
info.recycle();
}
}
private void populateVirtualStructure(ViewStructure structure,
- AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
+ AccessibilityNodeProvider provider, AccessibilityNodeInfo info, int flags) {
structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
null, null, null);
Rect rect = structure.getTempRect();
@@ -6890,7 +7033,7 @@
AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
ViewStructure child = structure.newChild(i);
- populateVirtualStructure(child, provider, cinfo);
+ populateVirtualStructure(child, provider, cinfo, flags);
cinfo.recycle();
}
}
@@ -6900,11 +7043,38 @@
* Dispatch creation of {@link ViewStructure} down the hierarchy. The default
* implementation calls {@link #onProvideStructure} and
* {@link #onProvideVirtualStructure}.
+ *
+ * @deprecated As of API O, sub-classes should override
+ * {@link #dispatchProvideStructure(ViewStructure, int)} instead.
*/
+ // TODO(b/33197203): set proper API above
+ @Deprecated
public void dispatchProvideStructure(ViewStructure structure) {
- if (!isAssistBlocked()) {
- onProvideStructure(structure);
- onProvideVirtualStructure(structure);
+ dispatchProvideStructure(structure, 0);
+ }
+
+ /**
+ * Dispatch creation of {@link ViewStructure} down the hierarchy.
+ *
+ * <p>The structure must be filled according to the request type, which is set in the
+ * {@code flags} parameter - see the documentation on each flag for more details.
+ *
+ * <p>The default implementation calls {@link #onProvideStructure(ViewStructure, int)} and
+ * {@link #onProvideVirtualStructure(ViewStructure, int)}.
+ *
+ * @param structure Fill in with structured view data.
+ * @param flags optional flags (see {@link #ASSIST_FLAG_SANITIZED_TEXT} and
+ * {@link #ASSIST_FLAG_NON_SANITIZED_TEXT} for more info).
+ */
+ public void dispatchProvideStructure(ViewStructure structure, int flags) {
+ boolean forAutoFill = (flags
+ & (View.ASSIST_FLAG_SANITIZED_TEXT
+ | View.ASSIST_FLAG_NON_SANITIZED_TEXT)) != 0;
+
+ boolean blocked = forAutoFill ? isAutoFillBlocked() : isAssistBlocked();
+ if (!blocked) {
+ onProvideStructure(structure, flags);
+ onProvideVirtualStructure(structure, flags);
} else {
structure.setClassName(getAccessibilityClassName().toString());
structure.setAssistBlocked(true);
@@ -7725,6 +7895,50 @@
}
/**
+ * Gets the id of the root of the next keyboard navigation cluster.
+ * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
+ * decide automatically.
+ *
+ * @attr ref android.R.styleable#View_nextClusterForward
+ */
+ public int getNextClusterForwardId() {
+ return mNextClusterForwardId;
+ }
+
+ /**
+ * Sets the id of the view to use as the root of the next keyboard navigation cluster.
+ * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
+ * decide automatically.
+ *
+ * @attr ref android.R.styleable#View_nextClusterForward
+ */
+ public void setNextClusterForwardId(int nextClusterForwardId) {
+ mNextClusterForwardId = nextClusterForwardId;
+ }
+
+ /**
+ * Gets the id of the root of the next keyboard navigation section.
+ * @return The next keyboard navigation section ID, or {@link #NO_ID} if the framework should
+ * decide automatically.
+ *
+ * @attr ref android.R.styleable#View_nextSectionForward
+ */
+ public int getNextSectionForwardId() {
+ return mNextSectionForwardId;
+ }
+
+ /**
+ * Sets the id of the view to use as the root of the next keyboard navigation section.
+ * @param nextSectionForwardId The next section ID, or {@link #NO_ID} if the framework should
+ * decide automatically.
+ *
+ * @attr ref android.R.styleable#View_nextSectionForward
+ */
+ public void setNextSectionForwardId(int nextSectionForwardId) {
+ mNextSectionForwardId = nextSectionForwardId;
+ }
+
+ /**
* Returns the visibility of this view and all of its ancestors
*
* @return True if this view and all of its ancestors are {@link #VISIBLE}
@@ -8643,6 +8857,25 @@
/**
* @hide
+ * Indicates whether this view will participate in data collection through
+ * {@link ViewStructure} for auto-fill purposes.
+ *
+ * <p>If {@code true}, it will not provide any data for itself or its children.
+ * <p>If {@code false}, the normal data collection will be allowed.
+ *
+ * @return Returns {@code false} if assist data collection for auto-fill is not blocked,
+ * else {@code true}.
+ *
+ * TODO(b/33197203): update / remove javadoc tags below
+ * @see #setAssistBlocked(boolean)
+ * @attr ref android.R.styleable#View_assistBlocked
+ */
+ public boolean isAutoFillBlocked() {
+ return false; // TODO(b/33197203): properly implement it
+ }
+
+ /**
+ * @hide
* Controls whether assist data collection from this view and its children is enabled
* (that is, whether {@link #onProvideStructure} and
* {@link #onProvideVirtualStructure} will be called). The default value is false,
@@ -8801,6 +9034,58 @@
}
/**
+ * Returns whether this View is a root of a keyboard navigation cluster.
+ *
+ * @return True if this view is a root of a cluster, or false otherwise.
+ * @attr ref android.R.styleable#View_keyboardNavigationCluster
+ */
+ @ViewDebug.ExportedProperty(category = "keyboardNavigationCluster")
+ public final boolean isKeyboardNavigationCluster() {
+ return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
+ }
+
+ /**
+ * Set whether this view is a root of a keyboard navigation cluster.
+ *
+ * @param isCluster If true, this view is a root of a cluster.
+ *
+ * @attr ref android.R.styleable#View_keyboardNavigationCluster
+ */
+ public void setKeyboardNavigationCluster(boolean isCluster) {
+ if (isCluster) {
+ mPrivateFlags3 |= PFLAG3_CLUSTER;
+ } else {
+ mPrivateFlags3 &= ~PFLAG3_CLUSTER;
+ }
+ }
+
+ /**
+ * Returns whether this View is a root of a keyboard navigation section.
+ *
+ * @return True if this view is a root of a section, or false otherwise.
+ * @attr ref android.R.styleable#View_keyboardNavigationSection
+ */
+ @ViewDebug.ExportedProperty(category = "keyboardNavigationSection")
+ public final boolean isKeyboardNavigationSection() {
+ return (mPrivateFlags3 & PFLAG3_SECTION) != 0;
+ }
+
+ /**
+ * Set whether this view is a root of a keyboard navigation section.
+ *
+ * @param isSection If true, this view is a root of a section.
+ *
+ * @attr ref android.R.styleable#View_keyboardNavigationSection
+ */
+ public void setKeyboardNavigationSection(boolean isSection) {
+ if (isSection) {
+ mPrivateFlags3 |= PFLAG3_SECTION;
+ } else {
+ mPrivateFlags3 &= ~PFLAG3_SECTION;
+ }
+ }
+
+ /**
* This method is the last chance for the focused view and its ancestors to
* respond to an arrow key. This is called when the focused view did not
* consume the key internally, nor could the view system find a new view in
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 0f8200d..ff797d1 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3083,14 +3083,22 @@
}
/**
- * Dispatch creation of {@link ViewStructure} down the hierarchy. This implementation
- * adds in all child views of the view group, in addition to calling the default View
- * implementation.
+ * {@inheritDoc}
+ *
+ * <p>This implementation adds in all child views of the view group, in addition to calling the
+ * default {@link View} implementation.
*/
@Override
- public void dispatchProvideStructure(ViewStructure structure) {
- super.dispatchProvideStructure(structure);
- if (!isAssistBlocked()) {
+ public void dispatchProvideStructure(ViewStructure structure, int flags) {
+ super.dispatchProvideStructure(structure, flags);
+
+ boolean forAutoFill = (flags
+ & (View.ASSIST_FLAG_SANITIZED_TEXT
+ | View.ASSIST_FLAG_NON_SANITIZED_TEXT)) != 0;
+
+ boolean blocked = forAutoFill ? isAutoFillBlocked() : isAssistBlocked();
+
+ if (!blocked) {
if (structure.getChildCount() == 0) {
final int childrenCount = getChildCount();
if (childrenCount > 0) {
@@ -3151,7 +3159,14 @@
final View child = getAndVerifyPreorderedView(
preorderedList, children, childIndex);
final ViewStructure cstructure = structure.newChild(i);
- child.dispatchProvideStructure(cstructure);
+
+ // Must explicitly check which recursive method to call because child might
+ // not be overriding the new, flags-based version
+ if (flags == 0) {
+ child.dispatchProvideStructure(cstructure);
+ } else {
+ child.dispatchProvideStructure(cstructure, flags);
+ }
}
if (preorderedList != null) preorderedList.clear();
}
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index 7dd2fc2..e4d4e7b 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -385,6 +385,14 @@
}
}
+ if (observer.mOnDrawListeners != null) {
+ if (mOnDrawListeners != null) {
+ mOnDrawListeners.addAll(observer.mOnDrawListeners);
+ } else {
+ mOnDrawListeners = observer.mOnDrawListeners;
+ }
+ }
+
if (observer.mOnTouchModeChangeListeners != null) {
if (mOnTouchModeChangeListeners != null) {
mOnTouchModeChangeListeners.addAll(observer.mOnTouchModeChangeListeners);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 2c13831..7c1bcee 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -301,6 +301,7 @@
private boolean mDestroyed;
private boolean mOverlayWithDecorCaptionEnabled = false;
+ private boolean mCloseOnSwipeEnabled = false;
// The current window attributes.
private final WindowManager.LayoutParams mWindowAttributes =
@@ -579,8 +580,10 @@
* Called when a window is dismissed. This informs the callback that the
* window is gone, and it should finish itself.
* @param finishTask True if the task should also be finished.
+ * @param suppressWindowTransition True if the resulting exit and enter window transition
+ * animations should be suppressed.
*/
- void onWindowDismissed(boolean finishTask);
+ void onWindowDismissed(boolean finishTask, boolean suppressWindowTransition);
}
/** @hide */
@@ -869,9 +872,10 @@
}
/** @hide */
- public final void dispatchOnWindowDismissed(boolean finishTask) {
+ public final void dispatchOnWindowDismissed(
+ boolean finishTask, boolean suppressWindowTransition) {
if (mOnWindowDismissedCallback != null) {
- mOnWindowDismissedCallback.onWindowDismissed(finishTask);
+ mOnWindowDismissedCallback.onWindowDismissed(finishTask, suppressWindowTransition);
}
}
@@ -2209,4 +2213,21 @@
* @hide
*/
public abstract void reportActivityRelaunched();
+
+ /**
+ * Called to set flag to check if the close on swipe is enabled. This will only function if
+ * FEATURE_SWIPE_TO_DISMISS has been set.
+ * @hide
+ */
+ public void setCloseOnSwipeEnabled(boolean closeOnSwipeEnabled) {
+ mCloseOnSwipeEnabled = closeOnSwipeEnabled;
+ }
+
+ /**
+ * @return {@code true} if the close on swipe is enabled.
+ * @hide
+ */
+ public boolean isCloseOnSwipeEnabled() {
+ return mCloseOnSwipeEnabled;
+ }
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index b8408dd..aa7631d 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -922,8 +922,11 @@
* unlock credential) than the user will still need to confirm it before
* seeing this window, unless {@link #FLAG_SHOW_WHEN_LOCKED} has
* also been set.
- * @see KeyguardManager#dismissKeyguard
+ * @deprecated Use {@link #FLAG_SHOW_WHEN_LOCKED} or {@link KeyguardManager#dismissKeyguard}
+ * instead. The Keyguard should never be dismissed automatically repeatedly as it also
+ * guards against unintentional touches.
*/
+ @Deprecated
public static final int FLAG_DISMISS_KEYGUARD = 0x00400000;
/** Window flag: when set the window will accept for touch events
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 2f55fc9..caa09cc 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -482,16 +482,6 @@
*/
public void switchInputMethod(boolean forwardDirection);
- /**
- * Returns the visibility of the current input method window (false if there is none).
- */
- public boolean isInputMethodWindowVisible();
-
- /**
- * Hides the current input method, if visible.
- */
- public void hideCurrentInputMethod();
-
public void shutdown(boolean confirm);
public void reboot(boolean confirm);
public void rebootSafeMode(boolean confirm);
@@ -523,6 +513,11 @@
void notifyShowingDreamChanged();
/**
+ * @return The currently active input method window.
+ */
+ WindowState getInputMethodWindowLw();
+
+ /**
* Notifies window manager that {@link #isKeyguardTrustedLw} has changed.
*/
void notifyKeyguardTrustedChanged();
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 8084195..13d5b85 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -350,7 +350,18 @@
return;
}
if (!mIsEnabled) {
- throw new IllegalStateException("Accessibility off. Did you forget to check that?");
+ Looper myLooper = Looper.myLooper();
+ if (myLooper == Looper.getMainLooper()) {
+ throw new IllegalStateException(
+ "Accessibility off. Did you forget to check that?");
+ } else {
+ // If we're not running on the thread with the main looper, it's possible for
+ // the state of accessibility to change between checking isEnabled and
+ // calling this method. So just log the error rather than throwing the
+ // exception.
+ Log.e(LOG_TAG, "Interrupt called with accessibility disabled");
+ return;
+ }
}
userId = mUserId;
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index b840f4a..8ecc42d 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2504,6 +2504,7 @@
return mProvider.getViewDelegate().shouldDelayChildPressedState();
}
+ @Override
public CharSequence getAccessibilityClassName() {
return WebView.class.getName();
}
@@ -2513,6 +2514,11 @@
mProvider.getViewDelegate().onProvideVirtualStructure(structure);
}
+ @Override
+ public void onProvideVirtualStructure(ViewStructure structure, int flags) {
+ mProvider.getViewDelegate().onProvideVirtualStructure(structure, flags);
+ }
+
/** @hide */
@Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 95ec179..7b95180 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -311,6 +311,11 @@
public void onProvideVirtualStructure(android.view.ViewStructure structure);
+ @SuppressWarnings("unused")
+ public default void onProvideVirtualStructure(android.view.ViewStructure structure,
+ int flags) {
+ }
+
public AccessibilityNodeProvider getAccessibilityNodeProvider();
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info);
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index c206974..e0d589a 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -53,6 +53,10 @@
return sPackage.packageName;
}
+ public static boolean isMultiprocessEnabled() {
+ return sMultiprocessEnabled && sPackage != null;
+ }
+
public static void setMultiprocessEnabled(boolean enabled) {
sMultiprocessEnabled = enabled;
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index a8d3984..043eb34 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -142,6 +142,12 @@
/** @hide */
@Override
+ protected boolean supportsAutoSizeText() {
+ return false;
+ }
+
+ /** @hide */
+ @Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfoInternal(info);
if (isEnabled()) {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index fc1520b..5fa1d2b 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1835,7 +1835,8 @@
// can expect the OnAttachStateChangeListener to have been called prior
// to executing this method, so we can rely on that instead.
final Transition exitTransition = mExitTransition;
- if (mIsAnchorRootAttached && exitTransition != null && decorView.isLaidOut()) {
+ if (exitTransition != null && decorView.isLaidOut()
+ && (mIsAnchorRootAttached || mAnchorRoot == null)) {
// The decor view is non-interactive and non-IME-focusable during exit transitions.
final LayoutParams p = (LayoutParams) decorView.getLayoutParams();
p.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
@@ -1843,18 +1844,13 @@
p.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
mWindowManager.updateViewLayout(decorView, p);
+ final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
+ final Rect epicenter = getTransitionEpicenter();
+
// Once we start dismissing the decor view, all state (including
// the anchor root) needs to be moved to the decor view since we
// may open another popup while it's busy exiting.
- final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
- final Rect epicenter = getTransitionEpicenter();
- exitTransition.setEpicenterCallback(new EpicenterCallback() {
- @Override
- public Rect onGetEpicenter(Transition transition) {
- return epicenter;
- }
- });
- decorView.startExitTransition(exitTransition, anchorRoot,
+ decorView.startExitTransition(exitTransition, anchorRoot, epicenter,
new TransitionListenerAdapter() {
@Override
public void onTransitionEnd(Transition transition) {
@@ -2349,8 +2345,9 @@
* its {@code onTransitionEnd} method called even if the transition
* never starts; however, it may be called with a {@code null} argument.
*/
- public void startExitTransition(Transition transition, final View anchorRoot,
- final TransitionListener listener) {
+ public void startExitTransition(@NonNull Transition transition,
+ @Nullable final View anchorRoot, @Nullable final Rect epicenter,
+ @NonNull final TransitionListener listener) {
if (transition == null) {
return;
}
@@ -2358,24 +2355,35 @@
// The anchor view's window may go away while we're executing our
// transition, in which case we need to end the transition
// immediately and execute the listener to remove the popup.
- anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
+ if (anchorRoot != null) {
+ anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
+ }
// The exit listener MUST be called for cleanup, even if the
// transition never starts or ends. Stash it for later.
mPendingExitListener = new TransitionListenerAdapter() {
@Override
- public void onTransitionEnd(Transition transition) {
- anchorRoot.removeOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
- listener.onTransitionEnd(transition);
+ public void onTransitionEnd(Transition t) {
+ if (anchorRoot != null) {
+ anchorRoot.removeOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
+ }
+
+ listener.onTransitionEnd(t);
// The listener was called. Our job here is done.
mPendingExitListener = null;
- transition.removeListener(this);
+ t.removeListener(this);
}
};
final Transition exitTransition = transition.clone();
exitTransition.addListener(mPendingExitListener);
+ exitTransition.setEpicenterCallback(new EpicenterCallback() {
+ @Override
+ public Rect onGetEpicenter(Transition transition) {
+ return epicenter;
+ }
+ });
final int count = getChildCount();
for (int i = 0; i < count; i++) {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index a9268d4e..eb46b9f 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -42,11 +42,13 @@
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.Process;
import android.os.StrictMode;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -92,6 +94,12 @@
static final String EXTRA_REMOTEADAPTER_APPWIDGET_ID = "remoteAdapterAppWidgetId";
/**
+ * Maximum depth of nested views calls from {@link #addView(int, RemoteViews)} and
+ * {@link #RemoteViews(RemoteViews, RemoteViews)}.
+ */
+ private static final int MAX_NESTED_VIEWS = 10;
+
+ /**
* Application that hosts the remote views.
*
* @hide
@@ -1538,11 +1546,11 @@
}
}
- ViewGroupAction(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info) {
+ ViewGroupAction(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info, int depth) {
viewId = parcel.readInt();
boolean nestedViewsNull = parcel.readInt() == 0;
if (!nestedViewsNull) {
- nestedViews = new RemoteViews(parcel, bitmapCache, info);
+ nestedViews = new RemoteViews(parcel, bitmapCache, info, depth);
} else {
nestedViews = null;
}
@@ -2209,10 +2217,16 @@
* @param parcel
*/
public RemoteViews(Parcel parcel) {
- this(parcel, null, null);
+ this(parcel, null, null, 0);
}
- private RemoteViews(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info) {
+ private RemoteViews(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info, int depth) {
+ if (depth > MAX_NESTED_VIEWS
+ && (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID)) {
+ throw new IllegalArgumentException("Too many nested views.");
+ }
+ depth++;
+
int mode = parcel.readInt();
// We only store a bitmap cache in the root of the RemoteViews.
@@ -2245,7 +2259,8 @@
mActions.add(new ReflectionAction(parcel));
break;
case ViewGroupAction.TAG:
- mActions.add(new ViewGroupAction(parcel, mBitmapCache, mApplication));
+ mActions.add(new ViewGroupAction(parcel, mBitmapCache, mApplication,
+ depth));
break;
case ReflectionActionWithoutParams.TAG:
mActions.add(new ReflectionActionWithoutParams(parcel));
@@ -2293,8 +2308,8 @@
}
} else {
// MODE_HAS_LANDSCAPE_AND_PORTRAIT
- mLandscape = new RemoteViews(parcel, mBitmapCache, info);
- mPortrait = new RemoteViews(parcel, mBitmapCache, mLandscape.mApplication);
+ mLandscape = new RemoteViews(parcel, mBitmapCache, info, depth);
+ mPortrait = new RemoteViews(parcel, mBitmapCache, mLandscape.mApplication, depth);
mApplication = mPortrait.mApplication;
mLayoutId = mPortrait.getLayoutId();
}
@@ -2318,7 +2333,7 @@
p.setDataPosition(0);
mIsRoot = true;
- RemoteViews rv = new RemoteViews(p, mBitmapCache.clone(), mApplication);
+ RemoteViews rv = new RemoteViews(p, mBitmapCache.clone(), mApplication, 0);
rv.mIsRoot = true;
p.recycle();
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index fcc1667..e629df9 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -1404,8 +1404,10 @@
}
@Override
- public void onProvideStructure(ViewStructure structure) {
- super.onProvideStructure(structure);
+ public void onProvideStructure(ViewStructure structure, int flags) {
+ super.onProvideStructure(structure, flags);
+
+ // NOTE: current there is no difference for Assist (flags=0) or AutoFill (flags>0);
CharSequence switchText = isChecked() ? mTextOn : mTextOff;
if (!TextUtils.isEmpty(switchText)) {
CharSequence oldText = structure.getText();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b85175d..1961bf6 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -77,6 +77,7 @@
import android.text.SpannedString;
import android.text.StaticLayout;
import android.text.TextAssistant;
+import android.text.TextClassificationManager;
import android.text.TextDirectionHeuristic;
import android.text.TextDirectionHeuristics;
import android.text.TextPaint;
@@ -680,8 +681,6 @@
private static final int DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX = 1;
// Contains the sorted set of desired text sizes in pixels to pick from when auto-sizing text.
private int[] mAutoSizeTextSizesInPx;
- // Specifies if the current TextView needs to be auto-sized.
- private boolean mNeedsTextAutoResize = false;
/**
* Kick-start the font cache for the zygote process (to pay the cost of
@@ -1534,7 +1533,7 @@
}
// Setup auto-size.
- if (mEditor == null) {
+ if (supportsAutoSizeText()) {
switch (mAutoSizeType) {
case AUTO_SIZE_TYPE_NONE:
// Nothing to do.
@@ -1561,7 +1560,6 @@
}
Arrays.sort(mAutoSizeTextSizesInPx);
- mNeedsTextAutoResize = true;
break;
default:
throw new IllegalArgumentException(
@@ -7524,7 +7522,7 @@
scrollTo(0, 0);
}
- if (mNeedsTextAutoResize) {
+ if (isAutoSizeEnabled()) {
// Call auto-size after the width and height have been calculated.
autoSizeText();
}
@@ -7536,20 +7534,21 @@
* Automatically computes and sets the text size.
*/
private void autoSizeText() {
+ final int maxWidth = getMeasuredWidth() - getTotalPaddingLeft() - getTotalPaddingRight();
+ final int maxHeight = getMeasuredHeight() - getTotalPaddingBottom() - getTotalPaddingTop();
+
+ if (maxWidth <= 0 || maxHeight <= 0) {
+ return;
+ }
+
synchronized (TEMP_RECTF) {
TEMP_RECTF.setEmpty();
- final int maxWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
- final int maxHeight = getMeasuredHeight() - getPaddingBottom() - getPaddingTop();
-
- if (maxWidth <= 0 || maxHeight <= 0) {
- return;
- }
-
TEMP_RECTF.right = maxWidth;
TEMP_RECTF.bottom = maxHeight;
final float textSize = findLargestTextSizeWhichFits(TEMP_RECTF);
- setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
- mNeedsTextAutoResize = false;
+ if (textSize != getTextSize()) {
+ setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
+ }
}
}
@@ -7594,13 +7593,12 @@
if ((mLayout instanceof BoringLayout) && BoringLayout.isBoring(
text, mTempTextPaint, getTextDirectionHeuristic(), mBoring) != null) {
- return mTempTextPaint.getFontSpacing() + getPaddingTop() + getPaddingBottom()
- <= availableSpace.bottom
- && mTempTextPaint.measureText(text, 0, text.length())
- + getPaddingLeft() + getPaddingRight() <= availableSpace.right;
+ return mTempTextPaint.getFontSpacing() <= availableSpace.bottom
+ && mTempTextPaint.measureText(text, 0, text.length()) <= availableSpace.right;
} else {
StaticLayout.Builder layoutBuilder = StaticLayout.Builder.obtain(text, 0, text.length(),
- mTempTextPaint, getMeasuredWidth() - getPaddingLeft() - getPaddingRight());
+ mTempTextPaint,
+ getMeasuredWidth() - getTotalPaddingLeft() - getTotalPaddingRight());
layoutBuilder.setAlignment(getLayoutAlignment());
layoutBuilder.setLineSpacing(getLineSpacingExtra(), getLineSpacingMultiplier());
layoutBuilder.setIncludePad(true);
@@ -9261,8 +9259,8 @@
}
/**
- * @return true if this TextView is specialized for showing and interacting with the extracted
- * text in a full-screen input method.
+ * @return {@code true} if this TextView is specialized for showing and interacting with the
+ * extracted text in a full-screen input method.
* @hide
*/
public boolean isInExtractedMode() {
@@ -9270,6 +9268,22 @@
}
/**
+ * @return {@code true} if this widget supports auto-sizing text and has been configured to
+ * auto-size.
+ */
+ private boolean isAutoSizeEnabled() {
+ return supportsAutoSizeText() && mAutoSizeType != AUTO_SIZE_TYPE_NONE;
+ }
+
+ /**
+ * @return {@code true} if this TextView supports auto-sizing text to fit within its container.
+ * @hide
+ */
+ protected boolean supportsAutoSizeText() {
+ return true;
+ }
+
+ /**
* This is a temporary method. Future versions may support multi-locale text.
* Caveat: This method may not return the latest spell checker locale, but this should be
* acceptable and it's more important to make this method asynchronous.
@@ -9377,11 +9391,14 @@
}
@Override
- public void onProvideStructure(ViewStructure structure) {
- super.onProvideStructure(structure);
+ public void onProvideStructure(ViewStructure structure, int flags) {
+ super.onProvideStructure(structure, flags);
+
+ final boolean forAutoFillSave =
+ (flags & ASSIST_FLAG_NON_SANITIZED_TEXT) != 0;
final boolean isPassword = hasPasswordTransformationMethod()
|| isPasswordInputType(getInputType());
- if (!isPassword) {
+ if (!isPassword || forAutoFillSave) {
if (mLayout == null) {
assumeLayout();
}
@@ -10019,8 +10036,8 @@
mTextAssistant = ((Activity) mContext).getTextAssistant();
} else {
// The context of this TextView should be an Activity. If it is not and no
- // text assistant has been set, return a NO_OP TextAssistant.
- mTextAssistant = TextAssistant.NO_OP;
+ // text assistant has been set, return the TextClassificationManager.
+ mTextAssistant = mContext.getSystemService(TextClassificationManager.class);
}
return mTextAssistant;
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index d8f7907..c314cae 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -19,6 +19,7 @@
import android.animation.ObjectAnimator;
import android.annotation.NonNull;
import android.app.Activity;
+import android.app.usage.UsageStatsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -299,6 +300,11 @@
|| aInfo.name.equals(IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE)) {
result = Intent.createChooser(result,
getIntent().getCharSequenceExtra(Intent.EXTRA_TITLE));
+
+ // Don't auto-launch single intents if the intent is being forwarded. This is done
+ // because automatically launching a resolving application as a response to the user
+ // action of switching accounts is pretty unexpected.
+ result.putExtra(Intent.EXTRA_AUTO_LAUNCH_SINGLE_CHOICE, false);
}
return result;
}
@@ -398,6 +404,7 @@
}
}
}
+ updateChooserCounts(target, mContentType);
return super.onTargetSelected(target, alwaysCheck);
}
@@ -542,20 +549,46 @@
// Do nothing. We'll send the voice stuff ourselves.
}
+ void updateChooserCounts(TargetInfo info, String annotation) {
+ if (info != null) {
+ UsageStatsManager usageStatsManager =
+ (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
+ if (usageStatsManager == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Can not start UsageStatsManager");
+ }
+ return;
+ }
+ final ResolveInfo ri = info.getResolveInfo();
+ if (ri != null && ri.activityInfo != null) {
+ usageStatsManager.reportChooserSelection(ri.activityInfo.packageName, getUserId(),
+ annotation, null, info.getResolvedIntent().getAction());
+ if (DEBUG) {
+ Log.d(TAG, "ResolveInfo Package is" + ri.activityInfo.packageName);
+ }
+ } else if(DEBUG) {
+ Log.d(TAG, "Can not log Chooser Counts of null ResovleInfo");
+ }
+ }
+ }
+
void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) {
if (mRefinementResultReceiver != null) {
mRefinementResultReceiver.destroy();
mRefinementResultReceiver = null;
}
-
if (selectedTarget == null) {
Log.e(TAG, "Refinement result intent did not match any known targets; canceling");
} else if (!checkTargetSourceIntent(selectedTarget, matchingIntent)) {
Log.e(TAG, "onRefinementResult: Selected target " + selectedTarget
+ " cannot match refined source intent " + matchingIntent);
- } else if (super.onTargetSelected(selectedTarget.cloneFilledIn(matchingIntent, 0), false)) {
- finish();
- return;
+ } else {
+ TargetInfo clonedTarget = selectedTarget.cloneFilledIn(matchingIntent, 0);
+ if (super.onTargetSelected(clonedTarget, false)) {
+ updateChooserCounts(clonedTarget, mContentType);
+ finish();
+ return;
+ }
}
onRefinementCanceled();
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index dd8ef18..c516b5c 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -26,6 +26,7 @@
import android.app.VoiceInteractor.Prompt;
import android.content.pm.ComponentInfo;
import android.os.AsyncTask;
+import android.os.RemoteException;
import android.provider.MediaStore;
import android.provider.Settings;
import android.text.TextUtils;
@@ -53,7 +54,6 @@
import android.os.Build;
import android.os.Bundle;
import android.os.PatternMatcher;
-import android.os.RemoteException;
import android.os.StrictMode;
import android.os.UserHandle;
import android.os.UserManager;
@@ -114,6 +114,7 @@
private ComponentName[] mFilteredComponents;
protected ResolverDrawerLayout mResolverDrawerLayout;
+ protected String mContentType;
private boolean mRegistered;
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@@ -270,6 +271,7 @@
final String referrerPackage = getReferrerPackageName();
mResolverComparator = new ResolverComparator(this, getTargetIntent(), referrerPackage);
+ mContentType = mResolverComparator.mContentType;
if (configureContentView(mIntents, initialIntents, rList, alwaysUseOption)) {
return;
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
index 4d4c7ce..75be906 100644
--- a/core/java/com/android/internal/app/ResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -63,6 +63,8 @@
private final long mSinceTime;
private final LinkedHashMap<ComponentName, ScoredTarget> mScoredTargets = new LinkedHashMap<>();
private final String mReferrerPackage;
+ public String mContentType;
+ private String mAction;
public ResolverComparator(Context context, Intent intent, String referrerPackage) {
mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
@@ -76,6 +78,8 @@
mCurrentTime = System.currentTimeMillis();
mSinceTime = mCurrentTime - USAGE_STATS_PERIOD;
mStats = mUsm.queryAndAggregateUsageStats(mSinceTime, mCurrentTime);
+ mContentType = intent.getType();
+ mAction = intent.getAction();
}
public void compute(List<ResolvedComponentInfo> targets) {
@@ -86,6 +90,7 @@
long mostRecentlyUsedTime = recentSinceTime + 1;
long mostTimeSpent = 1;
int mostLaunched = 1;
+ int mostSelected = 1;
for (ResolvedComponentInfo target : targets) {
final ScoredTarget scoredTarget
@@ -114,6 +119,25 @@
if (launched > mostLaunched) {
mostLaunched = launched;
}
+ // TODO(kanlig): get and combine counts of categories.
+
+ int selected = 0;
+ if (pkStats.mChooserCounts != null && mAction != null
+ && pkStats.mChooserCounts.get(mAction) != null) {
+ selected = pkStats.mChooserCounts.get(mAction).getOrDefault(mContentType, 0);
+ }
+ if (DEBUG) {
+ if (mAction == null) {
+ Log.d(TAG, "Action type is null");
+ } else {
+ Log.d(TAG, "Chooser Count of " + mAction + ":" +
+ target.name.getPackageName() + " is " + Integer.toString(selected));
+ }
+ }
+ scoredTarget.chooserCount = selected;
+ if (selected > mostSelected) {
+ mostSelected = selected;
+ }
}
}
@@ -190,7 +214,15 @@
lhs.activityInfo.packageName, lhs.activityInfo.name));
final ScoredTarget rhsTarget = mScoredTargets.get(new ComponentName(
rhs.activityInfo.packageName, rhs.activityInfo.name));
- final float diff = rhsTarget.score - lhsTarget.score;
+
+ final int chooserCountDiff = Long.compare(
+ rhsTarget.chooserCount, lhsTarget.chooserCount);
+
+ if (chooserCountDiff != 0) {
+ return chooserCountDiff > 0 ? 1 : -1;
+ }
+
+ final int diff = Float.compare(rhsTarget.score, lhsTarget.score);
if (diff != 0) {
return diff > 0 ? 1 : -1;
@@ -220,6 +252,7 @@
public long lastTimeUsed;
public long timeSpent;
public long launchCount;
+ public long chooserCount;
public ScoredTarget(ComponentInfo ci) {
componentInfo = ci;
@@ -232,6 +265,7 @@
+ " lastTimeUsed: " + lastTimeUsed
+ " timeSpent: " + timeSpent
+ " launchCount: " + launchCount
+ + " chooserCount: " + chooserCount
+ "}";
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index b60e6b5..99dbb1c 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -111,7 +111,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 150 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 151 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -1603,7 +1603,7 @@
@Override
public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
super.writeToParcel(out, elapsedRealtimeUs);
- out.writeLong(mMaxDurationMs);
+ out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
}
/**
@@ -1616,7 +1616,7 @@
@Override
public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs);
- out.writeLong(mMaxDurationMs);
+ out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000));
}
/**
@@ -1640,7 +1640,7 @@
public void onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
super.onTimeStarted(elapsedRealtimeUs, baseUptime, baseRealtime);
if (mNesting > 0) {
- mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000;
+ mStartTimeMs = baseRealtime / 1000;
}
}
@@ -1650,10 +1650,11 @@
* If the timer is running, add the duration into mCurrentDurationMs.
*/
@Override
- public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtime) {
- super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtime);
+ public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs) {
+ super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtimeUs);
if (mNesting > 0) {
- mCurrentDurationMs += (elapsedRealtimeUs / 1000) - mStartTimeMs;
+ // baseRealtimeUs has already been converted to the timebase's realtime.
+ mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs;
}
mStartTimeMs = -1;
}
@@ -1668,7 +1669,7 @@
super.startRunningLocked(elapsedRealtimeMs);
if (mNesting == 1 && mTimeBase.isRunning()) {
// Just started
- mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000;
+ mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000) / 1000;
}
}
@@ -1680,8 +1681,7 @@
*/
@Override
public void stopRunningLocked(long elapsedRealtimeMs) {
- super.stopRunningLocked(elapsedRealtimeMs);
- if (mNesting == 0) {
+ if (mNesting == 1) {
final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs);
if (durationMs > mMaxDurationMs) {
mMaxDurationMs = durationMs;
@@ -1689,6 +1689,9 @@
mStartTimeMs = -1;
mCurrentDurationMs = 0;
}
+ // super method decrements mNesting, which getCurrentDurationMsLocked relies on,
+ // so call super.stopRunningLocked after calling getCurrentDurationMsLocked.
+ super.stopRunningLocked(elapsedRealtimeMs);
}
@Override
@@ -1730,11 +1733,9 @@
@Override
public long getCurrentDurationMsLocked(long elapsedRealtimeMs) {
long durationMs = mCurrentDurationMs;
- if (mNesting > 0) {
- if (mTimeBase.isRunning()) {
- durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs*1000)/1000)
- - mStartTimeMs;
- }
+ if (mNesting > 0 && mTimeBase.isRunning()) {
+ durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs*1000)/1000)
+ - mStartTimeMs;
}
return durationMs;
}
diff --git a/core/java/com/android/internal/os/InstallerConnection.java b/core/java/com/android/internal/os/InstallerConnection.java
deleted file mode 100644
index 419c3d8..0000000
--- a/core/java/com/android/internal/os/InstallerConnection.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.internal.os;
-
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.Slog;
-
-import com.android.internal.util.Preconditions;
-
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-
-/**
- * Represents a connection to {@code installd}. Allows multiple connect and
- * disconnect cycles.
- *
- * @hide for internal use only
- */
-public class InstallerConnection {
- private static final String TAG = "InstallerConnection";
- private static final boolean LOCAL_DEBUG = false;
-
- private InputStream mIn;
- private OutputStream mOut;
- private LocalSocket mSocket;
-
- private volatile Object mWarnIfHeld;
-
- private final byte buf[] = new byte[1024];
-
- public InstallerConnection() {
- }
-
- /**
- * Yell loudly if someone tries making future calls while holding a lock on
- * the given object.
- */
- public void setWarnIfHeld(Object warnIfHeld) {
- Preconditions.checkState(mWarnIfHeld == null);
- mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld);
- }
-
- public synchronized String transact(String cmd) {
- if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
- Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
- + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
- }
-
- if (!connect()) {
- Slog.e(TAG, "connection failed");
- return "-1";
- }
-
- if (!writeCommand(cmd)) {
- /*
- * If installd died and restarted in the background (unlikely but
- * possible) we'll fail on the next write (this one). Try to
- * reconnect and write the command one more time before giving up.
- */
- Slog.e(TAG, "write command failed? reconnect!");
- if (!connect() || !writeCommand(cmd)) {
- return "-1";
- }
- }
- if (LOCAL_DEBUG) {
- Slog.i(TAG, "send: '" + cmd + "'");
- }
-
- final int replyLength = readReply();
- if (replyLength > 0) {
- String s = new String(buf, 0, replyLength);
- if (LOCAL_DEBUG) {
- Slog.i(TAG, "recv: '" + s + "'");
- }
- return s;
- } else {
- if (LOCAL_DEBUG) {
- Slog.i(TAG, "fail");
- }
- return "-1";
- }
- }
-
- public String[] execute(String cmd, Object... args) throws InstallerException {
- final StringBuilder builder = new StringBuilder(cmd);
- for (Object arg : args) {
- String escaped;
- if (arg == null) {
- escaped = "";
- } else {
- escaped = String.valueOf(arg);
- }
- if (escaped.indexOf('\0') != -1 || escaped.indexOf(' ') != -1 || "!".equals(escaped)) {
- throw new InstallerException(
- "Invalid argument while executing " + cmd + " " + Arrays.toString(args));
- }
- if (TextUtils.isEmpty(escaped)) {
- escaped = "!";
- }
- builder.append(' ').append(escaped);
- }
- final String[] resRaw = transact(builder.toString()).split(" ");
- int res = -1;
- try {
- res = Integer.parseInt(resRaw[0]);
- } catch (ArrayIndexOutOfBoundsException | NumberFormatException ignored) {
- }
- if (res != 0) {
- throw new InstallerException(
- "Failed to execute " + cmd + " " + Arrays.toString(args) + ": " + res);
- }
- return resRaw;
- }
-
- public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
- int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries)
- throws InstallerException {
- dexopt(apkPath, uid, "*", instructionSet, dexoptNeeded, null /*outputPath*/, dexFlags,
- compilerFilter, volumeUuid, sharedLibraries);
- }
-
- public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
- int dexoptNeeded, String outputPath, int dexFlags, String compilerFilter,
- String volumeUuid, String sharedLibraries) throws InstallerException {
- execute("dexopt",
- apkPath,
- uid,
- pkgName,
- instructionSet,
- dexoptNeeded,
- outputPath,
- dexFlags,
- compilerFilter,
- volumeUuid,
- sharedLibraries);
- }
-
- private boolean safeParseBooleanResult(String[] res) throws InstallerException {
- if ((res == null) || (res.length != 2)) {
- throw new InstallerException("Invalid size result: " + Arrays.toString(res));
- }
-
- // Just as a sanity check. Anything != "true" will be interpreted as false by parseBoolean.
- if (!res[1].equals("true") && !res[1].equals("false")) {
- throw new InstallerException("Invalid boolean result: " + Arrays.toString(res));
- }
-
- return Boolean.parseBoolean(res[1]);
- }
-
- public boolean mergeProfiles(int uid, String pkgName) throws InstallerException {
- final String[] res = execute("merge_profiles", uid, pkgName);
-
- return safeParseBooleanResult(res);
- }
-
- public boolean dumpProfiles(String gid, String packageName, String codePaths)
- throws InstallerException {
- final String[] res = execute("dump_profiles", gid, packageName, codePaths);
-
- return safeParseBooleanResult(res);
- }
-
- private boolean connect() {
- if (mSocket != null) {
- return true;
- }
- Slog.i(TAG, "connecting...");
- try {
- mSocket = new LocalSocket();
-
- LocalSocketAddress address = new LocalSocketAddress("installd",
- LocalSocketAddress.Namespace.RESERVED);
-
- mSocket.connect(address);
-
- mIn = mSocket.getInputStream();
- mOut = mSocket.getOutputStream();
- } catch (IOException ex) {
- disconnect();
- return false;
- }
- return true;
- }
-
- public void disconnect() {
- Slog.i(TAG, "disconnecting...");
- IoUtils.closeQuietly(mSocket);
- IoUtils.closeQuietly(mIn);
- IoUtils.closeQuietly(mOut);
-
- mSocket = null;
- mIn = null;
- mOut = null;
- }
-
-
- private boolean readFully(byte[] buffer, int len) {
- try {
- Streams.readFully(mIn, buffer, 0, len);
- } catch (IOException ioe) {
- Slog.e(TAG, "read exception");
- disconnect();
- return false;
- }
-
- if (LOCAL_DEBUG) {
- Slog.i(TAG, "read " + len + " bytes");
- }
-
- return true;
- }
-
- private int readReply() {
- if (!readFully(buf, 2)) {
- return -1;
- }
-
- final int len = (((int) buf[0]) & 0xff) | ((((int) buf[1]) & 0xff) << 8);
- if ((len < 1) || (len > buf.length)) {
- Slog.e(TAG, "invalid reply length (" + len + ")");
- disconnect();
- return -1;
- }
-
- if (!readFully(buf, len)) {
- return -1;
- }
-
- return len;
- }
-
- private boolean writeCommand(String cmdString) {
- final byte[] cmd = cmdString.getBytes();
- final int len = cmd.length;
- if ((len < 1) || (len > buf.length)) {
- return false;
- }
-
- buf[0] = (byte) (len & 0xff);
- buf[1] = (byte) ((len >> 8) & 0xff);
- try {
- mOut.write(buf, 0, 2);
- mOut.write(cmd, 0, len);
- } catch (IOException ex) {
- Slog.e(TAG, "write error");
- disconnect();
- return false;
- }
- return true;
- }
-
- public void waitForConnection() {
- for (;;) {
- try {
- execute("ping");
- return;
- } catch (InstallerException ignored) {
- }
- Slog.w(TAG, "installd not ready");
- SystemClock.sleep(1000);
- }
- }
-
- public static class InstallerException extends Exception {
- public InstallerException(String detailMessage) {
- super(detailMessage);
- }
- }
-}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index cdd267e..c88e9da 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -26,11 +26,16 @@
import android.icu.util.ULocale;
import android.net.LocalServerSocket;
import android.opengl.EGL14;
+import android.os.IInstalld;
import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.ZygoteProcess;
+import android.os.storage.StorageManager;
import android.security.keystore.AndroidKeyStoreProvider;
import android.system.ErrnoException;
import android.system.Os;
@@ -43,7 +48,6 @@
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.os.InstallerConnection.InstallerException;
import dalvik.system.DexFile;
import dalvik.system.PathClassLoader;
@@ -494,54 +498,55 @@
*/
private static void performSystemServerDexOpt(String classPath) {
final String[] classPathElements = classPath.split(":");
- final InstallerConnection installer = new InstallerConnection();
- installer.waitForConnection();
+ final IInstalld installd = IInstalld.Stub
+ .asInterface(ServiceManager.getService("installd"));
final String instructionSet = VMRuntime.getRuntime().vmInstructionSet();
- try {
- String sharedLibraries = "";
- for (String classPathElement : classPathElements) {
- // System server is fully AOTed and never profiled
- // for profile guided compilation.
- // TODO: Make this configurable between INTERPRET_ONLY, SPEED, SPACE and EVERYTHING?
+ String sharedLibraries = "";
+ for (String classPathElement : classPathElements) {
+ // System server is fully AOTed and never profiled
+ // for profile guided compilation.
+ // TODO: Make this configurable between INTERPRET_ONLY, SPEED, SPACE and EVERYTHING?
- int dexoptNeeded;
- try {
- dexoptNeeded = DexFile.getDexOptNeeded(
- classPathElement, instructionSet, "speed",
- false /* newProfile */);
- } catch (FileNotFoundException ignored) {
- // Do not add to the classpath.
- Log.w(TAG, "Missing classpath element for system server: " + classPathElement);
- continue;
- } catch (IOException e) {
- // Not fully clear what to do here as we don't know the cause of the
- // IO exception. Add to the classpath to be conservative, but don't
- // attempt to compile it.
- Log.w(TAG, "Error checking classpath element for system server: "
- + classPathElement, e);
- dexoptNeeded = DexFile.NO_DEXOPT_NEEDED;
- }
-
- if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- try {
- installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
- dexoptNeeded, 0 /*dexFlags*/, "speed", null /*volumeUuid*/,
- sharedLibraries);
- } catch (InstallerException e) {
- // Ignore (but log), we need this on the classpath for fallback mode.
- Log.w(TAG, "Failed compiling classpath element for system server: "
- + classPathElement, e);
- }
- }
-
- if (!sharedLibraries.isEmpty()) {
- sharedLibraries += ":";
- }
- sharedLibraries += classPathElement;
+ int dexoptNeeded;
+ try {
+ dexoptNeeded = DexFile.getDexOptNeeded(
+ classPathElement, instructionSet, "speed",
+ false /* newProfile */);
+ } catch (FileNotFoundException ignored) {
+ // Do not add to the classpath.
+ Log.w(TAG, "Missing classpath element for system server: " + classPathElement);
+ continue;
+ } catch (IOException e) {
+ // Not fully clear what to do here as we don't know the cause of the
+ // IO exception. Add to the classpath to be conservative, but don't
+ // attempt to compile it.
+ Log.w(TAG, "Error checking classpath element for system server: "
+ + classPathElement, e);
+ dexoptNeeded = DexFile.NO_DEXOPT_NEEDED;
}
- } finally {
- installer.disconnect();
+
+ if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
+ final String packageName = "*";
+ final String outputPath = null;
+ final int dexFlags = 0;
+ final String compilerFilter = "speed";
+ final String uuid = StorageManager.UUID_PRIVATE_INTERNAL;
+ try {
+ installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName,
+ instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter,
+ uuid, sharedLibraries);
+ } catch (RemoteException | ServiceSpecificException e) {
+ // Ignore (but log), we need this on the classpath for fallback mode.
+ Log.w(TAG, "Failed compiling classpath element for system server: "
+ + classPathElement, e);
+ }
+ }
+
+ if (!sharedLibraries.isEmpty()) {
+ sharedLibraries += ":";
+ }
+ sharedLibraries += classPathElement;
}
}
@@ -572,7 +577,7 @@
String args[] = {
"--setuid=1000",
"--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
+ "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 2a004cfb..ec068a3 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2502,6 +2502,7 @@
// System.out.println("Features: 0x" + Integer.toHexString(features));
if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
layoutResource = R.layout.screen_swipe_dismiss;
+ setCloseOnSwipeEnabled(true);
} else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
@@ -2573,7 +2574,7 @@
}
if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
- registerSwipeCallbacks();
+ registerSwipeCallbacks(contentParent);
}
// Remaining setup -- of background and title -- that only applies
@@ -2987,25 +2988,26 @@
return (mRightIconView = (ImageView)findViewById(R.id.right_icon));
}
- private void registerSwipeCallbacks() {
- SwipeDismissLayout swipeDismiss =
- (SwipeDismissLayout) findViewById(R.id.content);
+ private void registerSwipeCallbacks(ViewGroup contentParent) {
+ if (!(contentParent instanceof SwipeDismissLayout)) {
+ Log.w(TAG, "contentParent is not a SwipeDismissLayout: " + contentParent);
+ return;
+ }
+ SwipeDismissLayout swipeDismiss = (SwipeDismissLayout) contentParent;
swipeDismiss.setOnDismissedListener(new SwipeDismissLayout.OnDismissedListener() {
@Override
public void onDismissed(SwipeDismissLayout layout) {
- dispatchOnWindowDismissed(false /*finishTask*/);
+ dispatchOnWindowDismissed(false /*finishTask*/, true /*suppressWindowTransition*/);
}
});
swipeDismiss.setOnSwipeProgressChangedListener(
new SwipeDismissLayout.OnSwipeProgressChangedListener() {
- private static final float ALPHA_DECREASE = 0.5f;
- private boolean mIsTranslucent = false;
@Override
public void onSwipeProgressChanged(
- SwipeDismissLayout layout, float progress, float translate) {
+ SwipeDismissLayout layout, float alpha, float translate) {
WindowManager.LayoutParams newParams = getAttributes();
newParams.x = (int) translate;
- newParams.alpha = 1 - (progress * ALPHA_DECREASE);
+ newParams.alpha = alpha;
setAttributes(newParams);
int flags = 0;
@@ -3028,6 +3030,16 @@
});
}
+ /** @hide */
+ @Override
+ public void setCloseOnSwipeEnabled(boolean closeOnSwipeEnabled) {
+ if (hasFeature(Window.FEATURE_SWIPE_TO_DISMISS) // swipe-to-dismiss feature is requested
+ && mContentParent instanceof SwipeDismissLayout) { // check casting mContentParent
+ ((SwipeDismissLayout) mContentParent).setDismissable(closeOnSwipeEnabled);
+ }
+ super.setCloseOnSwipeEnabled(closeOnSwipeEnabled);
+ }
+
/**
* Helper method for calling the {@link Callback#onPanelClosed(int, Menu)}
* callback. This method will grab whatever extra state is needed for the
diff --git a/core/java/com/android/internal/view/OneShotPreDrawListener.java b/core/java/com/android/internal/view/OneShotPreDrawListener.java
index 98ffd82..42d104a 100644
--- a/core/java/com/android/internal/view/OneShotPreDrawListener.java
+++ b/core/java/com/android/internal/view/OneShotPreDrawListener.java
@@ -25,8 +25,6 @@
* OneShotPreDrawListener.add(view, () -> { view.doSomething(); })
* </code></pre>
* <p>
- * The onPreDraw always returns true.
- * <p>
* The listener will also remove itself from the ViewTreeObserver when the view
* is detached from the view hierarchy. In that case, the Runnable will never be
* executed.
@@ -36,22 +34,39 @@
private final View mView;
private ViewTreeObserver mViewTreeObserver;
private final Runnable mRunnable;
+ private final boolean mReturnValue;
- private OneShotPreDrawListener(View view, Runnable runnable) {
+ private OneShotPreDrawListener(View view, boolean returnValue, Runnable runnable) {
mView = view;
mViewTreeObserver = view.getViewTreeObserver();
mRunnable = runnable;
+ mReturnValue = returnValue;
}
/**
- * Creates a OneShotPreDrawListener and adds it to view's ViewTreeObserver.
+ * Creates a OneShotPreDrawListener and adds it to view's ViewTreeObserver. The
+ * return value from the OnPreDrawListener is {@code true}.
+ *
* @param view The view whose ViewTreeObserver the OnPreDrawListener should listen.
* @param runnable The Runnable to execute in the OnPreDraw (once)
* @return The added OneShotPreDrawListener. It can be removed prior to
* the onPreDraw by calling {@link #removeListener()}.
*/
public static OneShotPreDrawListener add(View view, Runnable runnable) {
- OneShotPreDrawListener listener = new OneShotPreDrawListener(view, runnable);
+ return add(view, true, runnable);
+ }
+
+ /**
+ * Creates a OneShotPreDrawListener and adds it to view's ViewTreeObserver.
+ *
+ * @param view The view whose ViewTreeObserver the OnPreDrawListener should listen.
+ * @param returnValue The value to be returned from the OnPreDrawListener.
+ * @param runnable The Runnable to execute in the OnPreDraw (once)
+ * @return The added OneShotPreDrawListener. It can be removed prior to
+ * the onPreDraw by calling {@link #removeListener()}.
+ */
+ public static OneShotPreDrawListener add(View view, boolean returnValue, Runnable runnable) {
+ OneShotPreDrawListener listener = new OneShotPreDrawListener(view, returnValue, runnable);
view.getViewTreeObserver().addOnPreDrawListener(listener);
view.addOnAttachStateChangeListener(listener);
return listener;
@@ -61,7 +76,7 @@
public boolean onPreDraw() {
removeListener();
mRunnable.run();
- return true;
+ return mReturnValue;
}
/**
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index 0bf170e..af4f777 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -20,28 +20,22 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.AttributeSet;
-import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
import android.widget.ActionMenuView;
import android.widget.ForwardingListener;
import android.widget.TextView;
-import android.widget.Toast;
/**
* @hide
*/
public class ActionMenuItemView extends TextView
- implements MenuView.ItemView, View.OnClickListener, View.OnLongClickListener,
- ActionMenuView.ActionMenuChildView {
+ implements MenuView.ItemView, View.OnClickListener, ActionMenuView.ActionMenuChildView {
private static final String TAG = "ActionMenuItemView";
private MenuItemImpl mItemData;
@@ -59,9 +53,6 @@
private static final int MAX_ICON_SIZE = 32; // dp
private int mMaxIconSize;
- private Toast mTooltip;
- private Runnable mShowTooltipRunnable = () -> showTooltip(Toast.LENGTH_LONG);
-
public ActionMenuItemView(Context context) {
this(context, null);
}
@@ -88,7 +79,6 @@
mMaxIconSize = (int) (MAX_ICON_SIZE * density + 0.5f);
setOnClickListener(this);
- setOnLongClickListener(this);
mSavedPaddingLeft = -1;
setSaveEnabled(false);
@@ -193,6 +183,9 @@
(mItemData.showsTextAsAction() && (mAllowTextWithIcon || mExpandedFormat));
setText(visible ? mTitle : null);
+
+ // Show the tooltip for items that do not already show text.
+ setTooltip(visible ? null : mTitle);
}
public void setIcon(Drawable icon) {
@@ -249,7 +242,6 @@
@Override
public boolean dispatchHoverEvent(MotionEvent event) {
- updateTooltip(event);
// Don't allow children to hover; we want this to be treated as a single component.
return onHoverEvent(event);
}
@@ -267,68 +259,6 @@
}
@Override
- public boolean onLongClick(View v) {
- return showTooltip(Toast.LENGTH_SHORT);
- }
-
- private boolean showTooltip(@Toast.Duration int duration) {
- if (hasText()) {
- // Don't show the cheat sheet for items that already show text.
- return false;
- }
-
- final int[] screenPos = new int[2];
- final Rect displayFrame = new Rect();
- getLocationOnScreen(screenPos);
- getWindowVisibleDisplayFrame(displayFrame);
-
- final Context context = getContext();
- final int width = getWidth();
- final int height = getHeight();
- final int midy = screenPos[1] + height / 2;
- int referenceX = screenPos[0] + width / 2;
- if (getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
- final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
- referenceX = screenWidth - referenceX; // mirror
- }
- hideTooltip ();
- mTooltip = Toast.makeText(context, mItemData.getTitle(), duration);
- if (midy < displayFrame.height()) {
- // Show along the top; follow action buttons
- mTooltip.setGravity(Gravity.TOP | Gravity.END, referenceX,
- screenPos[1] + height - displayFrame.top);
- } else {
- // Show along the bottom center
- mTooltip.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
- }
- mTooltip.show();
- return true;
- }
-
- private void hideTooltip() {
- if (mTooltip != null) {
- mTooltip.cancel();
- mTooltip = null;
- }
- getHandler().removeCallbacks(mShowTooltipRunnable);
- }
-
- private void updateTooltip(MotionEvent event) {
- AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
- if (manager.isEnabled() && manager.isTouchExplorationEnabled()) {
- return;
- }
-
- final int action = event.getAction();
- if (action == MotionEvent.ACTION_HOVER_MOVE) {
- hideTooltip();
- getHandler().postDelayed(mShowTooltipRunnable, ViewConfiguration.getLongPressTimeout());
- } else if (action == MotionEvent.ACTION_HOVER_EXIT) {
- hideTooltip();
- }
- }
-
- @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final boolean textVisible = hasText();
if (textVisible && mSavedPaddingLeft >= 0) {
diff --git a/core/java/com/android/internal/widget/DecorCaptionView.java b/core/java/com/android/internal/widget/DecorCaptionView.java
index c458ab1..b419113 100644
--- a/core/java/com/android/internal/widget/DecorCaptionView.java
+++ b/core/java/com/android/internal/widget/DecorCaptionView.java
@@ -408,7 +408,8 @@
if (mClickTarget == mMaximize) {
maximizeWindow();
} else if (mClickTarget == mClose) {
- mOwner.dispatchOnWindowDismissed(true /*finishTask*/);
+ mOwner.dispatchOnWindowDismissed(
+ true /*finishTask*/, false /*suppressWindowTransition*/);
}
return true;
}
diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java
index 358be60..a5d2bf3 100644
--- a/core/java/com/android/internal/widget/ImageFloatingTextView.java
+++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java
@@ -71,10 +71,14 @@
.setTextDirection(getTextDirectionHeuristic())
.setLineSpacing(getLineSpacingExtra(), getLineSpacingMultiplier())
.setIncludePad(getIncludeFontPadding())
- .setEllipsize(shouldEllipsize ? effectiveEllipsize : null)
- .setEllipsizedWidth(ellipsisWidth)
.setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
- .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
+ .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL)
+ .setMaxLines(getMaxLines() >= 0 ? getMaxLines() : Integer.MAX_VALUE);
+ if (shouldEllipsize) {
+ builder.setEllipsize(effectiveEllipsize)
+ .setEllipsizedWidth(ellipsisWidth);
+ }
+
// we set the endmargin on the requested number of lines.
int endMargin = getContext().getResources().getDimensionPixelSize(
R.dimen.notification_content_picture_margin);
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
index d2a43b7..cb123a1 100644
--- a/core/java/com/android/internal/widget/MessagingLinearLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -126,7 +126,8 @@
// Pretend we need the image padding for all views, we don't know which
// one will end up needing to do this (might end up not using all the space,
// but calculating this exactly would be more expensive).
- ((ImageFloatingTextView) child).setNumIndentLines(mIndentLines);
+ ((ImageFloatingTextView) child).setNumIndentLines(
+ mIndentLines == 2 ? 3 : mIndentLines);
}
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
@@ -147,6 +148,9 @@
// Now that we know which views to take, fix up the indents and see what width we get.
int measuredWidth = mPaddingLeft + mPaddingRight;
int imageLines = mIndentLines;
+ // Need to redo the height because it may change due to changing indents.
+ totalHeight = mPaddingTop + mPaddingBottom;
+ first = true;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
@@ -173,6 +177,9 @@
measuredWidth = Math.max(measuredWidth,
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin
+ mPaddingLeft + mPaddingRight);
+ totalHeight = Math.max(totalHeight, totalHeight + child.getMeasuredHeight() +
+ lp.topMargin + lp.bottomMargin + (first ? 0 : mSpacing));
+ first = false;
}
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index ffd9b24..4466575 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -40,7 +40,6 @@
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
-import android.widget.Toast;
/**
* This widget implements the dynamic action bar tab behavior that can change
@@ -360,7 +359,7 @@
tabView.getTab().select();
}
- private class TabView extends LinearLayout implements OnLongClickListener {
+ private class TabView extends LinearLayout {
private ActionBar.Tab mTab;
private TextView mTextView;
private ImageView mIconView;
@@ -472,35 +471,10 @@
if (mIconView != null) {
mIconView.setContentDescription(tab.getContentDescription());
}
-
- if (!hasText && !TextUtils.isEmpty(tab.getContentDescription())) {
- setOnLongClickListener(this);
- } else {
- setOnLongClickListener(null);
- setLongClickable(false);
- }
+ setTooltip(hasText? null : tab.getContentDescription());
}
}
- public boolean onLongClick(View v) {
- final int[] screenPos = new int[2];
- getLocationOnScreen(screenPos);
-
- final Context context = getContext();
- final int width = getWidth();
- final int height = getHeight();
- final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
-
- Toast cheatSheet = Toast.makeText(context, mTab.getContentDescription(),
- Toast.LENGTH_SHORT);
- // Show under the tab
- cheatSheet.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL,
- (screenPos[0] + width / 2) - screenWidth / 2, height);
-
- cheatSheet.show();
- return true;
- }
-
public ActionBar.Tab getTab() {
return mTab;
}
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index d88f479..83b49eb 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -16,6 +16,10 @@
package com.android.internal.widget;
+import android.animation.Animator;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -30,6 +34,7 @@
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
/**
@@ -49,12 +54,12 @@
/**
* Called when the layout has been swiped and the position of the window should change.
*
- * @param progress A number in [0, 1] representing how far to the
- * right the window has been swiped
+ * @param alpha A number in [0, 1] representing what the alpha transparency of the window
+ * should be.
* @param translate A number in [0, w], where w is the width of the
* layout. This is equivalent to progress * layout.getWidth().
*/
- void onSwipeProgressChanged(SwipeDismissLayout layout, float progress, float translate);
+ void onSwipeProgressChanged(SwipeDismissLayout layout, float alpha, float translate);
void onSwipeCancelled(SwipeDismissLayout layout);
}
@@ -72,6 +77,9 @@
private boolean mDiscardIntercept;
private VelocityTracker mVelocityTracker;
private float mTranslationX;
+ private boolean mBlockGesture = false;
+
+ private final DismissAnimator mDismissAnimator = new DismissAnimator();
private OnDismissedListener mDismissedListener;
private OnSwipeProgressChangedListener mProgressListener;
@@ -110,6 +118,8 @@
private float mLastX;
+ private boolean mDismissable = true;
+
public SwipeDismissLayout(Context context) {
super(context);
init(context);
@@ -166,6 +176,14 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
+ checkGesture((ev));
+ if (mBlockGesture) {
+ return true;
+ }
+ if (!mDismissable) {
+ return super.onInterceptTouchEvent(ev);
+ }
+
// offset because the view is translated during swipe
ev.offsetLocation(mTranslationX, 0);
@@ -225,7 +243,11 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (mVelocityTracker == null) {
+ checkGesture((ev));
+ if (mBlockGesture) {
+ return true;
+ }
+ if (mVelocityTracker == null || !mDismissable) {
return super.onTouchEvent(ev);
}
// offset because the view is translated during swipe
@@ -234,9 +256,9 @@
case MotionEvent.ACTION_UP:
updateDismiss(ev);
if (mDismissed) {
- dismiss();
+ mDismissAnimator.animateDismissal(ev.getRawX() - mDownX);
} else if (mSwiping) {
- cancel();
+ mDismissAnimator.animateRecovery(ev.getRawX() - mDownX);
}
resetMembers();
break;
@@ -264,7 +286,8 @@
private void setProgress(float deltaX) {
mTranslationX = deltaX;
if (mProgressListener != null && deltaX >= 0) {
- mProgressListener.onSwipeProgressChanged(this, deltaX / getWidth(), deltaX);
+ mProgressListener.onSwipeProgressChanged(
+ this, progressToAlpha(deltaX / getWidth()), deltaX);
}
}
@@ -363,4 +386,100 @@
return checkV && v.canScrollHorizontally((int) -dx);
}
+
+ public void setDismissable(boolean dismissable) {
+ if (!dismissable && mDismissable) {
+ cancel();
+ resetMembers();
+ }
+
+ mDismissable = dismissable;
+ }
+
+ private void checkGesture(MotionEvent ev) {
+ if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mBlockGesture = mDismissAnimator.isAnimating();
+ }
+ }
+
+ private float progressToAlpha(float progress) {
+ return 1 - progress * progress * progress;
+ }
+
+ private class DismissAnimator implements AnimatorUpdateListener, Animator.AnimatorListener {
+ private final TimeInterpolator DISMISS_INTERPOLATOR = new DecelerateInterpolator(1.5f);
+ private final long DISMISS_DURATION = 250;
+
+ private final ValueAnimator mDismissAnimator = new ValueAnimator();
+ private boolean mWasCanceled = false;
+ private boolean mDismissOnComplete = false;
+
+ /* package */ DismissAnimator() {
+ mDismissAnimator.addUpdateListener(this);
+ mDismissAnimator.addListener(this);
+ }
+
+ /* package */ void animateDismissal(float currentTranslation) {
+ animate(
+ currentTranslation / getWidth(),
+ 1,
+ DISMISS_DURATION,
+ DISMISS_INTERPOLATOR,
+ true /* dismiss */);
+ }
+
+ /* package */ void animateRecovery(float currentTranslation) {
+ animate(
+ currentTranslation / getWidth(),
+ 0,
+ DISMISS_DURATION,
+ DISMISS_INTERPOLATOR,
+ false /* don't dismiss */);
+ }
+
+ /* package */ boolean isAnimating() {
+ return mDismissAnimator.isStarted();
+ }
+
+ private void animate(float from, float to, long duration, TimeInterpolator interpolator,
+ boolean dismissOnComplete) {
+ mDismissAnimator.cancel();
+ mDismissOnComplete = dismissOnComplete;
+ mDismissAnimator.setFloatValues(from, to);
+ mDismissAnimator.setDuration(duration);
+ mDismissAnimator.setInterpolator(interpolator);
+ mDismissAnimator.start();
+ }
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float value = (Float) animation.getAnimatedValue();
+ setProgress(value * getWidth());
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mWasCanceled = false;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mWasCanceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mWasCanceled) {
+ if (mDismissOnComplete) {
+ dismiss();
+ } else {
+ cancel();
+ }
+ }
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ }
+ }
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 77934fe..44b6e1a 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -136,7 +136,6 @@
android/graphics/PathEffect.cpp \
android/graphics/Picture.cpp \
android/graphics/BitmapRegionDecoder.cpp \
- android/graphics/Rasterizer.cpp \
android/graphics/Region.cpp \
android/graphics/Shader.cpp \
android/graphics/SurfaceTexture.cpp \
@@ -249,6 +248,7 @@
libGLESv1_CM \
libGLESv2 \
libvulkan \
+ libziparchive \
libETC1 \
libhardware \
libhardware_legacy \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 1f810ac..d47c6b7 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -121,13 +121,11 @@
extern int register_android_graphics_ColorFilter(JNIEnv* env);
extern int register_android_graphics_DrawFilter(JNIEnv* env);
extern int register_android_graphics_FontFamily(JNIEnv* env);
-extern int register_android_graphics_LayerRasterizer(JNIEnv*);
extern int register_android_graphics_Matrix(JNIEnv* env);
extern int register_android_graphics_Paint(JNIEnv* env);
extern int register_android_graphics_Path(JNIEnv* env);
extern int register_android_graphics_PathMeasure(JNIEnv* env);
extern int register_android_graphics_Picture(JNIEnv*);
-extern int register_android_graphics_Rasterizer(JNIEnv* env);
extern int register_android_graphics_Region(JNIEnv* env);
extern int register_android_graphics_SurfaceTexture(JNIEnv* env);
extern int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env);
@@ -1332,7 +1330,6 @@
REG_JNI(register_android_graphics_DrawFilter),
REG_JNI(register_android_graphics_FontFamily),
REG_JNI(register_android_graphics_Interpolator),
- REG_JNI(register_android_graphics_LayerRasterizer),
REG_JNI(register_android_graphics_MaskFilter),
REG_JNI(register_android_graphics_Matrix),
REG_JNI(register_android_graphics_Movie),
@@ -1342,7 +1339,6 @@
REG_JNI(register_android_graphics_PathMeasure),
REG_JNI(register_android_graphics_PathEffect),
REG_JNI(register_android_graphics_Picture),
- REG_JNI(register_android_graphics_Rasterizer),
REG_JNI(register_android_graphics_Region),
REG_JNI(register_android_graphics_Shader),
REG_JNI(register_android_graphics_SurfaceTexture),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index d9aa8f1..178e073 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -668,42 +668,34 @@
static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
jint format, jint quality,
jobject jstream, jbyteArray jstorage) {
-
- LocalScopedBitmap bitmap(bitmapHandle);
- SkImageEncoder::Type fm;
-
+ SkEncodedImageFormat fm;
switch (format) {
case kJPEG_JavaEncodeFormat:
- fm = SkImageEncoder::kJPEG_Type;
+ fm = SkEncodedImageFormat::kJPEG;
break;
case kPNG_JavaEncodeFormat:
- fm = SkImageEncoder::kPNG_Type;
+ fm = SkEncodedImageFormat::kPNG;
break;
case kWEBP_JavaEncodeFormat:
- fm = SkImageEncoder::kWEBP_Type;
+ fm = SkEncodedImageFormat::kWEBP;
break;
default:
return JNI_FALSE;
}
+ LocalScopedBitmap bitmap(bitmapHandle);
if (!bitmap.valid()) {
return JNI_FALSE;
}
- bool success = false;
-
std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
if (!strm.get()) {
return JNI_FALSE;
}
- std::unique_ptr<SkImageEncoder> encoder(SkImageEncoder::Create(fm));
- if (encoder.get()) {
- SkBitmap skbitmap;
- bitmap->getSkBitmap(&skbitmap);
- success = encoder->encodeStream(strm.get(), skbitmap, quality);
- }
- return success ? JNI_TRUE : JNI_FALSE;
+ SkBitmap skbitmap;
+ bitmap->getSkBitmap(&skbitmap);
+ return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
}
static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 2923f94..762a3f3 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -48,31 +48,31 @@
using namespace android;
-jstring encodedFormatToString(JNIEnv* env, SkEncodedFormat format) {
+jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format) {
const char* mimeType;
switch (format) {
- case SkEncodedFormat::kBMP_SkEncodedFormat:
+ case SkEncodedImageFormat::kBMP:
mimeType = "image/bmp";
break;
- case SkEncodedFormat::kGIF_SkEncodedFormat:
+ case SkEncodedImageFormat::kGIF:
mimeType = "image/gif";
break;
- case SkEncodedFormat::kICO_SkEncodedFormat:
+ case SkEncodedImageFormat::kICO:
mimeType = "image/x-ico";
break;
- case SkEncodedFormat::kJPEG_SkEncodedFormat:
+ case SkEncodedImageFormat::kJPEG:
mimeType = "image/jpeg";
break;
- case SkEncodedFormat::kPNG_SkEncodedFormat:
+ case SkEncodedImageFormat::kPNG:
mimeType = "image/png";
break;
- case SkEncodedFormat::kWEBP_SkEncodedFormat:
+ case SkEncodedImageFormat::kWEBP:
mimeType = "image/webp";
break;
- case SkEncodedFormat::kWBMP_SkEncodedFormat:
+ case SkEncodedImageFormat::kWBMP:
mimeType = "image/vnd.wap.wbmp";
break;
- case SkEncodedFormat::kDNG_SkEncodedFormat:
+ case SkEncodedImageFormat::kDNG:
mimeType = "image/x-adobe-dng";
break;
default:
@@ -276,6 +276,11 @@
}
}
+ if (isMutable && isHardware) {
+ doThrowIAE(env, "Bitmaps with Config.HARWARE are always immutable");
+ return nullObjectReturn("Cannot create mutable hardware bitmap");
+ }
+
// Create the codec.
NinePatchPeeker peeker;
std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(streamDeleter.release(),
@@ -309,7 +314,8 @@
// Set the options and return if the client only wants the size.
if (options != NULL) {
- jstring mimeType = encodedFormatToString(env, codec->getEncodedFormat());
+ jstring mimeType = encodedFormatToString(
+ env, (SkEncodedImageFormat)codec->getEncodedFormat());
if (env->ExceptionCheck()) {
return nullObjectReturn("OOM in encodedFormatToString()");
}
diff --git a/core/jni/android/graphics/BitmapFactory.h b/core/jni/android/graphics/BitmapFactory.h
index 07825df..76db41d 100644
--- a/core/jni/android/graphics/BitmapFactory.h
+++ b/core/jni/android/graphics/BitmapFactory.h
@@ -2,7 +2,7 @@
#define _ANDROID_GRAPHICS_BITMAP_FACTORY_H_
#include "GraphicsJNI.h"
-#include "SkEncodedFormat.h"
+#include "SkEncodedImageFormat.h"
extern jclass gOptions_class;
extern jfieldID gOptions_justBoundsFieldID;
@@ -20,7 +20,7 @@
extern jfieldID gOptions_mCancelID;
extern jfieldID gOptions_bitmapFieldID;
-jstring encodedFormatToString(JNIEnv* env, SkEncodedFormat format);
+jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format);
jobject decodeBitmap(JNIEnv* env, void* data, size_t size);
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 3b2d5d2..3247851 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -187,7 +187,7 @@
env->SetIntField(options, gOptions_widthFieldID, bitmap.width());
env->SetIntField(options, gOptions_heightFieldID, bitmap.height());
env->SetObjectField(options, gOptions_mimeFieldID,
- encodedFormatToString(env, brd->getEncodedFormat()));
+ encodedFormatToString(env, (SkEncodedImageFormat)brd->getEncodedFormat()));
if (env->ExceptionCheck()) {
return nullObjectReturn("OOM in encodedFormatToString()");
}
diff --git a/core/jni/android/graphics/Movie_FactoryDefault.cpp b/core/jni/android/graphics/Movie_FactoryDefault.cpp
index 175e0a6..610f08f 100644
--- a/core/jni/android/graphics/Movie_FactoryDefault.cpp
+++ b/core/jni/android/graphics/Movie_FactoryDefault.cpp
@@ -7,6 +7,7 @@
#include "Movie.h"
#include "SkStream.h"
+#include "SkTRegistry.h"
typedef SkTRegistry<Movie*(*)(SkStreamRewindable*)> MovieReg;
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 3456839..dfe809d 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -30,7 +30,6 @@
#include "SkMaskFilter.h"
#include "SkPath.h"
#include "SkPathEffect.h"
-#include "SkRasterizer.h"
#include "SkShader.h"
#include "SkBlendMode.h"
#include "unicode/uloc.h"
@@ -848,12 +847,6 @@
return 0;
}
- static jlong setRasterizer(jlong objHandle, jlong rasterizerHandle) {
- Paint* obj = reinterpret_cast<Paint*>(objHandle);
- obj->setRasterizer(GraphicsJNI::refNativeRasterizer(rasterizerHandle));
- return reinterpret_cast<jlong>(obj->getRasterizer());
- }
-
static jint getTextAlign(jlong objHandle) {
Paint* obj = reinterpret_cast<Paint*>(objHandle);
return static_cast<jint>(obj->getTextAlign());
@@ -1038,7 +1031,6 @@
{"nSetPathEffect","(JJ)J", (void*) PaintGlue::setPathEffect},
{"nSetMaskFilter","(JJ)J", (void*) PaintGlue::setMaskFilter},
{"nSetTypeface","(JJ)J", (void*) PaintGlue::setTypeface},
- {"nSetRasterizer","(JJ)J", (void*) PaintGlue::setRasterizer},
{"nGetTextAlign","(J)I", (void*) PaintGlue::getTextAlign},
{"nSetTextAlign","(JI)V", (void*) PaintGlue::setTextAlign},
{"nSetTextLocalesByMinikinLangListId","(JI)V",
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index ab393f2..292454b 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -36,7 +36,18 @@
class SkPathGlue {
public:
- static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
+ // ---------------- Regular JNI -----------------------------
+
+ static jlong init(JNIEnv* env, jclass clazz) {
+ return reinterpret_cast<jlong>(new SkPath());
+ }
+
+ static jlong init_Path(JNIEnv* env, jclass clazz, jlong valHandle) {
+ SkPath* val = reinterpret_cast<SkPath*>(valHandle);
+ return reinterpret_cast<jlong>(new SkPath(*val));
+ }
+
+ static void finalize(JNIEnv* env, jclass clazz, jlong objHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
// Purge entries from the HWUI path cache if this path's data is unique
if (obj->unique() && android::uirenderer::Caches::hasInstance()) {
@@ -45,112 +56,68 @@
delete obj;
}
- static jlong init1(JNIEnv* env, jobject clazz) {
- return reinterpret_cast<jlong>(new SkPath());
- }
-
- static jlong init2(JNIEnv* env, jobject clazz, jlong valHandle) {
- SkPath* val = reinterpret_cast<SkPath*>(valHandle);
- return reinterpret_cast<jlong>(new SkPath(*val));
- }
-
- static void reset(JNIEnv* env, jobject clazz, jlong objHandle) {
- SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
- obj->reset();
- }
-
- static void rewind(JNIEnv* env, jobject clazz, jlong objHandle) {
- SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
- obj->rewind();
- }
-
- static void assign(JNIEnv* env, jobject clazz, jlong dstHandle, jlong srcHandle) {
+ static void set(JNIEnv* env, jclass clazz, jlong dstHandle, jlong srcHandle) {
SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
const SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
*dst = *src;
}
- static jboolean isConvex(JNIEnv* env, jobject clazz, jlong objHandle) {
- SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
- return obj->isConvex();
- }
-
- static jint getFillType(JNIEnv* env, jobject clazz, jlong objHandle) {
- SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
- return obj->getFillType();
- }
-
- static void setFillType(JNIEnv* env, jobject clazz, jlong pathHandle, jint ftHandle) {
- SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
- SkPath::FillType ft = static_cast<SkPath::FillType>(ftHandle);
- path->setFillType(ft);
- }
-
- static jboolean isEmpty(JNIEnv* env, jobject clazz, jlong objHandle) {
- SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
- return obj->isEmpty();
- }
-
- static jboolean isRect(JNIEnv* env, jobject clazz, jlong objHandle, jobject jrect) {
- SkRect rect;
- SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
- jboolean result = obj->isRect(&rect);
- GraphicsJNI::rect_to_jrectf(rect, env, jrect);
- return result;
- }
-
- static void computeBounds(JNIEnv* env, jobject clazz, jlong objHandle, jobject jbounds) {
+ static void computeBounds(JNIEnv* env, jclass clazz, jlong objHandle, jobject jbounds) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
const SkRect& bounds = obj->getBounds();
GraphicsJNI::rect_to_jrectf(bounds, env, jbounds);
}
- static void incReserve(JNIEnv* env, jobject clazz, jlong objHandle, jint extraPtCount) {
+ static void incReserve(JNIEnv* env, jclass clazz, jlong objHandle, jint extraPtCount) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->incReserve(extraPtCount);
}
- static void moveTo__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y) {
+ static void moveTo__FF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x, jfloat y) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->moveTo(x, y);
}
- static void rMoveTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
+ static void rMoveTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx, jfloat dy) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->rMoveTo(dx, dy);
}
- static void lineTo__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y) {
+ static void lineTo__FF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x, jfloat y) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->lineTo(x, y);
}
- static void rLineTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
+ static void rLineTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx, jfloat dy) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->rLineTo(dx, dy);
}
- static void quadTo__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2) {
+ static void quadTo__FFFF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x1, jfloat y1,
+ jfloat x2, jfloat y2) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->quadTo(x1, y1, x2, y2);
}
- static void rQuadTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2) {
+ static void rQuadTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx1, jfloat dy1,
+ jfloat dx2, jfloat dy2) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->rQuadTo(dx1, dy1, dx2, dy2);
}
- static void cubicTo__FFFFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
+ static void cubicTo__FFFFFF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x1, jfloat y1,
+ jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->cubicTo(x1, y1, x2, y2, x3, y3);
}
- static void rCubicTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
+ static void rCubicTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x1, jfloat y1,
+ jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->rCubicTo(x1, y1, x2, y2, x3, y3);
}
- static void arcTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top,
+ static void arcTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat left, jfloat top,
jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
jboolean forceMoveTo) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
@@ -158,19 +125,19 @@
obj->arcTo(oval, startAngle, sweepAngle, forceMoveTo);
}
- static void close(JNIEnv* env, jobject clazz, jlong objHandle) {
+ static void close(JNIEnv* env, jclass clazz, jlong objHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->close();
}
- static void addRect(JNIEnv* env, jobject clazz, jlong objHandle,
+ static void addRect(JNIEnv* env, jclass clazz, jlong objHandle,
jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
obj->addRect(left, top, right, bottom, dir);
}
- static void addOval(JNIEnv* env, jobject clazz, jlong objHandle,
+ static void addOval(JNIEnv* env, jclass clazz, jlong objHandle,
jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
@@ -178,20 +145,21 @@
obj->addOval(oval, dir);
}
- static void addCircle(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y, jfloat radius, jint dirHandle) {
+ static void addCircle(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x, jfloat y,
+ jfloat radius, jint dirHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
obj->addCircle(x, y, radius, dir);
}
- static void addArc(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top,
+ static void addArc(JNIEnv* env, jclass clazz, jlong objHandle, jfloat left, jfloat top,
jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle) {
SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->addArc(oval, startAngle, sweepAngle);
}
- static void addRoundRectXY(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top,
+ static void addRoundRectXY(JNIEnv* env, jclass clazz, jlong objHandle, jfloat left, jfloat top,
jfloat right, jfloat bottom, jfloat rx, jfloat ry, jint dirHandle) {
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
@@ -199,8 +167,8 @@
obj->addRoundRect(rect, rx, ry, dir);
}
- static void addRoundRect8(JNIEnv* env, jobject, jlong objHandle, jfloat left, jfloat top,
- jfloat right, jfloat bottom, jfloatArray array, jint dirHandle) {
+ static void addRoundRect8(JNIEnv* env, jclass clazz, jlong objHandle, jfloat left, jfloat top,
+ jfloat right, jfloat bottom, jfloatArray array, jint dirHandle) {
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
@@ -213,49 +181,53 @@
obj->addRoundRect(rect, src, dir);
}
- static void addPath__PathFF(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jfloat dx, jfloat dy) {
+ static void addPath__PathFF(JNIEnv* env, jclass clazz, jlong objHandle, jlong srcHandle,
+ jfloat dx, jfloat dy) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
obj->addPath(*src, dx, dy);
}
- static void addPath__Path(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle) {
+ static void addPath__Path(JNIEnv* env, jclass clazz, jlong objHandle, jlong srcHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
obj->addPath(*src);
}
- static void addPath__PathMatrix(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jlong matrixHandle) {
+ static void addPath__PathMatrix(JNIEnv* env, jclass clazz, jlong objHandle, jlong srcHandle,
+ jlong matrixHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
obj->addPath(*src, *matrix);
}
- static void offset__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
+ static void offset__FF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx, jfloat dy) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->offset(dx, dy);
}
- static void setLastPoint(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
+ static void setLastPoint(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx, jfloat dy) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
obj->setLastPt(dx, dy);
}
- static void transform__MatrixPath(JNIEnv* env, jobject clazz, jlong objHandle, jlong matrixHandle, jlong dstHandle) {
+ static void transform__MatrixPath(JNIEnv* env, jclass clazz, jlong objHandle, jlong matrixHandle,
+ jlong dstHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
obj->transform(*matrix, dst);
}
- static void transform__Matrix(JNIEnv* env, jobject clazz, jlong objHandle, jlong matrixHandle) {
+ static void transform__Matrix(JNIEnv* env, jclass clazz, jlong objHandle, jlong matrixHandle) {
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
obj->transform(*matrix);
}
- static jboolean op(JNIEnv* env, jobject clazz, jlong p1Handle, jlong p2Handle, jint opHandle, jlong rHandle) {
+ static jboolean op(JNIEnv* env, jclass clazz, jlong p1Handle, jlong p2Handle, jint opHandle,
+ jlong rHandle) {
SkPath* p1 = reinterpret_cast<SkPath*>(p1Handle);
SkPath* p2 = reinterpret_cast<SkPath*>(p2Handle);
SkPathOp op = static_cast<SkPathOp>(opHandle);
@@ -416,8 +388,8 @@
// Note that more than one point may have the same length along the path in
// the case of a move.
// NULL can be returned if the Path is empty.
- static jfloatArray approximate(JNIEnv* env, jclass, jlong pathHandle, float acceptableError)
- {
+ static jfloatArray approximate(JNIEnv* env, jclass clazz, jlong pathHandle,
+ float acceptableError) {
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
SkASSERT(path);
SkPath::Iter pathIter(*path, false);
@@ -467,47 +439,94 @@
delete[] approximation;
return result;
}
+
+ // ---------------- @FastNative -----------------------------
+
+ static jboolean isRect(JNIEnv* env, jclass clazz, jlong objHandle, jobject jrect) {
+ SkRect rect;
+ SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
+ jboolean result = obj->isRect(&rect);
+ GraphicsJNI::rect_to_jrectf(rect, env, jrect);
+ return result;
+ }
+
+ // ---------------- @CriticalNative -------------------------
+
+ static void reset(jlong objHandle) {
+ SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
+ obj->reset();
+ }
+
+ static void rewind(jlong objHandle) {
+ SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
+ obj->rewind();
+ }
+
+ static jboolean isEmpty(jlong objHandle) {
+ SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
+ return obj->isEmpty();
+ }
+
+ static jboolean isConvex(jlong objHandle) {
+ SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
+ return obj->isConvex();
+ }
+
+ static jint getFillType(jlong objHandle) {
+ SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
+ return obj->getFillType();
+ }
+
+ static void setFillType(jlong pathHandle, jint ftHandle) {;
+ SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
+ SkPath::FillType ft = static_cast<SkPath::FillType>(ftHandle);
+ path->setFillType(ft);
+ }
};
static const JNINativeMethod methods[] = {
- {"finalizer", "(J)V", (void*) SkPathGlue::finalizer},
- {"init1","()J", (void*) SkPathGlue::init1},
- {"init2","(J)J", (void*) SkPathGlue::init2},
- {"native_reset","(J)V", (void*) SkPathGlue::reset},
- {"native_rewind","(J)V", (void*) SkPathGlue::rewind},
- {"native_set","(JJ)V", (void*) SkPathGlue::assign},
- {"native_isConvex","(J)Z", (void*) SkPathGlue::isConvex},
- {"native_getFillType","(J)I", (void*) SkPathGlue::getFillType},
- {"native_setFillType","(JI)V", (void*) SkPathGlue::setFillType},
- {"native_isEmpty","(J)Z", (void*) SkPathGlue::isEmpty},
- {"native_isRect","(JLandroid/graphics/RectF;)Z", (void*) SkPathGlue::isRect},
- {"native_computeBounds","(JLandroid/graphics/RectF;)V", (void*) SkPathGlue::computeBounds},
- {"native_incReserve","(JI)V", (void*) SkPathGlue::incReserve},
- {"native_moveTo","(JFF)V", (void*) SkPathGlue::moveTo__FF},
- {"native_rMoveTo","(JFF)V", (void*) SkPathGlue::rMoveTo},
- {"native_lineTo","(JFF)V", (void*) SkPathGlue::lineTo__FF},
- {"native_rLineTo","(JFF)V", (void*) SkPathGlue::rLineTo},
- {"native_quadTo","(JFFFF)V", (void*) SkPathGlue::quadTo__FFFF},
- {"native_rQuadTo","(JFFFF)V", (void*) SkPathGlue::rQuadTo},
- {"native_cubicTo","(JFFFFFF)V", (void*) SkPathGlue::cubicTo__FFFFFF},
- {"native_rCubicTo","(JFFFFFF)V", (void*) SkPathGlue::rCubicTo},
- {"native_arcTo","(JFFFFFFZ)V", (void*) SkPathGlue::arcTo},
- {"native_close","(J)V", (void*) SkPathGlue::close},
- {"native_addRect","(JFFFFI)V", (void*) SkPathGlue::addRect},
- {"native_addOval","(JFFFFI)V", (void*) SkPathGlue::addOval},
- {"native_addCircle","(JFFFI)V", (void*) SkPathGlue::addCircle},
- {"native_addArc","(JFFFFFF)V", (void*) SkPathGlue::addArc},
- {"native_addRoundRect","(JFFFFFFI)V", (void*) SkPathGlue::addRoundRectXY},
- {"native_addRoundRect","(JFFFF[FI)V", (void*) SkPathGlue::addRoundRect8},
- {"native_addPath","(JJFF)V", (void*) SkPathGlue::addPath__PathFF},
- {"native_addPath","(JJ)V", (void*) SkPathGlue::addPath__Path},
- {"native_addPath","(JJJ)V", (void*) SkPathGlue::addPath__PathMatrix},
- {"native_offset","(JFF)V", (void*) SkPathGlue::offset__FF},
- {"native_setLastPoint","(JFF)V", (void*) SkPathGlue::setLastPoint},
- {"native_transform","(JJJ)V", (void*) SkPathGlue::transform__MatrixPath},
- {"native_transform","(JJ)V", (void*) SkPathGlue::transform__Matrix},
- {"native_op","(JJIJ)Z", (void*) SkPathGlue::op},
- {"native_approximate", "(JF)[F", (void*) SkPathGlue::approximate},
+ {"nInit","()J", (void*) SkPathGlue::init},
+ {"nInit","(J)J", (void*) SkPathGlue::init_Path},
+ {"nFinalize", "(J)V", (void*) SkPathGlue::finalize},
+ {"nSet","(JJ)V", (void*) SkPathGlue::set},
+ {"nComputeBounds","(JLandroid/graphics/RectF;)V", (void*) SkPathGlue::computeBounds},
+ {"nIncReserve","(JI)V", (void*) SkPathGlue::incReserve},
+ {"nMoveTo","(JFF)V", (void*) SkPathGlue::moveTo__FF},
+ {"nRMoveTo","(JFF)V", (void*) SkPathGlue::rMoveTo},
+ {"nLineTo","(JFF)V", (void*) SkPathGlue::lineTo__FF},
+ {"nRLineTo","(JFF)V", (void*) SkPathGlue::rLineTo},
+ {"nQuadTo","(JFFFF)V", (void*) SkPathGlue::quadTo__FFFF},
+ {"nRQuadTo","(JFFFF)V", (void*) SkPathGlue::rQuadTo},
+ {"nCubicTo","(JFFFFFF)V", (void*) SkPathGlue::cubicTo__FFFFFF},
+ {"nRCubicTo","(JFFFFFF)V", (void*) SkPathGlue::rCubicTo},
+ {"nArcTo","(JFFFFFFZ)V", (void*) SkPathGlue::arcTo},
+ {"nClose","(J)V", (void*) SkPathGlue::close},
+ {"nAddRect","(JFFFFI)V", (void*) SkPathGlue::addRect},
+ {"nAddOval","(JFFFFI)V", (void*) SkPathGlue::addOval},
+ {"nAddCircle","(JFFFI)V", (void*) SkPathGlue::addCircle},
+ {"nAddArc","(JFFFFFF)V", (void*) SkPathGlue::addArc},
+ {"nAddRoundRect","(JFFFFFFI)V", (void*) SkPathGlue::addRoundRectXY},
+ {"nAddRoundRect","(JFFFF[FI)V", (void*) SkPathGlue::addRoundRect8},
+ {"nAddPath","(JJFF)V", (void*) SkPathGlue::addPath__PathFF},
+ {"nAddPath","(JJ)V", (void*) SkPathGlue::addPath__Path},
+ {"nAddPath","(JJJ)V", (void*) SkPathGlue::addPath__PathMatrix},
+ {"nOffset","(JFF)V", (void*) SkPathGlue::offset__FF},
+ {"nSetLastPoint","(JFF)V", (void*) SkPathGlue::setLastPoint},
+ {"nTransform","(JJJ)V", (void*) SkPathGlue::transform__MatrixPath},
+ {"nTransform","(JJ)V", (void*) SkPathGlue::transform__Matrix},
+ {"nOp","(JJIJ)Z", (void*) SkPathGlue::op},
+ {"nApproximate", "(JF)[F", (void*) SkPathGlue::approximate},
+
+ // ------- @FastNative below here ----------------------
+ {"nIsRect","(JLandroid/graphics/RectF;)Z", (void*) SkPathGlue::isRect},
+
+ // ------- @CriticalNative below here ------------------
+ {"nReset","(J)V", (void*) SkPathGlue::reset},
+ {"nRewind","(J)V", (void*) SkPathGlue::rewind},
+ {"nIsEmpty","(J)Z", (void*) SkPathGlue::isEmpty},
+ {"nIsConvex","(J)Z", (void*) SkPathGlue::isConvex},
+ {"nGetFillType","(J)I", (void*) SkPathGlue::getFillType},
+ {"nSetFillType","(JI)V", (void*) SkPathGlue::setFillType},
};
int register_android_graphics_Path(JNIEnv* env) {
diff --git a/core/jni/android/graphics/Rasterizer.cpp b/core/jni/android/graphics/Rasterizer.cpp
deleted file mode 100644
index f409498..0000000
--- a/core/jni/android/graphics/Rasterizer.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/* libs/android_runtime/android/graphics/Rasterizer.cpp
-**
-** Copyright 2006, 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.
-*/
-
-// This file was generated from the C++ include file: SkRasterizer.h
-// Any changes made to this file will be discarded by the build.
-// To change this file, either edit the include, or device/tools/gluemaker/main.cpp,
-// or one of the auxilary file specifications in device/tools/gluemaker.
-
-#include "jni.h"
-#include "GraphicsJNI.h"
-#include "SkLayerRasterizer.h"
-#include "core_jni_helpers.h"
-
-#include <hwui/Paint.h>
-
-// Rasterizer.java holds a pointer (jlong) to this guy
-class NativeRasterizer {
-public:
- NativeRasterizer() {}
- virtual ~NativeRasterizer() {}
-
- // Can return NULL, or a ref to the skia rasterizer.
- virtual sk_sp<SkRasterizer> refRasterizer() { return NULL; }
-};
-
-class NativeLayerRasterizer : public NativeRasterizer {
-public:
- SkLayerRasterizer::Builder fBuilder;
-
- virtual sk_sp<SkRasterizer> refRasterizer() {
- return fBuilder.snapshot();
- }
-};
-
-sk_sp<SkRasterizer> GraphicsJNI::refNativeRasterizer(jlong rasterizerHandle) {
- NativeRasterizer* nr = reinterpret_cast<NativeRasterizer*>(rasterizerHandle);
- return nr ? nr->refRasterizer() : NULL;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-namespace android {
-
-class SkRasterizerGlue {
-public:
- static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
- delete reinterpret_cast<NativeRasterizer *>(objHandle);
- }
-};
-
-static const JNINativeMethod gRasterizerMethods[] = {
- {"finalizer", "(J)V", (void*) SkRasterizerGlue::finalizer}
-};
-
-int register_android_graphics_Rasterizer(JNIEnv* env) {
- return RegisterMethodsOrDie(env, "android/graphics/Rasterizer", gRasterizerMethods,
- NELEM(gRasterizerMethods));
-}
-
-class SkLayerRasterizerGlue {
-public:
- static jlong create(JNIEnv* env, jobject) {
- return reinterpret_cast<jlong>(new NativeLayerRasterizer);
- }
-
- static void addLayer(JNIEnv* env, jobject, jlong layerHandle, jlong paintHandle, jfloat dx, jfloat dy) {
- NativeLayerRasterizer* nr = reinterpret_cast<NativeLayerRasterizer *>(layerHandle);
- const Paint* paint = reinterpret_cast<Paint *>(paintHandle);
- SkASSERT(nr);
- SkASSERT(paint);
- nr->fBuilder.addLayer(*paint, dx, dy);
- }
-};
-
-static const JNINativeMethod gLayerRasterizerMethods[] = {
- { "nativeConstructor", "()J", (void*)SkLayerRasterizerGlue::create },
- { "nativeAddLayer", "(JJFF)V", (void*)SkLayerRasterizerGlue::addLayer }
-};
-
-int register_android_graphics_LayerRasterizer(JNIEnv* env)
-{
- return RegisterMethodsOrDie(env, "android/graphics/LayerRasterizer",
- gLayerRasterizerMethods, NELEM(gLayerRasterizerMethods));
-}
-
-}
-
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 04a7543..be9449b 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -183,26 +183,46 @@
return result ? JNI_TRUE : JNI_FALSE;
}
+// SkRegion::Op and SkClipOp are numerically identical, so we can freely cast
+// from one to the other (though SkClipOp is destined to become a strict subset)
+static_assert(SkRegion::kDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kDifference), "");
+static_assert(SkRegion::kIntersect_Op == static_cast<SkRegion::Op>(SkClipOp::kIntersect), "");
+static_assert(SkRegion::kUnion_Op == static_cast<SkRegion::Op>(SkClipOp::kUnion), "");
+static_assert(SkRegion::kXOR_Op == static_cast<SkRegion::Op>(SkClipOp::kXOR), "");
+static_assert(SkRegion::kReverseDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kReverseDifference), "");
+static_assert(SkRegion::kReplace_Op == static_cast<SkRegion::Op>(SkClipOp::kReplace), "");
+
+static SkClipOp opHandleToClipOp(jint opHandle) {
+ // The opHandle is defined in Canvas.java to be Region::Op
+ SkRegion::Op rgnOp = static_cast<SkRegion::Op>(opHandle);
+
+ // In the future, when we no longer support the wide range of ops (e.g. Union, Xor)
+ // this function can perform a range check and throw an unsupported-exception.
+ // e.g. if (rgnOp != kIntersect && rgnOp != kDifference) throw...
+
+ // Skia now takes a different type, SkClipOp, as the parameter to clipping calls
+ // This type is binary compatible with SkRegion::Op, so a static_cast<> is safe.
+ return static_cast<SkClipOp>(rgnOp);
+}
+
static jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t,
jfloat r, jfloat b, jint opHandle) {
- SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
- bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op);
+ bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b,
+ opHandleToClipOp(opHandle));
return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
}
static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
jint opHandle) {
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
- SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
- bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, op);
+ bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, opHandleToClipOp(opHandle));
return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
}
static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle,
jint opHandle) {
SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
- SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
- bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op);
+ bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, opHandleToClipOp(opHandle));
return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
}
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index f4135c2..64c9fe8 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -600,6 +600,9 @@
static void
android_glColorPointerBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -618,17 +621,29 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data ) */
static void
android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -644,20 +659,34 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCompressedTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data ) */
static void
android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -674,9 +703,14 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCopyTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) */
@@ -781,6 +815,12 @@
jint _remaining;
GLuint *textures = (GLuint *) 0;
+ if (!textures_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "textures == null";
+ goto exit;
+ }
textures = (GLuint *)getPointer(_env, textures_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -885,6 +925,12 @@
jint _remaining;
GLvoid *indices = (GLvoid *) 0;
+ if (!indices_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "indices == null";
+ goto exit;
+ }
indices = (GLvoid *)getPointer(_env, indices_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count) {
_exception = 1;
@@ -1026,6 +1072,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1144,6 +1196,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1278,6 +1336,12 @@
jint _remaining;
GLuint *textures = (GLuint *) 0;
+ if (!textures_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "textures == null";
+ goto exit;
+ }
textures = (GLuint *)getPointer(_env, textures_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1424,6 +1488,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1542,6 +1612,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1676,6 +1752,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1825,6 +1907,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1947,11 +2035,20 @@
static void
android_glLoadMatrixf__Ljava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *m = (GLfloat *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfloat *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1960,9 +2057,14 @@
glLoadMatrixf(
(GLfloat *)m
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glLoadMatrixx ( const GLfixed *m ) */
@@ -2011,11 +2113,20 @@
static void
android_glLoadMatrixx__Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *m = (GLfixed *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfixed *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2024,9 +2135,14 @@
glLoadMatrixx(
(GLfixed *)m
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glLogicOp ( GLenum opcode ) */
@@ -2134,6 +2250,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2279,6 +2401,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2383,11 +2511,20 @@
static void
android_glMultMatrixf__Ljava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *m = (GLfloat *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfloat *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2396,9 +2533,14 @@
glMultMatrixf(
(GLfloat *)m
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMultMatrixx ( const GLfixed *m ) */
@@ -2447,11 +2589,20 @@
static void
android_glMultMatrixx__Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *m = (GLfixed *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfixed *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2460,9 +2611,14 @@
glMultMatrixx(
(GLfixed *)m
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMultiTexCoord4f ( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q ) */
@@ -2517,6 +2673,9 @@
static void
android_glNormalPointerBounds__IILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -2534,6 +2693,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glOrthof ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) */
@@ -2630,11 +2792,20 @@
static void
android_glReadPixels__IIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *pixels = (GLvoid *) 0;
+ if (!pixels_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "pixels == null";
+ goto exit;
+ }
pixels = (GLvoid *)getPointer(_env, pixels_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (pixels == NULL) {
char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -2649,8 +2820,13 @@
(GLenum)type,
(GLvoid *)pixels
);
+
+exit:
if (_array) {
- releasePointer(_env, _array, pixels, JNI_TRUE);
+ releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -2776,6 +2952,9 @@
static void
android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -2794,6 +2973,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexEnvf ( GLenum target, GLenum pname, GLfloat param ) */
@@ -2880,6 +3062,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -3001,6 +3189,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -3042,6 +3236,9 @@
static void
android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3068,6 +3265,9 @@
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexParameterf ( GLenum target, GLenum pname, GLfloat param ) */
@@ -3096,6 +3296,9 @@
static void
android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3122,6 +3325,9 @@
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTranslatef ( GLfloat x, GLfloat y, GLfloat z ) */
@@ -3150,6 +3356,9 @@
static void
android_glVertexPointerBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3168,6 +3377,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glViewport ( GLint x, GLint y, GLsizei width, GLsizei height ) */
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
index 4dc4233..533bda4 100644
--- a/core/jni/android_opengl_GLES10Ext.cpp
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -540,6 +540,12 @@
jint _exponentRemaining;
GLint *exponent = (GLint *) 0;
+ if (!mantissa_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "mantissa == null";
+ goto exit;
+ }
mantissa = (GLfixed *)getPointer(_env, mantissa_buf, (jarray*)&_mantissaArray, &_mantissaRemaining, &_mantissaBufferOffset);
if (_mantissaRemaining < 16) {
_exception = 1;
@@ -547,6 +553,12 @@
_exceptionMessage = "remaining() < 16 < needed";
goto exit;
}
+ if (!exponent_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "exponent == null";
+ goto exit;
+ }
exponent = (GLint *)getPointer(_env, exponent_buf, (jarray*)&_exponentArray, &_exponentRemaining, &_exponentBufferOffset);
if (_exponentRemaining < 16) {
_exception = 1;
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index 2625e03..923f7a8 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -505,6 +505,12 @@
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < size) {
_exception = 1;
@@ -587,6 +593,12 @@
jint _remaining;
GLfloat *equation = (GLfloat *) 0;
+ if (!equation_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "equation == null";
+ goto exit;
+ }
equation = (GLfloat *)getPointer(_env, equation_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (equation == NULL) {
char * _equationBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -596,6 +608,8 @@
(GLenum)plane,
(GLfloat *)equation
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)equation, JNI_ABORT);
}
@@ -659,6 +673,12 @@
jint _remaining;
GLfixed *equation = (GLfixed *) 0;
+ if (!equation_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "equation == null";
+ goto exit;
+ }
equation = (GLfixed *)getPointer(_env, equation_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (equation == NULL) {
char * _equationBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -668,6 +688,8 @@
(GLenum)plane,
(GLfixed *)equation
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)equation, JNI_ABORT);
}
@@ -761,6 +783,12 @@
jint _remaining;
GLuint *buffers = (GLuint *) 0;
+ if (!buffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "buffers == null";
+ goto exit;
+ }
buffers = (GLuint *)getPointer(_env, buffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -865,6 +893,12 @@
jint _remaining;
GLuint *buffers = (GLuint *) 0;
+ if (!buffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "buffers == null";
+ goto exit;
+ }
buffers = (GLuint *)getPointer(_env, buffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -967,6 +1001,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -1054,6 +1094,12 @@
jint _remaining;
GLfloat *eqn = (GLfloat *) 0;
+ if (!eqn_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "eqn == null";
+ goto exit;
+ }
eqn = (GLfloat *)getPointer(_env, eqn_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 4) {
_exception = 1;
@@ -1140,6 +1186,12 @@
jint _remaining;
GLfixed *eqn = (GLfixed *) 0;
+ if (!eqn_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "eqn == null";
+ goto exit;
+ }
eqn = (GLfixed *)getPointer(_env, eqn_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 4) {
_exception = 1;
@@ -1212,11 +1264,20 @@
static void
android_glGetFixedv__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1226,8 +1287,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1333,6 +1399,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1471,6 +1543,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1607,6 +1685,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1741,6 +1825,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1863,6 +1953,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1973,6 +2069,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2083,6 +2185,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2182,6 +2290,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2270,6 +2384,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2358,6 +2478,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2499,6 +2625,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2595,6 +2727,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2624,6 +2762,9 @@
static void
android_glPointSizePointerOESBounds__IILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -2641,6 +2782,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexCoordPointer ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
@@ -2739,6 +2883,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2838,6 +2988,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2937,6 +3093,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -3025,6 +3187,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index fb85cb0..f7498d5 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -572,6 +572,12 @@
jint _remaining;
GLshort *coords = (GLshort *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLshort *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -656,6 +662,12 @@
jint _remaining;
GLint *coords = (GLint *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLint *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -740,6 +752,12 @@
jint _remaining;
GLfixed *coords = (GLfixed *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLfixed *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -837,6 +855,12 @@
jint _remaining;
GLfloat *coords = (GLfloat *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLfloat *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -865,11 +889,20 @@
static void
android_glEGLImageTargetTexture2DOES__ILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jobject image_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLeglImageOES image = (GLeglImageOES) 0;
+ if (!image_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "image == null";
+ goto exit;
+ }
image = (GLeglImageOES)getPointer(_env, image_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (image == NULL) {
char * _imageBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -879,8 +912,13 @@
(GLenum)target,
(GLeglImageOES)image
);
+
+exit:
if (_array) {
- releasePointer(_env, _array, image, JNI_TRUE);
+ releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -888,11 +926,20 @@
static void
android_glEGLImageTargetRenderbufferStorageOES__ILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jobject image_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLeglImageOES image = (GLeglImageOES) 0;
+ if (!image_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "image == null";
+ goto exit;
+ }
image = (GLeglImageOES)getPointer(_env, image_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (image == NULL) {
char * _imageBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -902,8 +949,13 @@
(GLenum)target,
(GLeglImageOES)image
);
+
+exit:
if (_array) {
- releasePointer(_env, _array, image, JNI_TRUE);
+ releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -985,11 +1037,20 @@
static void
android_glClipPlanexOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *equation = (GLfixed *) 0;
+ if (!equation_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "equation == null";
+ goto exit;
+ }
equation = (GLfixed *)getPointer(_env, equation_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (equation == NULL) {
char * _equationBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -999,9 +1060,14 @@
(GLenum)plane,
(GLfixed *)equation
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)equation, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glColor4xOES ( GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha ) */
@@ -1083,11 +1149,20 @@
static void
android_glFogxvOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1097,9 +1172,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glFrustumxOES ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar ) */
@@ -1177,6 +1257,12 @@
jint _remaining;
GLfixed *eqn = (GLfixed *) 0;
+ if (!eqn_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "eqn == null";
+ goto exit;
+ }
eqn = (GLfixed *)getPointer(_env, eqn_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 4) {
_exception = 1;
@@ -1249,11 +1335,20 @@
static void
android_glGetFixedvOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1263,8 +1358,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1316,11 +1416,20 @@
static void
android_glGetLightxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1331,8 +1440,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1384,11 +1498,20 @@
static void
android_glGetMaterialxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1399,8 +1522,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1452,11 +1580,20 @@
static void
android_glGetTexEnvxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1467,8 +1604,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1520,11 +1662,20 @@
static void
android_glGetTexParameterxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1535,8 +1686,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1597,11 +1753,20 @@
static void
android_glLightModelxvOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1611,9 +1776,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glLightxOES ( GLenum light, GLenum pname, GLfixed param ) */
@@ -1675,11 +1845,20 @@
static void
android_glLightxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1690,9 +1869,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glLineWidthxOES ( GLfixed width ) */
@@ -1750,11 +1934,20 @@
static void
android_glLoadMatrixxOES__Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *m = (GLfixed *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfixed *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1763,9 +1956,14 @@
glLoadMatrixxOES(
(GLfixed *)m
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMaterialxOES ( GLenum face, GLenum pname, GLfixed param ) */
@@ -1827,11 +2025,20 @@
static void
android_glMaterialxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1842,9 +2049,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMultMatrixxOES ( const GLfixed *m ) */
@@ -1893,11 +2105,20 @@
static void
android_glMultMatrixxOES__Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *m = (GLfixed *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfixed *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1906,9 +2127,14 @@
glMultMatrixxOES(
(GLfixed *)m
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMultiTexCoord4xOES ( GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q ) */
@@ -2006,11 +2232,20 @@
static void
android_glPointParameterxvOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2020,9 +2255,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glPointSizexOES ( GLfixed size ) */
@@ -2136,11 +2376,20 @@
static void
android_glTexEnvxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2151,9 +2400,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexParameterxOES ( GLenum target, GLenum pname, GLfixed param ) */
@@ -2215,11 +2469,20 @@
static void
android_glTexParameterxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2230,9 +2493,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTranslatexOES ( GLfixed x, GLfixed y, GLfixed z ) */
@@ -2328,6 +2596,12 @@
jint _remaining;
GLuint *renderbuffers = (GLuint *) 0;
+ if (!renderbuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "renderbuffers == null";
+ goto exit;
+ }
renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -2414,6 +2688,12 @@
jint _remaining;
GLuint *renderbuffers = (GLuint *) 0;
+ if (!renderbuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "renderbuffers == null";
+ goto exit;
+ }
renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -2513,6 +2793,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2621,6 +2907,12 @@
jint _remaining;
GLuint *framebuffers = (GLuint *) 0;
+ if (!framebuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "framebuffers == null";
+ goto exit;
+ }
framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -2707,6 +2999,12 @@
jint _remaining;
GLuint *framebuffers = (GLuint *) 0;
+ if (!framebuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "framebuffers == null";
+ goto exit;
+ }
framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -2831,6 +3129,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2887,6 +3191,9 @@
static void
android_glMatrixIndexPointerOESBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -2905,12 +3212,18 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glWeightPointerOES ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) */
static void
android_glWeightPointerOESBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -2929,6 +3242,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glDepthRangefOES ( GLclampf zNear, GLclampf zFar ) */
@@ -3016,11 +3332,20 @@
static void
android_glClipPlanefOES__ILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *equation = (GLfloat *) 0;
+ if (!equation_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "equation == null";
+ goto exit;
+ }
equation = (GLfloat *)getPointer(_env, equation_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (equation == NULL) {
char * _equationBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -3030,9 +3355,14 @@
(GLenum)plane,
(GLfloat *)equation
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)equation, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetClipPlanefOES ( GLenum pname, GLfloat *eqn ) */
@@ -3096,6 +3426,12 @@
jint _remaining;
GLfloat *eqn = (GLfloat *) 0;
+ if (!eqn_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "eqn == null";
+ goto exit;
+ }
eqn = (GLfloat *)getPointer(_env, eqn_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 4) {
_exception = 1;
@@ -3189,11 +3525,20 @@
static void
android_glTexGenfvOES__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -3204,9 +3549,14 @@
(GLenum)pname,
(GLfloat *)params
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexGeniOES ( GLenum coord, GLenum pname, GLint param ) */
@@ -3268,11 +3618,20 @@
static void
android_glTexGenivOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3283,9 +3642,14 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexGenxOES ( GLenum coord, GLenum pname, GLfixed param ) */
@@ -3347,11 +3711,20 @@
static void
android_glTexGenxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3362,9 +3735,14 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetTexGenfvOES ( GLenum coord, GLenum pname, GLfloat *params ) */
@@ -3415,11 +3793,20 @@
static void
android_glGetTexGenfvOES__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -3430,8 +3817,13 @@
(GLenum)pname,
(GLfloat *)params
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)params, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3483,11 +3875,20 @@
static void
android_glGetTexGenivOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3498,8 +3899,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3551,11 +3957,20 @@
static void
android_glGetTexGenxvOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3566,8 +3981,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index b5c0b64..791233b 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -640,6 +640,12 @@
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < size) {
_exception = 1;
@@ -742,11 +748,20 @@
static void
android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -762,20 +777,34 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCompressedTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data ) */
static void
android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -792,9 +821,14 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCopyTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) */
@@ -919,6 +953,12 @@
jint _remaining;
GLuint *buffers = (GLuint *) 0;
+ if (!buffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "buffers == null";
+ goto exit;
+ }
buffers = (GLuint *)getPointer(_env, buffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1005,6 +1045,12 @@
jint _remaining;
GLuint *framebuffers = (GLuint *) 0;
+ if (!framebuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "framebuffers == null";
+ goto exit;
+ }
framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1100,6 +1146,12 @@
jint _remaining;
GLuint *renderbuffers = (GLuint *) 0;
+ if (!renderbuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "renderbuffers == null";
+ goto exit;
+ }
renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1195,6 +1247,12 @@
jint _remaining;
GLuint *textures = (GLuint *) 0;
+ if (!textures_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "textures == null";
+ goto exit;
+ }
textures = (GLuint *)getPointer(_env, textures_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1317,6 +1375,12 @@
jint _remaining;
GLvoid *indices = (GLvoid *) 0;
+ if (!indices_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "indices == null";
+ goto exit;
+ }
indices = (GLvoid *)getPointer(_env, indices_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count) {
_exception = 1;
@@ -1471,6 +1535,12 @@
jint _remaining;
GLuint *buffers = (GLuint *) 0;
+ if (!buffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "buffers == null";
+ goto exit;
+ }
buffers = (GLuint *)getPointer(_env, buffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1566,6 +1636,12 @@
jint _remaining;
GLuint *framebuffers = (GLuint *) 0;
+ if (!framebuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "framebuffers == null";
+ goto exit;
+ }
framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1652,6 +1728,12 @@
jint _remaining;
GLuint *renderbuffers = (GLuint *) 0;
+ if (!renderbuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "renderbuffers == null";
+ goto exit;
+ }
renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1738,6 +1820,12 @@
jint _remaining;
GLuint *textures = (GLuint *) 0;
+ if (!textures_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "textures == null";
+ goto exit;
+ }
textures = (GLuint *)getPointer(_env, textures_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -2514,6 +2602,12 @@
goto exit;
}
}
+ if (!shaders_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "shaders == null";
+ goto exit;
+ }
shaders = (GLuint *)getPointer(_env, shaders_buf, (jarray*)&_shadersArray, &_shadersRemaining, &_shadersBufferOffset);
if (_shadersRemaining < maxcount) {
_exception = 1;
@@ -2659,6 +2753,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2758,11 +2858,20 @@
static void
android_glGetFramebufferAttachmentParameteriv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2774,8 +2883,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -2856,6 +2970,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -2963,6 +3083,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -3051,6 +3177,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -3194,6 +3326,12 @@
jint _precisionRemaining;
GLint *precision = (GLint *) 0;
+ if (!range_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "range == null";
+ goto exit;
+ }
range = (GLint *)getPointer(_env, range_buf, (jarray*)&_rangeArray, &_rangeRemaining, &_rangeBufferOffset);
if (_rangeRemaining < 1) {
_exception = 1;
@@ -3201,6 +3339,12 @@
_exceptionMessage = "remaining() < 1 < needed";
goto exit;
}
+ if (!precision_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "precision == null";
+ goto exit;
+ }
precision = (GLint *)getPointer(_env, precision_buf, (jarray*)&_precisionArray, &_precisionRemaining, &_precisionBufferOffset);
if (_precisionRemaining < 1) {
_exception = 1;
@@ -3409,6 +3553,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -3497,6 +3647,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -3585,6 +3741,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -3673,6 +3835,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -3806,6 +3974,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -3916,6 +4090,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -4082,11 +4262,20 @@
static void
android_glReadPixels__IIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *pixels = (GLvoid *) 0;
+ if (!pixels_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "pixels == null";
+ goto exit;
+ }
pixels = (GLvoid *)getPointer(_env, pixels_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (pixels == NULL) {
char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -4101,8 +4290,13 @@
(GLenum)type,
(GLvoid *)pixels
);
+
+exit:
if (_array) {
- releasePointer(_env, _array, pixels, JNI_TRUE);
+ releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4179,6 +4373,12 @@
_env->GetIntArrayElements(shaders_ref, (jboolean *)0);
shaders = shaders_base + offset;
+ if (!binary_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "binary == null";
+ goto exit;
+ }
binary = (GLvoid *)getPointer(_env, binary_buf, (jarray*)&_array, &_binaryRemaining, &_bufferOffset);
if (_binaryRemaining < length) {
_exception = 1;
@@ -4227,7 +4427,19 @@
jint _binaryRemaining;
GLvoid *binary = (GLvoid *) 0;
+ if (!shaders_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "shaders == null";
+ goto exit;
+ }
shaders = (GLuint *)getPointer(_env, shaders_buf, (jarray*)&_shadersArray, &_shadersRemaining, &_shadersBufferOffset);
+ if (!binary_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "binary == null";
+ goto exit;
+ }
binary = (GLvoid *)getPointer(_env, binary_buf, (jarray*)&_binaryArray, &_binaryRemaining, &_binaryBufferOffset);
if (_binaryRemaining < length) {
_exception = 1;
@@ -4349,6 +4561,9 @@
static void
android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -4375,6 +4590,9 @@
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexParameterf ( GLenum target, GLenum pname, GLfloat param ) */
@@ -4450,6 +4668,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -4549,6 +4773,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -4579,6 +4809,9 @@
static void
android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -4605,6 +4838,9 @@
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniform1f ( GLint location, GLfloat x ) */
@@ -4679,6 +4915,12 @@
jint _remaining;
GLfloat *v = (GLfloat *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLfloat *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count) {
_exception = 1;
@@ -4777,6 +5019,12 @@
jint _remaining;
GLint *v = (GLint *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLint *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count) {
_exception = 1;
@@ -4876,6 +5124,12 @@
jint _remaining;
GLfloat *v = (GLfloat *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLfloat *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*2) {
_exception = 1;
@@ -4975,6 +5229,12 @@
jint _remaining;
GLint *v = (GLint *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLint *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*2) {
_exception = 1;
@@ -5075,6 +5335,12 @@
jint _remaining;
GLfloat *v = (GLfloat *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLfloat *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*3) {
_exception = 1;
@@ -5175,6 +5441,12 @@
jint _remaining;
GLint *v = (GLint *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLint *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*3) {
_exception = 1;
@@ -5276,6 +5548,12 @@
jint _remaining;
GLfloat *v = (GLfloat *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLfloat *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*4) {
_exception = 1;
@@ -5377,6 +5655,12 @@
jint _remaining;
GLint *v = (GLint *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLint *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*4) {
_exception = 1;
@@ -5466,6 +5750,12 @@
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*4) {
_exception = 1;
@@ -5556,6 +5846,12 @@
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*9) {
_exception = 1;
@@ -5646,6 +5942,12 @@
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count*16) {
_exception = 1;
@@ -5762,6 +6064,12 @@
jint _remaining;
GLfloat *values = (GLfloat *) 0;
+ if (!values_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "values == null";
+ goto exit;
+ }
values = (GLfloat *)getPointer(_env, values_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -5859,6 +6167,12 @@
jint _remaining;
GLfloat *values = (GLfloat *) 0;
+ if (!values_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "values == null";
+ goto exit;
+ }
values = (GLfloat *)getPointer(_env, values_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 2) {
_exception = 1;
@@ -5957,6 +6271,12 @@
jint _remaining;
GLfloat *values = (GLfloat *) 0;
+ if (!values_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "values == null";
+ goto exit;
+ }
values = (GLfloat *)getPointer(_env, values_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 3) {
_exception = 1;
@@ -6056,6 +6376,12 @@
jint _remaining;
GLfloat *values = (GLfloat *) 0;
+ if (!values_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "values == null";
+ goto exit;
+ }
values = (GLfloat *)getPointer(_env, values_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 4) {
_exception = 1;
@@ -6099,6 +6425,9 @@
static void
android_glVertexAttribPointerBounds__IIIZILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint indx, jint size, jint type, jboolean normalized, jint stride, jobject ptr_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -6119,6 +6448,9 @@
(GLvoid *)ptr,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glViewport ( GLint x, GLint y, GLsizei width, GLsizei height ) */
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 59b8911..736fd99 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -455,11 +455,20 @@
static void
android_glDrawRangeElements__IIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint mode, jint start, jint end, jint count, jint type, jobject indices_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *indices = (GLvoid *) 0;
+ if (!indices_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "indices == null";
+ goto exit;
+ }
indices = (GLvoid *)getPointer(_env, indices_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (indices == NULL) {
char * _indicesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -473,9 +482,14 @@
(GLenum)type,
(GLvoid *)indices
);
+
+exit:
if (_array) {
releasePointer(_env, _array, indices, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glDrawRangeElements ( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, GLsizei offset ) */
@@ -496,6 +510,9 @@
static void
android_glTexImage3D__IIIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint depth, jint border, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -523,6 +540,9 @@
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexImage3D ( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLsizei offset ) */
@@ -547,11 +567,20 @@
static void
android_glTexSubImage3D__IIIIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint zoffset, jint width, jint height, jint depth, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *pixels = (GLvoid *) 0;
+ if (!pixels_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "pixels == null";
+ goto exit;
+ }
pixels = (GLvoid *)getPointer(_env, pixels_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (pixels == NULL) {
char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -570,9 +599,14 @@
(GLenum)type,
(GLvoid *)pixels
);
+
+exit:
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexSubImage3D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei offset ) */
@@ -615,11 +649,20 @@
static void
android_glCompressedTexImage3D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint depth, jint border, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -636,9 +679,14 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCompressedTexImage3D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, GLsizei offset ) */
@@ -662,11 +710,20 @@
static void
android_glCompressedTexSubImage3D__IIIIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint zoffset, jint width, jint height, jint depth, jint format, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -685,9 +742,14 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCompressedTexSubImage3D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, GLsizei offset ) */
@@ -756,11 +818,20 @@
static void
android_glGenQueries__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject ids_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *ids = (GLuint *) 0;
+ if (!ids_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "ids == null";
+ goto exit;
+ }
ids = (GLuint *)getPointer(_env, ids_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (ids == NULL) {
char * _idsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -770,8 +841,13 @@
(GLsizei)n,
(GLuint *)ids
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)ids, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)ids, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -822,11 +898,20 @@
static void
android_glDeleteQueries__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject ids_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *ids = (GLuint *) 0;
+ if (!ids_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "ids == null";
+ goto exit;
+ }
ids = (GLuint *)getPointer(_env, ids_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (ids == NULL) {
char * _idsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -836,9 +921,14 @@
(GLsizei)n,
(GLuint *)ids
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)ids, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* GLboolean glIsQuery ( GLuint id ) */
@@ -919,11 +1009,20 @@
static void
android_glGetQueryiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -934,8 +1033,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -987,11 +1091,20 @@
static void
android_glGetQueryObjectuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint id, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1002,8 +1115,13 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1076,11 +1194,20 @@
static void
android_glDrawBuffers__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject bufs_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLenum *bufs = (GLenum *) 0;
+ if (!bufs_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "bufs == null";
+ goto exit;
+ }
bufs = (GLenum *)getPointer(_env, bufs_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (bufs == NULL) {
char * _bufsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1090,9 +1217,14 @@
(GLsizei)n,
(GLenum *)bufs
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)bufs, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniformMatrix2x3fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -1144,11 +1276,20 @@
static void
android_glUniformMatrix2x3fv__IIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1160,9 +1301,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniformMatrix3x2fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -1214,11 +1360,20 @@
static void
android_glUniformMatrix3x2fv__IIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1230,9 +1385,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniformMatrix2x4fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -1284,11 +1444,20 @@
static void
android_glUniformMatrix2x4fv__IIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1300,9 +1469,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniformMatrix4x2fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -1354,11 +1528,20 @@
static void
android_glUniformMatrix4x2fv__IIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1370,9 +1553,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniformMatrix3x4fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -1424,11 +1612,20 @@
static void
android_glUniformMatrix3x4fv__IIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1440,9 +1637,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniformMatrix4x3fv ( GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -1494,11 +1696,20 @@
static void
android_glUniformMatrix4x3fv__IIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1510,9 +1721,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glBlitFramebuffer ( GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter ) */
@@ -1639,11 +1855,20 @@
static void
android_glDeleteVertexArrays__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject arrays_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *arrays = (GLuint *) 0;
+ if (!arrays_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "arrays == null";
+ goto exit;
+ }
arrays = (GLuint *)getPointer(_env, arrays_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (arrays == NULL) {
char * _arraysBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1653,9 +1878,14 @@
(GLsizei)n,
(GLuint *)arrays
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)arrays, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGenVertexArrays ( GLsizei n, GLuint *arrays ) */
@@ -1705,11 +1935,20 @@
static void
android_glGenVertexArrays__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject arrays_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *arrays = (GLuint *) 0;
+ if (!arrays_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "arrays == null";
+ goto exit;
+ }
arrays = (GLuint *)getPointer(_env, arrays_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (arrays == NULL) {
char * _arraysBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1719,8 +1958,13 @@
(GLsizei)n,
(GLuint *)arrays
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)arrays, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)arrays, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1783,11 +2027,20 @@
static void
android_glGetIntegeri_v__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint index, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *data = (GLint *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLint *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1798,8 +2051,13 @@
(GLuint)index,
(GLint *)data
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)data, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)data, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -2240,6 +2498,9 @@
static void
android_glVertexAttribIPointerBounds__IIIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint index, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -2259,6 +2520,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glVertexAttribIPointer ( GLuint index, GLint size, GLenum type, GLsizei stride, GLsizei offset ) */
@@ -2322,11 +2586,20 @@
static void
android_glGetVertexAttribIiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint index, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2337,8 +2610,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -2390,11 +2668,20 @@
static void
android_glGetVertexAttribIuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint index, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2405,8 +2692,13 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -2483,11 +2775,20 @@
static void
android_glVertexAttribI4iv__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint index, jobject v_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *v = (GLint *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLint *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (v == NULL) {
char * _vBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2497,9 +2798,14 @@
(GLuint)index,
(GLint *)v
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)v, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glVertexAttribI4uiv ( GLuint index, const GLuint *v ) */
@@ -2549,11 +2855,20 @@
static void
android_glVertexAttribI4uiv__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint index, jobject v_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *v = (GLuint *) 0;
+ if (!v_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "v == null";
+ goto exit;
+ }
v = (GLuint *)getPointer(_env, v_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (v == NULL) {
char * _vBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2563,9 +2878,14 @@
(GLuint)index,
(GLuint *)v
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)v, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetUniformuiv ( GLuint program, GLint location, GLuint *params ) */
@@ -2616,11 +2936,20 @@
static void
android_glGetUniformuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2631,8 +2960,13 @@
(GLint)location,
(GLuint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -2764,11 +3098,20 @@
static void
android_glUniform1uiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2779,9 +3122,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniform2uiv ( GLint location, GLsizei count, const GLuint *value ) */
@@ -2832,11 +3180,20 @@
static void
android_glUniform2uiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2847,9 +3204,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniform3uiv ( GLint location, GLsizei count, const GLuint *value ) */
@@ -2900,11 +3262,20 @@
static void
android_glUniform3uiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2915,9 +3286,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glUniform4uiv ( GLint location, GLsizei count, const GLuint *value ) */
@@ -2968,11 +3344,20 @@
static void
android_glUniform4uiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2983,9 +3368,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glClearBufferiv ( GLenum buffer, GLint drawbuffer, const GLint *value ) */
@@ -3036,11 +3426,20 @@
static void
android_glClearBufferiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint buffer, jint drawbuffer, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *value = (GLint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3051,9 +3450,14 @@
(GLint)drawbuffer,
(GLint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glClearBufferuiv ( GLenum buffer, GLint drawbuffer, const GLuint *value ) */
@@ -3104,11 +3508,20 @@
static void
android_glClearBufferuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint buffer, jint drawbuffer, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3119,9 +3532,14 @@
(GLint)drawbuffer,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glClearBufferfv ( GLenum buffer, GLint drawbuffer, const GLfloat *value ) */
@@ -3172,11 +3590,20 @@
static void
android_glClearBufferfv__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint buffer, jint drawbuffer, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -3187,9 +3614,14 @@
(GLint)drawbuffer,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glClearBufferfi ( GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil ) */
@@ -3453,6 +3885,9 @@
static void
android_glGetActiveUniformsiv__IILjava_nio_IntBuffer_2ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint uniformCount, jobject uniformIndices_buf, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _uniformIndicesArray = (jintArray) 0;
jint _uniformIndicesBufferOffset = (jint) 0;
jintArray _paramsArray = (jintArray) 0;
@@ -3462,7 +3897,19 @@
jint _paramsRemaining;
GLint *params = (GLint *) 0;
+ if (!uniformIndices_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "uniformIndices == null";
+ goto exit;
+ }
uniformIndices = (GLuint *)getPointer(_env, uniformIndices_buf, (jarray*)&_uniformIndicesArray, &_uniformIndicesRemaining, &_uniformIndicesBufferOffset);
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_paramsArray, &_paramsRemaining, &_paramsBufferOffset);
if (uniformIndices == NULL) {
char * _uniformIndicesBase = (char *)_env->GetIntArrayElements(_uniformIndicesArray, (jboolean *) 0);
@@ -3479,12 +3926,17 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_paramsArray) {
- _env->ReleaseIntArrayElements(_paramsArray, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_paramsArray, (jint*)params, _exception ? JNI_ABORT : 0);
}
if (_uniformIndicesArray) {
_env->ReleaseIntArrayElements(_uniformIndicesArray, (jint*)uniformIndices, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* GLuint glGetUniformBlockIndex ( GLuint program, const GLchar *uniformBlockName ) */
@@ -3570,11 +4022,20 @@
static void
android_glGetActiveUniformBlockiv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint uniformBlockIndex, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3586,8 +4047,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3877,11 +4343,20 @@
static void
android_glGetInteger64v__ILjava_nio_LongBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jlongArray _array = (jlongArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint64 *params = (GLint64 *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint64 *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetLongArrayElements(_array, (jboolean *) 0);
@@ -3891,8 +4366,13 @@
(GLenum)pname,
(GLint64 *)params
);
+
+exit:
if (_array) {
- _env->ReleaseLongArrayElements(_array, (jlong*)params, 0);
+ _env->ReleaseLongArrayElements(_array, (jlong*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3966,6 +4446,9 @@
static void
android_glGetSynciv__JIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jlong sync, jint pname, jint bufSize, jobject length_buf, jobject values_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _lengthArray = (jintArray) 0;
jint _lengthBufferOffset = (jint) 0;
jintArray _valuesArray = (jintArray) 0;
@@ -3978,6 +4461,12 @@
if (length_buf) {
length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
}
+ if (!values_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "values == null";
+ goto exit;
+ }
values = (GLint *)getPointer(_env, values_buf, (jarray*)&_valuesArray, &_valuesRemaining, &_valuesBufferOffset);
if (length_buf && length == NULL) {
char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
@@ -3994,11 +4483,16 @@
(GLsizei *)length,
(GLint *)values
);
+
+exit:
if (_valuesArray) {
- _env->ReleaseIntArrayElements(_valuesArray, (jint*)values, 0);
+ _env->ReleaseIntArrayElements(_valuesArray, (jint*)values, _exception ? JNI_ABORT : 0);
}
if (_lengthArray) {
- _env->ReleaseIntArrayElements(_lengthArray, (jint*)length, 0);
+ _env->ReleaseIntArrayElements(_lengthArray, (jint*)length, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4050,11 +4544,20 @@
static void
android_glGetInteger64i_v__IILjava_nio_LongBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint index, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jlongArray _array = (jlongArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint64 *data = (GLint64 *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLint64 *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetLongArrayElements(_array, (jboolean *) 0);
@@ -4065,8 +4568,13 @@
(GLuint)index,
(GLint64 *)data
);
+
+exit:
if (_array) {
- _env->ReleaseLongArrayElements(_array, (jlong*)data, 0);
+ _env->ReleaseLongArrayElements(_array, (jlong*)data, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4118,11 +4626,20 @@
static void
android_glGetBufferParameteri64v__IILjava_nio_LongBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jlongArray _array = (jlongArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint64 *params = (GLint64 *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint64 *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetLongArrayElements(_array, (jboolean *) 0);
@@ -4133,8 +4650,13 @@
(GLenum)pname,
(GLint64 *)params
);
+
+exit:
if (_array) {
- _env->ReleaseLongArrayElements(_array, (jlong*)params, 0);
+ _env->ReleaseLongArrayElements(_array, (jlong*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4185,11 +4707,20 @@
static void
android_glGenSamplers__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint count, jobject samplers_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *samplers = (GLuint *) 0;
+ if (!samplers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "samplers == null";
+ goto exit;
+ }
samplers = (GLuint *)getPointer(_env, samplers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (samplers == NULL) {
char * _samplersBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4199,8 +4730,13 @@
(GLsizei)count,
(GLuint *)samplers
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)samplers, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)samplers, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4251,11 +4787,20 @@
static void
android_glDeleteSamplers__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint count, jobject samplers_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *samplers = (GLuint *) 0;
+ if (!samplers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "samplers == null";
+ goto exit;
+ }
samplers = (GLuint *)getPointer(_env, samplers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (samplers == NULL) {
char * _samplersBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4265,9 +4810,14 @@
(GLsizei)count,
(GLuint *)samplers
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)samplers, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* GLboolean glIsSampler ( GLuint sampler ) */
@@ -4350,11 +4900,20 @@
static void
android_glSamplerParameteriv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject param_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *param = (GLint *) 0;
+ if (!param_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "param == null";
+ goto exit;
+ }
param = (GLint *)getPointer(_env, param_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (param == NULL) {
char * _paramBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4365,9 +4924,14 @@
(GLenum)pname,
(GLint *)param
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)param, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glSamplerParameterf ( GLuint sampler, GLenum pname, GLfloat param ) */
@@ -4429,11 +4993,20 @@
static void
android_glSamplerParameterfv__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject param_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *param = (GLfloat *) 0;
+ if (!param_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "param == null";
+ goto exit;
+ }
param = (GLfloat *)getPointer(_env, param_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (param == NULL) {
char * _paramBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -4444,9 +5017,14 @@
(GLenum)pname,
(GLfloat *)param
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)param, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetSamplerParameteriv ( GLuint sampler, GLenum pname, GLint *params ) */
@@ -4497,11 +5075,20 @@
static void
android_glGetSamplerParameteriv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4512,8 +5099,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4565,11 +5157,20 @@
static void
android_glGetSamplerParameterfv__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -4580,8 +5181,13 @@
(GLenum)pname,
(GLfloat *)params
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)params, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4652,11 +5258,20 @@
static void
android_glDeleteTransformFeedbacks__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject ids_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *ids = (GLuint *) 0;
+ if (!ids_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "ids == null";
+ goto exit;
+ }
ids = (GLuint *)getPointer(_env, ids_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (ids == NULL) {
char * _idsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4666,9 +5281,14 @@
(GLsizei)n,
(GLuint *)ids
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)ids, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGenTransformFeedbacks ( GLsizei n, GLuint *ids ) */
@@ -4718,11 +5338,20 @@
static void
android_glGenTransformFeedbacks__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject ids_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *ids = (GLuint *) 0;
+ if (!ids_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "ids == null";
+ goto exit;
+ }
ids = (GLuint *)getPointer(_env, ids_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (ids == NULL) {
char * _idsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4732,8 +5361,13 @@
(GLsizei)n,
(GLuint *)ids
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)ids, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)ids, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4810,6 +5444,12 @@
_env->GetIntArrayElements(binaryFormat_ref, (jboolean *)0);
binaryFormat = binaryFormat_base + binaryFormatOffset;
+ if (!binary_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "binary == null";
+ goto exit;
+ }
binary = (GLvoid *)getPointer(_env, binary_buf, (jarray*)&_array, &_binaryRemaining, &_bufferOffset);
if (binary == NULL) {
char * _binaryBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -4844,6 +5484,9 @@
static void
android_glGetProgramBinary__IILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint program, jint bufSize, jobject length_buf, jobject binaryFormat_buf, jobject binary_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _lengthArray = (jintArray) 0;
jint _lengthBufferOffset = (jint) 0;
jintArray _binaryFormatArray = (jintArray) 0;
@@ -4860,7 +5503,19 @@
if (length_buf) {
length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
}
+ if (!binaryFormat_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "binaryFormat == null";
+ goto exit;
+ }
binaryFormat = (GLenum *)getPointer(_env, binaryFormat_buf, (jarray*)&_binaryFormatArray, &_binaryFormatRemaining, &_binaryFormatBufferOffset);
+ if (!binary_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "binary == null";
+ goto exit;
+ }
binary = (GLvoid *)getPointer(_env, binary_buf, (jarray*)&_binaryArray, &_binaryRemaining, &_binaryBufferOffset);
if (length_buf && length == NULL) {
char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
@@ -4881,14 +5536,19 @@
(GLenum *)binaryFormat,
(GLvoid *)binary
);
+
+exit:
if (_binaryArray) {
- releasePointer(_env, _binaryArray, binary, JNI_TRUE);
+ releasePointer(_env, _binaryArray, binary, _exception ? JNI_FALSE : JNI_TRUE);
}
if (_binaryFormatArray) {
- _env->ReleaseIntArrayElements(_binaryFormatArray, (jint*)binaryFormat, 0);
+ _env->ReleaseIntArrayElements(_binaryFormatArray, (jint*)binaryFormat, _exception ? JNI_ABORT : 0);
}
if (_lengthArray) {
- _env->ReleaseIntArrayElements(_lengthArray, (jint*)length, 0);
+ _env->ReleaseIntArrayElements(_lengthArray, (jint*)length, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4896,11 +5556,20 @@
static void
android_glProgramBinary__IILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint program, jint binaryFormat, jobject binary_buf, jint length) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *binary = (GLvoid *) 0;
+ if (!binary_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "binary == null";
+ goto exit;
+ }
binary = (GLvoid *)getPointer(_env, binary_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (binary == NULL) {
char * _binaryBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -4912,9 +5581,14 @@
(GLvoid *)binary,
(GLsizei)length
);
+
+exit:
if (_array) {
releasePointer(_env, _array, binary, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramParameteri ( GLuint program, GLenum pname, GLint value ) */
@@ -4976,11 +5650,20 @@
static void
android_glInvalidateFramebuffer__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint numAttachments, jobject attachments_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLenum *attachments = (GLenum *) 0;
+ if (!attachments_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "attachments == null";
+ goto exit;
+ }
attachments = (GLenum *)getPointer(_env, attachments_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (attachments == NULL) {
char * _attachmentsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4991,9 +5674,14 @@
(GLsizei)numAttachments,
(GLenum *)attachments
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)attachments, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glInvalidateSubFramebuffer ( GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height ) */
@@ -5048,11 +5736,20 @@
static void
android_glInvalidateSubFramebuffer__IILjava_nio_IntBuffer_2IIII
(JNIEnv *_env, jobject _this, jint target, jint numAttachments, jobject attachments_buf, jint x, jint y, jint width, jint height) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLenum *attachments = (GLenum *) 0;
+ if (!attachments_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "attachments == null";
+ goto exit;
+ }
attachments = (GLenum *)getPointer(_env, attachments_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (attachments == NULL) {
char * _attachmentsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -5067,9 +5764,14 @@
(GLsizei)width,
(GLsizei)height
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)attachments, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexStorage2D ( GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height ) */
@@ -5149,11 +5851,20 @@
static void
android_glGetInternalformativ__IIIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint internalformat, jint pname, jint bufSize, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -5166,8 +5877,13 @@
(GLsizei)bufSize,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
diff --git a/core/jni/android_opengl_GLES31.cpp b/core/jni/android_opengl_GLES31.cpp
index 156e7bd..0e596dc 100644
--- a/core/jni/android_opengl_GLES31.cpp
+++ b/core/jni/android_opengl_GLES31.cpp
@@ -547,11 +547,20 @@
static void
android_glGetFramebufferParameteriv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -562,8 +571,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -616,11 +630,20 @@
static void
android_glGetProgramInterfaceiv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint programInterface, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -632,8 +655,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -777,6 +805,9 @@
static void
android_glGetProgramResourceiv__IIIILjava_nio_IntBuffer_2ILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint programInterface, jint index, jint propCount, jobject props_buf, jint bufSize, jobject length_buf, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _propsArray = (jintArray) 0;
jint _propsBufferOffset = (jint) 0;
jintArray _lengthArray = (jintArray) 0;
@@ -790,10 +821,22 @@
jint _paramsRemaining;
GLint *params = (GLint *) 0;
+ if (!props_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "props == null";
+ goto exit;
+ }
props = (GLenum *)getPointer(_env, props_buf, (jarray*)&_propsArray, &_propsRemaining, &_propsBufferOffset);
if (length_buf) {
length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
}
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_paramsArray, &_paramsRemaining, &_paramsBufferOffset);
if (props == NULL) {
char * _propsBase = (char *)_env->GetIntArrayElements(_propsArray, (jboolean *) 0);
@@ -817,15 +860,20 @@
(GLsizei *)length,
(GLint *)params
);
+
+exit:
if (_paramsArray) {
- _env->ReleaseIntArrayElements(_paramsArray, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_paramsArray, (jint*)params, _exception ? JNI_ABORT : 0);
}
if (_lengthArray) {
- _env->ReleaseIntArrayElements(_lengthArray, (jint*)length, 0);
+ _env->ReleaseIntArrayElements(_lengthArray, (jint*)length, _exception ? JNI_ABORT : 0);
}
if (_propsArray) {
_env->ReleaseIntArrayElements(_propsArray, (jint*)props, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* GLint glGetProgramResourceLocation ( GLuint program, GLenum programInterface, const GLchar *name ) */
@@ -1008,11 +1056,20 @@
static void
android_glDeleteProgramPipelines__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject pipelines_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *pipelines = (GLuint *) 0;
+ if (!pipelines_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "pipelines == null";
+ goto exit;
+ }
pipelines = (GLuint *)getPointer(_env, pipelines_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (pipelines == NULL) {
char * _pipelinesBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1022,9 +1079,14 @@
(GLsizei)n,
(GLuint *)pipelines
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)pipelines, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGenProgramPipelines ( GLsizei n, GLuint *pipelines ) */
@@ -1074,11 +1136,20 @@
static void
android_glGenProgramPipelines__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject pipelines_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *pipelines = (GLuint *) 0;
+ if (!pipelines_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "pipelines == null";
+ goto exit;
+ }
pipelines = (GLuint *)getPointer(_env, pipelines_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (pipelines == NULL) {
char * _pipelinesBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1088,8 +1159,13 @@
(GLsizei)n,
(GLuint *)pipelines
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)pipelines, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)pipelines, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1152,11 +1228,20 @@
static void
android_glGetProgramPipelineiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pipeline, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1167,8 +1252,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1371,11 +1461,20 @@
static void
android_glProgramUniform1iv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *value = (GLint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1387,9 +1486,14 @@
(GLsizei)count,
(GLint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform2iv ( GLuint program, GLint location, GLsizei count, const GLint *value ) */
@@ -1441,11 +1545,20 @@
static void
android_glProgramUniform2iv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *value = (GLint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1457,9 +1570,14 @@
(GLsizei)count,
(GLint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform3iv ( GLuint program, GLint location, GLsizei count, const GLint *value ) */
@@ -1511,11 +1629,20 @@
static void
android_glProgramUniform3iv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *value = (GLint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1527,9 +1654,14 @@
(GLsizei)count,
(GLint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform4iv ( GLuint program, GLint location, GLsizei count, const GLint *value ) */
@@ -1581,11 +1713,20 @@
static void
android_glProgramUniform4iv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *value = (GLint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1597,9 +1738,14 @@
(GLsizei)count,
(GLint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform1uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
@@ -1651,11 +1797,20 @@
static void
android_glProgramUniform1uiv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1667,9 +1822,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform2uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
@@ -1721,11 +1881,20 @@
static void
android_glProgramUniform2uiv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1737,9 +1906,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform3uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
@@ -1791,11 +1965,20 @@
static void
android_glProgramUniform3uiv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1807,9 +1990,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform4uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
@@ -1861,11 +2049,20 @@
static void
android_glProgramUniform4uiv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *value = (GLuint *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLuint *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1877,9 +2074,14 @@
(GLsizei)count,
(GLuint *)value
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform1fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
@@ -1931,11 +2133,20 @@
static void
android_glProgramUniform1fv__IIILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -1947,9 +2158,14 @@
(GLsizei)count,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform2fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
@@ -2001,11 +2217,20 @@
static void
android_glProgramUniform2fv__IIILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2017,9 +2242,14 @@
(GLsizei)count,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform3fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
@@ -2071,11 +2301,20 @@
static void
android_glProgramUniform3fv__IIILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2087,9 +2326,14 @@
(GLsizei)count,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniform4fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
@@ -2141,11 +2385,20 @@
static void
android_glProgramUniform4fv__IIILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2157,9 +2410,14 @@
(GLsizei)count,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2212,11 +2470,20 @@
static void
android_glProgramUniformMatrix2fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2229,9 +2496,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2284,11 +2556,20 @@
static void
android_glProgramUniformMatrix3fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2301,9 +2582,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2356,11 +2642,20 @@
static void
android_glProgramUniformMatrix4fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2373,9 +2668,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix2x3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2428,11 +2728,20 @@
static void
android_glProgramUniformMatrix2x3fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2445,9 +2754,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix3x2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2500,11 +2814,20 @@
static void
android_glProgramUniformMatrix3x2fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2517,9 +2840,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix2x4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2572,11 +2900,20 @@
static void
android_glProgramUniformMatrix2x4fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2589,9 +2926,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix4x2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2644,11 +2986,20 @@
static void
android_glProgramUniformMatrix4x2fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2661,9 +3012,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix3x4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2716,11 +3072,20 @@
static void
android_glProgramUniformMatrix3x4fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2733,9 +3098,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glProgramUniformMatrix4x3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
@@ -2788,11 +3158,20 @@
static void
android_glProgramUniformMatrix4x3fv__IIIZLjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *value = (GLfloat *) 0;
+ if (!value_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "value == null";
+ goto exit;
+ }
value = (GLfloat *)getPointer(_env, value_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (value == NULL) {
char * _valueBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2805,9 +3184,14 @@
(GLboolean)transpose,
(GLfloat *)value
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)value, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glValidateProgramPipeline ( GLuint pipeline ) */
@@ -2901,11 +3285,20 @@
static void
android_glGetBooleani_v__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint index, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLboolean *data = (GLboolean *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLboolean *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2916,8 +3309,13 @@
(GLuint)index,
(GLboolean *)data
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)data, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)data, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3001,11 +3399,20 @@
static void
android_glGetMultisamplefv__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jint index, jobject val_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *val = (GLfloat *) 0;
+ if (!val_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "val == null";
+ goto exit;
+ }
val = (GLfloat *)getPointer(_env, val_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (val == NULL) {
char * _valBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -3016,8 +3423,13 @@
(GLuint)index,
(GLfloat *)val
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)val, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)val, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3080,11 +3492,20 @@
static void
android_glGetTexLevelParameteriv__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3096,8 +3517,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3150,11 +3576,20 @@
static void
android_glGetTexLevelParameterfv__IIILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -3166,8 +3601,13 @@
(GLenum)pname,
(GLfloat *)params
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)params, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
diff --git a/core/jni/android_opengl_GLES31Ext.cpp b/core/jni/android_opengl_GLES31Ext.cpp
index 5be7be0..9f2b0c5 100644
--- a/core/jni/android_opengl_GLES31Ext.cpp
+++ b/core/jni/android_opengl_GLES31Ext.cpp
@@ -499,11 +499,20 @@
static void
android_glDebugMessageControlKHR__IIIILjava_nio_IntBuffer_2Z
(JNIEnv *_env, jobject _this, jint source, jint type, jint severity, jint count, jobject ids_buf, jboolean enabled) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *ids = (GLuint *) 0;
+ if (!ids_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "ids == null";
+ goto exit;
+ }
ids = (GLuint *)getPointer(_env, ids_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (ids == NULL) {
char * _idsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -517,9 +526,14 @@
(GLuint *)ids,
(GLboolean)enabled
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)ids, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glDebugMessageInsertKHR ( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf ) */
@@ -915,11 +929,20 @@
static void
android_glTexParameterIivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -930,9 +953,14 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexParameterIuivEXT ( GLenum target, GLenum pname, const GLuint *params ) */
@@ -983,11 +1011,20 @@
static void
android_glTexParameterIuivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -998,9 +1035,14 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetTexParameterIivEXT ( GLenum target, GLenum pname, GLint *params ) */
@@ -1051,11 +1093,20 @@
static void
android_glGetTexParameterIivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1066,8 +1117,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1119,11 +1175,20 @@
static void
android_glGetTexParameterIuivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1134,8 +1199,13 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1187,11 +1257,20 @@
static void
android_glSamplerParameterIivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject param_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *param = (GLint *) 0;
+ if (!param_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "param == null";
+ goto exit;
+ }
param = (GLint *)getPointer(_env, param_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (param == NULL) {
char * _paramBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1202,9 +1281,14 @@
(GLenum)pname,
(GLint *)param
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)param, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glSamplerParameterIuivEXT ( GLuint sampler, GLenum pname, const GLuint *param ) */
@@ -1255,11 +1339,20 @@
static void
android_glSamplerParameterIuivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject param_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *param = (GLuint *) 0;
+ if (!param_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "param == null";
+ goto exit;
+ }
param = (GLuint *)getPointer(_env, param_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (param == NULL) {
char * _paramBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1270,9 +1363,14 @@
(GLenum)pname,
(GLuint *)param
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)param, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetSamplerParameterIivEXT ( GLuint sampler, GLenum pname, GLint *params ) */
@@ -1323,11 +1421,20 @@
static void
android_glGetSamplerParameterIivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1338,8 +1445,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1391,11 +1503,20 @@
static void
android_glGetSamplerParameterIuivEXT__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1406,8 +1527,13 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
diff --git a/core/jni/android_opengl_GLES32.cpp b/core/jni/android_opengl_GLES32.cpp
index f9a1a8e..aa917a0 100644
--- a/core/jni/android_opengl_GLES32.cpp
+++ b/core/jni/android_opengl_GLES32.cpp
@@ -535,6 +535,12 @@
jint _remaining;
GLuint *ids = (GLuint *) 0;
+ if (!ids_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "ids == null";
+ goto exit;
+ }
ids = (GLuint *)getPointer(_env, ids_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count) {
_exception = 1;
@@ -852,6 +858,12 @@
jint _remaining;
void *indices = (void *) 0;
+ if (!indices_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "indices == null";
+ goto exit;
+ }
indices = (void *)getPointer(_env, indices_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count-basevertex) {
_exception = 1;
@@ -892,6 +904,12 @@
jint _remaining;
void *indices = (void *) 0;
+ if (!indices_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "indices == null";
+ goto exit;
+ }
indices = (void *)getPointer(_env, indices_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count-basevertex) {
_exception = 1;
@@ -1022,6 +1040,12 @@
jint _remaining;
void *data = (void *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (void *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < bufSize) {
_exception = 1;
@@ -1116,6 +1140,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < bufSize) {
_exception = 1;
@@ -1206,6 +1236,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < bufSize) {
_exception = 1;
@@ -1296,6 +1332,12 @@
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < bufSize) {
_exception = 1;
@@ -1390,11 +1432,20 @@
static void
android_glTexParameterIiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1405,9 +1456,14 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexParameterIuiv ( GLenum target, GLenum pname, const GLuint *params ) */
@@ -1458,11 +1514,20 @@
static void
android_glTexParameterIuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1473,9 +1538,14 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)params, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetTexParameterIiv ( GLenum target, GLenum pname, GLint *params ) */
@@ -1526,11 +1596,20 @@
static void
android_glGetTexParameterIiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1541,8 +1620,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1594,11 +1678,20 @@
static void
android_glGetTexParameterIuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1609,8 +1702,13 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1662,11 +1760,20 @@
static void
android_glSamplerParameterIiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject param_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *param = (GLint *) 0;
+ if (!param_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "param == null";
+ goto exit;
+ }
param = (GLint *)getPointer(_env, param_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (param == NULL) {
char * _paramBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1677,9 +1784,14 @@
(GLenum)pname,
(GLint *)param
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)param, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glSamplerParameterIuiv ( GLuint sampler, GLenum pname, const GLuint *param ) */
@@ -1730,11 +1842,20 @@
static void
android_glSamplerParameterIuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject param_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *param = (GLuint *) 0;
+ if (!param_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "param == null";
+ goto exit;
+ }
param = (GLuint *)getPointer(_env, param_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (param == NULL) {
char * _paramBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1745,9 +1866,14 @@
(GLenum)pname,
(GLuint *)param
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)param, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glGetSamplerParameterIiv ( GLuint sampler, GLenum pname, GLint *params ) */
@@ -1798,11 +1924,20 @@
static void
android_glGetSamplerParameterIiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1813,8 +1948,13 @@
(GLenum)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -1866,11 +2006,20 @@
static void
android_glGetSamplerParameterIuiv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLuint *params = (GLuint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLuint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -1881,8 +2030,13 @@
(GLenum)pname,
(GLuint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 10090a1..740b24d 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -25,6 +25,8 @@
#include <JNIHelp.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hidl/base/1.0/IBase.h>
+#include <android/hidl/base/1.0/IHwBase.h>
#include <android_runtime/AndroidRuntime.h>
#include <hidl/ServiceManagement.h>
#include <hidl/Status.h>
@@ -240,10 +242,17 @@
sp<hardware::IBinder> binder = JHwBinder::GetNativeContext(env, thiz);
+ sp<hidl::base::V1_0::IBase> base = hidl::base::V1_0::IHwBase::asInterface(binder);
+ if (base.get() == nullptr) {
+ LOG(ERROR) << "IBinder object cannot be casted to the base interface.";
+ signalExceptionForError(env, UNKNOWN_ERROR);
+ return;
+ }
+
bool ok = hardware::defaultServiceManager()->add(
interfaceChain,
serviceName,
- binder);
+ base);
env->ReleaseStringUTFChars(serviceNameObj, serviceName);
serviceName = NULL;
@@ -289,8 +298,10 @@
hardware::defaultServiceManager()->get(
ifaceName,
serviceName,
- [&service](sp<hardware::IBinder> out) {
- service = out;
+ [&service](sp<hidl::base::V1_0::IBase> out) {
+ service = hardware::toBinder<
+ hidl::base::V1_0::IBase, hidl::base::V1_0::IHwBase
+ >(out);
});
env->ReleaseStringUTFChars(ifaceNameObj, ifaceName);
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index d70fbb9..d382f24 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1179,67 +1179,17 @@
return result ? JNI_TRUE : JNI_FALSE;
}
-static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
- jlong themeToken,
- jint defStyleAttr,
- jint defStyleRes,
- jlong xmlParserToken,
- jintArray attrs,
- jintArray outValues,
- jintArray outIndices)
-{
- if (themeToken == 0) {
- jniThrowNullPointerException(env, "theme token");
- return JNI_FALSE;
- }
- if (attrs == NULL) {
- jniThrowNullPointerException(env, "attrs");
- return JNI_FALSE;
- }
- if (outValues == NULL) {
- jniThrowNullPointerException(env, "out values");
- return JNI_FALSE;
- }
-
- const jsize NI = env->GetArrayLength(attrs);
- const jsize NV = env->GetArrayLength(outValues);
- if (NV < (NI*STYLE_NUM_ENTRIES)) {
- jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
- return JNI_FALSE;
- }
-
- jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
- if (src == NULL) {
- return JNI_FALSE;
- }
-
- jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
- if (baseDest == NULL) {
- env->ReleasePrimitiveArrayCritical(attrs, src, 0);
- return JNI_FALSE;
- }
-
- jint* indices = NULL;
- if (outIndices != NULL) {
- if (env->GetArrayLength(outIndices) > NI) {
- indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
- }
- }
-
+static void android_content_AssetManager_applyStyle(JNIEnv* env, jobject, jlong themeToken,
+ jint defStyleAttr, jint defStyleRes, jlong xmlParserToken, jintArray attrsObj, jint length,
+ jlong outValuesAddress, jlong outIndicesAddress) {
+ jint* attrs = env->GetIntArrayElements(attrsObj, 0);
ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
- bool result = ApplyStyle(theme, xmlParser,
- defStyleAttr, defStyleRes,
- (uint32_t*) src, NI,
- (uint32_t*) baseDest,
- (uint32_t*) indices);
-
- if (indices != NULL) {
- env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
- }
- env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
- env->ReleasePrimitiveArrayCritical(attrs, src, 0);
- return result ? JNI_TRUE : JNI_FALSE;
+ uint32_t* outValues = reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(outValuesAddress));
+ uint32_t* outIndices = reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(outIndicesAddress));
+ ApplyStyle(theme, xmlParser, defStyleAttr, defStyleRes,
+ reinterpret_cast<const uint32_t*>(attrs), length, outValues, outIndices);
+ env->ReleaseIntArrayElements(attrsObj, attrs, JNI_ABORT);
}
static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
@@ -1795,7 +1745,7 @@
{ "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
(void*) android_content_AssetManager_dumpTheme },
// @FastNative
- { "applyStyle","(JIIJ[I[I[I)Z",
+ { "applyStyle","(JIIJ[IIJJ)V",
(void*) android_content_AssetManager_applyStyle },
// @FastNative
{ "resolveAttrs","(JII[I[I[I[I)Z",
diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp
index 173afd8..3219d594 100644
--- a/core/jni/android_util_EventLog.cpp
+++ b/core/jni/android_util_EventLog.cpp
@@ -16,16 +16,14 @@
#include <fcntl.h>
+#include <log/log_event_list.h>
+
#include "JNIHelp.h"
#include "core_jni_helpers.h"
#include "jni.h"
-#include <log/logger.h>
#define UNUSED __attribute__((__unused__))
-// The size of the tag number comes out of the payload size.
-#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
-
namespace android {
static jclass gCollectionClass;
@@ -53,7 +51,9 @@
jobject clazz UNUSED,
jint tag, jint value)
{
- return android_btWriteLog(tag, EVENT_TYPE_INT, &value, sizeof(value));
+ android_log_event_list ctx(tag);
+ ctx << (int32_t)value;
+ return ctx.write();
}
/*
@@ -64,7 +64,9 @@
jobject clazz UNUSED,
jint tag, jlong value)
{
- return android_btWriteLog(tag, EVENT_TYPE_LONG, &value, sizeof(value));
+ android_log_event_list ctx(tag);
+ ctx << (int64_t)value;
+ return ctx.write();
}
/*
@@ -75,7 +77,9 @@
jobject clazz UNUSED,
jint tag, jfloat value)
{
- return android_btWriteLog(tag, EVENT_TYPE_FLOAT, &value, sizeof(value));
+ android_log_event_list ctx(tag);
+ ctx << (float)value;
+ return ctx.write();
}
/*
@@ -85,22 +89,17 @@
static jint android_util_EventLog_writeEvent_String(JNIEnv* env,
jobject clazz UNUSED,
jint tag, jstring value) {
- uint8_t buf[MAX_EVENT_PAYLOAD];
-
+ android_log_event_list ctx(tag);
// Don't throw NPE -- I feel like it's sort of mean for a logging function
// to be all crashy if you pass in NULL -- but make the NULL value explicit.
- const char *str = value != NULL ? env->GetStringUTFChars(value, NULL) : "NULL";
- uint32_t len = strlen(str);
- size_t max = sizeof(buf) - sizeof(len) - 2; // Type byte, final newline
- if (len > max) len = max;
-
- buf[0] = EVENT_TYPE_STRING;
- memcpy(&buf[1], &len, sizeof(len));
- memcpy(&buf[1 + sizeof(len)], str, len);
- buf[1 + sizeof(len) + len] = '\n';
-
- if (value != NULL) env->ReleaseStringUTFChars(value, str);
- return android_bWriteLog(tag, buf, 2 + sizeof(len) + len);
+ if (value != NULL) {
+ const char *str = env->GetStringUTFChars(value, NULL);
+ ctx << str;
+ env->ReleaseStringUTFChars(value, str);
+ } else {
+ ctx << "NULL";
+ }
+ return ctx.write();
}
/*
@@ -109,45 +108,29 @@
*/
static jint android_util_EventLog_writeEvent_Array(JNIEnv* env, jobject clazz,
jint tag, jobjectArray value) {
- if (value == NULL) {
- return android_util_EventLog_writeEvent_String(env, clazz, tag, NULL);
- }
+ android_log_event_list ctx(tag);
- uint8_t buf[MAX_EVENT_PAYLOAD];
- const size_t max = sizeof(buf) - 1; // leave room for final newline
- size_t pos = 2; // Save room for type tag & array count
+ if (value == NULL) {
+ ctx << "[NULL]";
+ return ctx.write();
+ }
jsize copied = 0, num = env->GetArrayLength(value);
for (; copied < num && copied < 255; ++copied) {
+ if (ctx.status()) break;
jobject item = env->GetObjectArrayElement(value, copied);
- if (item == NULL || env->IsInstanceOf(item, gStringClass)) {
- if (pos + 1 + sizeof(jint) > max) break;
- const char *str = item != NULL ? env->GetStringUTFChars((jstring) item, NULL) : "NULL";
- jint len = strlen(str);
- if (pos + 1 + sizeof(len) + len > max) len = max - pos - 1 - sizeof(len);
- buf[pos++] = EVENT_TYPE_STRING;
- memcpy(&buf[pos], &len, sizeof(len));
- memcpy(&buf[pos + sizeof(len)], str, len);
- pos += sizeof(len) + len;
- if (item != NULL) env->ReleaseStringUTFChars((jstring) item, str);
+ if (item == NULL) {
+ ctx << "NULL";
+ } else if (env->IsInstanceOf(item, gStringClass)) {
+ const char *str = env->GetStringUTFChars((jstring) item, NULL);
+ ctx << str;
+ env->ReleaseStringUTFChars((jstring) item, str);
} else if (env->IsInstanceOf(item, gIntegerClass)) {
- jint intVal = env->GetIntField(item, gIntegerValueID);
- if (pos + 1 + sizeof(intVal) > max) break;
- buf[pos++] = EVENT_TYPE_INT;
- memcpy(&buf[pos], &intVal, sizeof(intVal));
- pos += sizeof(intVal);
+ ctx << (int32_t)env->GetIntField(item, gIntegerValueID);
} else if (env->IsInstanceOf(item, gLongClass)) {
- jlong longVal = env->GetLongField(item, gLongValueID);
- if (pos + 1 + sizeof(longVal) > max) break;
- buf[pos++] = EVENT_TYPE_LONG;
- memcpy(&buf[pos], &longVal, sizeof(longVal));
- pos += sizeof(longVal);
+ ctx << (int64_t)env->GetLongField(item, gLongValueID);
} else if (env->IsInstanceOf(item, gFloatClass)) {
- jfloat floatVal = env->GetFloatField(item, gFloatValueID);
- if (pos + 1 + sizeof(floatVal) > max) break;
- buf[pos++] = EVENT_TYPE_FLOAT;
- memcpy(&buf[pos], &floatVal, sizeof(floatVal));
- pos += sizeof(floatVal);
+ ctx << (float)env->GetFloatField(item, gFloatValueID);
} else {
jniThrowException(env,
"java/lang/IllegalArgumentException",
@@ -156,11 +139,7 @@
}
env->DeleteLocalRef(item);
}
-
- buf[0] = EVENT_TYPE_LIST;
- buf[1] = copied;
- buf[pos++] = '\n';
- return android_bWriteLog(tag, buf, pos);
+ return ctx.write();
}
/*
diff --git a/core/jni/android_util_MemoryIntArray.cpp b/core/jni/android_util_MemoryIntArray.cpp
index 9513c8b..2dfbe3e 100644
--- a/core/jni/android_util_MemoryIntArray.cpp
+++ b/core/jni/android_util_MemoryIntArray.cpp
@@ -54,7 +54,7 @@
}
static jlong android_util_MemoryIntArray_open(JNIEnv* env, jobject clazz, jint fd,
- jboolean owner, jboolean writable)
+ jboolean owner)
{
if (fd < 0) {
jniThrowException(env, "java/io/IOException", "bad file descriptor");
@@ -72,19 +72,35 @@
return -1;
}
- int protMode = (owner || writable) ? (PROT_READ | PROT_WRITE) : PROT_READ;
+ // IMPORTANT: Ashmem allows the caller to change its size until
+ // it is memory mapped for the first time which lazily creates
+ // the underlying VFS file. So the size we get above may not
+ // reflect the size of the underlying shared memory region. Therefore,
+ // we first memory map to set the size in stone an verify if
+ // the underlying ashmem region has the same size as the one we
+ // memory mapped. This is critical as we use the underlying
+ // ashmem size for boundary checks and memory unmapping.
+ int protMode = owner ? (PROT_READ | PROT_WRITE) : PROT_READ;
void* ashmemAddr = mmap(NULL, ashmemSize, protMode, MAP_SHARED, fd, 0);
if (ashmemAddr == MAP_FAILED) {
jniThrowException(env, "java/io/IOException", "cannot mmap ashmem");
return -1;
}
+ // Check if the mapped size is the same as the ashmem region.
+ int mmapedSize = ashmem_get_size_region(fd);
+ if (mmapedSize != ashmemSize) {
+ munmap(reinterpret_cast<void *>(ashmemAddr), ashmemSize);
+ jniThrowException(env, "java/io/IOException", "bad file descriptor");
+ return -1;
+ }
+
if (owner) {
int size = ashmemSize / sizeof(std::atomic_int);
new (ashmemAddr) std::atomic_int[size];
}
- if (owner && !writable) {
+ if (owner) {
int setProtResult = ashmem_set_prot_region(fd, PROT_READ);
if (setProtResult < 0) {
jniThrowException(env, "java/io/IOException", "cannot set ashmem prot mode");
@@ -131,7 +147,7 @@
}
static jint android_util_MemoryIntArray_get(JNIEnv* env, jobject clazz,
- jint fd, jlong address, jint index, jboolean owner)
+ jint fd, jlong address, jint index)
{
if (fd < 0) {
jniThrowException(env, "java/io/IOException", "bad file descriptor");
@@ -153,7 +169,7 @@
}
static void android_util_MemoryIntArray_set(JNIEnv* env, jobject clazz,
- jint fd, jlong address, jint index, jint newValue, jboolean owner)
+ jint fd, jlong address, jint index, jint newValue)
{
if (fd < 0) {
jniThrowException(env, "java/io/IOException", "bad file descriptor");
@@ -195,10 +211,10 @@
static const JNINativeMethod methods[] = {
{"nativeCreate", "(Ljava/lang/String;I)I", (void*)android_util_MemoryIntArray_create},
- {"nativeOpen", "(IZZ)J", (void*)android_util_MemoryIntArray_open},
+ {"nativeOpen", "(IZ)J", (void*)android_util_MemoryIntArray_open},
{"nativeClose", "(IJZ)V", (void*)android_util_MemoryIntArray_close},
- {"nativeGet", "(IJIZ)I", (void*)android_util_MemoryIntArray_get},
- {"nativeSet", "(IJIIZ)V", (void*) android_util_MemoryIntArray_set},
+ {"nativeGet", "(IJI)I", (void*)android_util_MemoryIntArray_get},
+ {"nativeSet", "(IJII)V", (void*) android_util_MemoryIntArray_set},
{"nativeSize", "(I)I", (void*) android_util_MemoryIntArray_size},
};
diff --git a/core/jni/android_view_GraphicBuffer.cpp b/core/jni/android_view_GraphicBuffer.cpp
index 4b105ca..b6b5245 100644
--- a/core/jni/android_view_GraphicBuffer.cpp
+++ b/core/jni/android_view_GraphicBuffer.cpp
@@ -196,7 +196,8 @@
Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas);
nativeCanvas->setBitmap(bitmap);
- nativeCanvas->clipRect(rect.left, rect.top, rect.right, rect.bottom);
+ nativeCanvas->clipRect(rect.left, rect.top, rect.right, rect.bottom,
+ SkClipOp::kIntersect);
if (dirtyRect) {
INVOKEV(dirtyRect, gRectClassInfo.set,
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index b6c81cf8..92693b7 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -339,7 +339,7 @@
if (dirtyRectPtr) {
nativeCanvas->clipRect(dirtyRect.left, dirtyRect.top,
- dirtyRect.right, dirtyRect.bottom);
+ dirtyRect.right, dirtyRect.bottom, SkClipOp::kIntersect);
}
if (dirtyRectObj) {
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 268aec5..3c8db7f 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -166,7 +166,8 @@
Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas);
nativeCanvas->setBitmap(bitmap);
- nativeCanvas->clipRect(rect.left, rect.top, rect.right, rect.bottom);
+ nativeCanvas->clipRect(rect.left, rect.top, rect.right, rect.bottom,
+ SkClipOp::kIntersect);
if (dirtyRect) {
INVOKEV(dirtyRect, gRectClassInfo.set,
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index ad7d744..bf0e9ed 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -420,6 +420,9 @@
static void
android_glColorPointerBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -438,17 +441,29 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data ) */
static void
android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -464,20 +479,34 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCompressedTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data ) */
static void
android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint imageSize, jobject data_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (data == NULL) {
char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -494,9 +523,14 @@
(GLsizei)imageSize,
(GLvoid *)data
);
+
+exit:
if (_array) {
releasePointer(_env, _array, data, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glCopyTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) */
@@ -601,6 +635,12 @@
jint _remaining;
GLuint *textures = (GLuint *) 0;
+ if (!textures_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "textures == null";
+ goto exit;
+ }
textures = (GLuint *)getPointer(_env, textures_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -705,6 +745,12 @@
jint _remaining;
GLvoid *indices = (GLvoid *) 0;
+ if (!indices_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "indices == null";
+ goto exit;
+ }
indices = (GLvoid *)getPointer(_env, indices_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < count) {
_exception = 1;
@@ -860,6 +906,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1006,6 +1058,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -1154,6 +1212,12 @@
jint _remaining;
GLuint *textures = (GLuint *) 0;
+ if (!textures_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "textures == null";
+ goto exit;
+ }
textures = (GLuint *)getPointer(_env, textures_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -1580,6 +1644,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2038,6 +2108,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2166,6 +2242,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2322,6 +2404,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2505,6 +2593,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2644,11 +2738,20 @@
static void
android_glLoadMatrixf__Ljava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *m = (GLfloat *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfloat *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -2657,9 +2760,14 @@
glLoadMatrixf(
(GLfloat *)m
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glLoadMatrixx ( const GLfixed *m ) */
@@ -2708,11 +2816,20 @@
static void
android_glLoadMatrixx__Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *m = (GLfixed *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfixed *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -2721,9 +2838,14 @@
glLoadMatrixx(
(GLfixed *)m
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glLogicOp ( GLenum opcode ) */
@@ -2836,6 +2958,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -2991,6 +3119,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -3100,11 +3234,20 @@
static void
android_glMultMatrixf__Ljava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *m = (GLfloat *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfloat *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -3113,9 +3256,14 @@
glMultMatrixf(
(GLfloat *)m
);
+
+exit:
if (_array) {
_env->ReleaseFloatArrayElements(_array, (jfloat*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMultMatrixx ( const GLfixed *m ) */
@@ -3164,11 +3312,20 @@
static void
android_glMultMatrixx__Ljava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jobject m_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *m = (GLfixed *) 0;
+ if (!m_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "m == null";
+ goto exit;
+ }
m = (GLfixed *)getPointer(_env, m_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (m == NULL) {
char * _mBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -3177,9 +3334,14 @@
glMultMatrixx(
(GLfixed *)m
);
+
+exit:
if (_array) {
_env->ReleaseIntArrayElements(_array, (jint*)m, JNI_ABORT);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMultiTexCoord4f ( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q ) */
@@ -3234,6 +3396,9 @@
static void
android_glNormalPointerBounds__IILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3251,6 +3416,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glOrthof ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) */
@@ -3347,11 +3515,20 @@
static void
android_glReadPixels__IIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLvoid *pixels = (GLvoid *) 0;
+ if (!pixels_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "pixels == null";
+ goto exit;
+ }
pixels = (GLvoid *)getPointer(_env, pixels_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (pixels == NULL) {
char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
@@ -3366,8 +3543,13 @@
(GLenum)type,
(GLvoid *)pixels
);
+
+exit:
if (_array) {
- releasePointer(_env, _array, pixels, JNI_TRUE);
+ releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -3493,6 +3675,9 @@
static void
android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3511,6 +3696,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexEnvf ( GLenum target, GLenum pname, GLfloat param ) */
@@ -3608,6 +3796,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -3751,6 +3945,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -3803,6 +4003,9 @@
static void
android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3829,6 +4032,9 @@
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexParameterf ( GLenum target, GLenum pname, GLfloat param ) */
@@ -3857,6 +4063,9 @@
static void
android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint type, jobject pixels_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3883,6 +4092,9 @@
if (_array) {
releasePointer(_env, _array, pixels, JNI_FALSE);
}
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTranslatef ( GLfloat x, GLfloat y, GLfloat z ) */
@@ -3911,6 +4123,9 @@
static void
android_glVertexPointerBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -3929,6 +4144,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glViewport ( GLint x, GLint y, GLsizei width, GLsizei height ) */
@@ -4041,6 +4259,12 @@
jint _exponentRemaining;
GLint *exponent = (GLint *) 0;
+ if (!mantissa_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "mantissa == null";
+ goto exit;
+ }
mantissa = (GLfixed *)getPointer(_env, mantissa_buf, (jarray*)&_mantissaArray, &_mantissaRemaining, &_mantissaBufferOffset);
if (_mantissaRemaining < 16) {
_exception = 1;
@@ -4048,6 +4272,12 @@
_exceptionMessage = "remaining() < 16 < needed";
goto exit;
}
+ if (!exponent_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "exponent == null";
+ goto exit;
+ }
exponent = (GLint *)getPointer(_env, exponent_buf, (jarray*)&_exponentArray, &_exponentRemaining, &_exponentBufferOffset);
if (_exponentRemaining < 16) {
_exception = 1;
@@ -4144,6 +4374,12 @@
jint _remaining;
GLvoid *data = (GLvoid *) 0;
+ if (!data_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "data == null";
+ goto exit;
+ }
data = (GLvoid *)getPointer(_env, data_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < size) {
_exception = 1;
@@ -4232,6 +4468,12 @@
jint _remaining;
GLfloat *equation = (GLfloat *) 0;
+ if (!equation_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "equation == null";
+ goto exit;
+ }
equation = (GLfloat *)getPointer(_env, equation_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 4) {
_exception = 1;
@@ -4318,6 +4560,12 @@
jint _remaining;
GLfixed *equation = (GLfixed *) 0;
+ if (!equation_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "equation == null";
+ goto exit;
+ }
equation = (GLfixed *)getPointer(_env, equation_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 4) {
_exception = 1;
@@ -4428,6 +4676,12 @@
jint _remaining;
GLuint *buffers = (GLuint *) 0;
+ if (!buffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "buffers == null";
+ goto exit;
+ }
buffers = (GLuint *)getPointer(_env, buffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -4532,6 +4786,12 @@
jint _remaining;
GLuint *buffers = (GLuint *) 0;
+ if (!buffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "buffers == null";
+ goto exit;
+ }
buffers = (GLuint *)getPointer(_env, buffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -4604,11 +4864,20 @@
static void
android_glGetBooleanv__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLboolean *params = (GLboolean *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLboolean *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4618,8 +4887,13 @@
(GLenum)pname,
(GLboolean *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4686,11 +4960,20 @@
static void
android_glGetClipPlanef__ILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *eqn = (GLfloat *) 0;
+ if (!eqn_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "eqn == null";
+ goto exit;
+ }
eqn = (GLfloat *)getPointer(_env, eqn_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (eqn == NULL) {
char * _eqnBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -4700,8 +4983,13 @@
(GLenum)pname,
(GLfloat *)eqn
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)eqn, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)eqn, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4752,11 +5040,20 @@
static void
android_glGetClipPlanex__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *eqn = (GLfixed *) 0;
+ if (!eqn_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "eqn == null";
+ goto exit;
+ }
eqn = (GLfixed *)getPointer(_env, eqn_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (eqn == NULL) {
char * _eqnBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4766,8 +5063,13 @@
(GLenum)pname,
(GLfixed *)eqn
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)eqn, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)eqn, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4818,11 +5120,20 @@
static void
android_glGetFixedv__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -4832,8 +5143,13 @@
(GLenum)pname,
(GLfixed *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -4884,11 +5200,20 @@
static void
android_glGetFloatv__ILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -4898,8 +5223,13 @@
(GLenum)pname,
(GLfloat *)params
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)params, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -5007,6 +5337,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -5179,6 +5515,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -5337,6 +5679,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -5481,6 +5829,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -5619,6 +5973,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -5751,6 +6111,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -5861,6 +6227,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -5949,6 +6321,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -6037,6 +6415,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -6178,6 +6562,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -6274,6 +6664,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -6303,6 +6699,9 @@
static void
android_glPointSizePointerOESBounds__IILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -6320,6 +6719,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glTexCoordPointer ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
@@ -6429,6 +6831,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
int _needed;
switch (pname) {
@@ -6539,6 +6947,12 @@
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -6638,6 +7052,12 @@
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -6726,6 +7146,12 @@
jint _remaining;
GLfixed *params = (GLfixed *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfixed *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 1) {
_exception = 1;
@@ -6846,6 +7272,12 @@
jint _remaining;
GLfloat *coords = (GLfloat *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLfloat *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -6943,6 +7375,12 @@
jint _remaining;
GLint *coords = (GLint *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLint *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -7040,6 +7478,12 @@
jint _remaining;
GLshort *coords = (GLshort *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLshort *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -7137,6 +7581,12 @@
jint _remaining;
GLfixed *coords = (GLfixed *) 0;
+ if (!coords_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "coords == null";
+ goto exit;
+ }
coords = (GLfixed *)getPointer(_env, coords_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < 5) {
_exception = 1;
@@ -7172,6 +7622,9 @@
static void
android_glMatrixIndexPointerOESBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -7190,6 +7643,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glMatrixIndexPointerOES ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
@@ -7208,6 +7664,9 @@
static void
android_glWeightPointerOESBounds__IIILjava_nio_Buffer_2I
(JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jarray _array = (jarray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
@@ -7226,6 +7685,9 @@
(GLvoid *)pointer,
(GLsizei)remaining
);
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
+ }
}
/* void glWeightPointerOES ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
@@ -7403,6 +7865,12 @@
jint _remaining;
GLuint *framebuffers = (GLuint *) 0;
+ if (!framebuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "framebuffers == null";
+ goto exit;
+ }
framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -7499,6 +7967,12 @@
jint _remaining;
GLuint *renderbuffers = (GLuint *) 0;
+ if (!renderbuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "renderbuffers == null";
+ goto exit;
+ }
renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -7644,6 +8118,12 @@
jint _remaining;
GLuint *framebuffers = (GLuint *) 0;
+ if (!framebuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "framebuffers == null";
+ goto exit;
+ }
framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -7740,6 +8220,12 @@
jint _remaining;
GLuint *renderbuffers = (GLuint *) 0;
+ if (!renderbuffers_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "renderbuffers == null";
+ goto exit;
+ }
renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (_remaining < n) {
_exception = 1;
@@ -7824,11 +8310,20 @@
"glGetFramebufferAttachmentParameterivOES");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -7840,8 +8335,13 @@
(GLint)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -7903,11 +8403,20 @@
"glGetRenderbufferParameterivOES");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -7918,8 +8427,13 @@
(GLint)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -7981,11 +8495,20 @@
"glGetTexGenfv");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -7996,8 +8519,13 @@
(GLint)pname,
(GLfloat *)params
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)params, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -8059,11 +8587,20 @@
"glGetTexGeniv");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -8074,8 +8611,13 @@
(GLint)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -8137,11 +8679,20 @@
"glGetTexGenxv");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -8152,8 +8703,13 @@
(GLint)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -8280,11 +8836,20 @@
"glTexGenfv");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jfloatArray _array = (jfloatArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLfloat *params = (GLfloat *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLfloat *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetFloatArrayElements(_array, (jboolean *) 0);
@@ -8295,8 +8860,13 @@
(GLint)pname,
(GLfloat *)params
);
+
+exit:
if (_array) {
- _env->ReleaseFloatArrayElements(_array, (jfloat*)params, 0);
+ _env->ReleaseFloatArrayElements(_array, (jfloat*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -8374,11 +8944,20 @@
"glTexGeniv");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -8389,8 +8968,13 @@
(GLint)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
@@ -8468,11 +9052,20 @@
"glTexGenxv");
return;
}
+ jint _exception = 0;
+ const char * _exceptionType = NULL;
+ const char * _exceptionMessage = NULL;
jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLint *params = (GLint *) 0;
+ if (!params_buf) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "params == null";
+ goto exit;
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (params == NULL) {
char * _paramsBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
@@ -8483,8 +9076,13 @@
(GLint)pname,
(GLint *)params
);
+
+exit:
if (_array) {
- _env->ReleaseIntArrayElements(_array, (jint*)params, 0);
+ _env->ReleaseIntArrayElements(_array, (jint*)params, _exception ? JNI_ABORT : 0);
+ }
+ if (_exception) {
+ jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6f33f27..40fd881 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -182,6 +182,10 @@
android:name="android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS" />
<protected-broadcast
android:name="android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_RECEIVED" />
+ <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_SENT_SUCCESSFULLY" />
+ <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_DELIVERED_SUCCESSFULLY" />
<protected-broadcast
android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_SENT" />
<protected-broadcast
@@ -189,6 +193,7 @@
<protected-broadcast
android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.btopp.intent.action.INCOMING_FILE_NOTIFICATION" />
<protected-broadcast android:name="android.btopp.intent.action.USER_CONFIRMATION_TIMEOUT" />
@@ -2710,6 +2715,8 @@
This is a normal permission: an app requesting it will always be granted the
permission, without the user needing to approve or see it. -->
<permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"
+ android:label="@string/permlab_requestIgnoreBatteryOptimizations"
+ android:description="@string/permdesc_requestIgnoreBatteryOptimizations"
android:protectionLevel="normal" />
<!-- @SystemApi Allows an application to collect battery statistics -->
diff --git a/core/res/res/anim/slide_in_enter_micro.xml b/core/res/res/anim/slide_in_enter_micro.xml
index 6e7df4f..c70874c 100644
--- a/core/res/res/anim/slide_in_enter_micro.xml
+++ b/core/res/res/anim/slide_in_enter_micro.xml
@@ -19,7 +19,7 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:zAdjustment="top">
- <translate android:fromXDelta="5%p" android:toXDelta="0"
+ <translate android:fromYDelta="5%p" android:toYDelta="0"
android:duration="417"
android:interpolator="@android:interpolator/launch_task_micro_ydelta" />
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
diff --git a/core/res/res/anim/slide_out_micro.xml b/core/res/res/anim/slide_out_micro.xml
index cccf697..01df0da 100644
--- a/core/res/res/anim/slide_out_micro.xml
+++ b/core/res/res/anim/slide_out_micro.xml
@@ -20,7 +20,7 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:zAdjustment="normal">
- <translate android:fromXDelta="0" android:toXDelta="5%p"
+ <translate android:fromYDelta="0" android:toYDelta="5%p"
android:duration="250"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
diff --git a/core/res/res/layout/date_picker_material.xml b/core/res/res/layout/date_picker_material.xml
index 763f2a4..dd8a45d2 100644
--- a/core/res/res/layout/date_picker_material.xml
+++ b/core/res/res/layout/date_picker_material.xml
@@ -25,10 +25,16 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
- <include
- layout="@layout/date_picker_view_animator_material"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1" />
+ <ScrollView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:fadeScrollbars="false"
+ android:scrollIndicators="top|bottom">
+ <include
+ layout="@layout/date_picker_view_animator_material"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+ </ScrollView>
</LinearLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index a24bce1..4af7e4a 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Laat die program toe om die kitsboodskapdiens te gebruik om oproepe sonder jou ingryping te maak."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lees foonstatus en identiteit"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Laat die program toe om toegang tot die foonfunksies van die toestel te verkry. Hierdie toestemming laat die program toe om te bepaal wat die foonnommer en toestel-IDs is, of die oproep aan die gang is, en die afgeleë nommer wat deur \'n oproep verbind word."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lees foonnommer"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Gee die program toegang tot die toestel se foonnommer."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"verhoed dat tablet slaap"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"keer TV om te sluimer"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"verhoed foon om te slaap"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Laat \'n program toe om installasiesessies te lees. Dit laat dit toe om besonderhede van aktiewe pakketinstallasies te sien."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"versoek installeerpakkette"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Laat \'n program toe om te versoek dat pakkette geïnstalleer word."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"vra om batteryoptimerings te ignoreer"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Laat \'n program toe om toestemming te vra om batteryoptimerings vir daardie program ignoreer."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Klop twee keer vir zoembeheer"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Kon nie legstuk byvoeg nie."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Gaan"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Kies jaar"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> uitgevee"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2e werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3e werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Raak en hou Terug om hierdie skerm te ontspeld."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Program is vasgespeld: Dit mag nie op hierdie toestel ontspeld word nie."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skerm vasgespeld"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Stel nou terug"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Het <xliff:g id="LABEL">%1$s</xliff:g> gedeaktiveer"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferensie-oproep"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Nutswenk-opspringer"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Nutswenk"</string>
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 6bab82c..9731f27 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"መተግበሪያው ያለእርስዎ ጣልቃ ገብነት ጥሪዎችን ለማድረግ የአይኤምኤስ አገልግሎቱን እንዲጠቀም ያስችለዋል።"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"የስልክ ሁኔታና ማንነት አንብብ"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"መተግበሪያው የመሳሪያውን የስልክ ባህሪያት ላይ እንዲደርስ ይፈቅድለታል። ይህ ፈቃድ መተግበሪያው የስልክ ቁጥሩን እና የመሳሪያውን መታወቂያዎች፣ ጥሪ የነቃ እንደሆነ፣ እና በጥሪ የተገናኘውን የሩቅ ቁጥር እንዲወስን ይፈቅድለታል።"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ስልክ ቁጥር አንብብ"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"መተግበሪያው የመሣሪያውን ስልክ ቁጥር እንዲደርስበት ይፈቅድለታል።"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ጡባዊ ከማንቀላፋት ተከላከል"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ቴሌቪዥን እንዳይተኛ አግድ"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ስልክ ከማንቀላፋት ተከላከል"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"መተግበሪያው የመጫን ክፍለ ጊዜዎችን እንዲያነብ ይፈቅድለታል። ይህም ስለ ገቢር የጥቅል ጭነቶች ዝርዝር መረጃን እንዲያይ ይፈቅድለታል።"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"የጭነት ጥቅሎችን መጠየቅ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"መተግበሪያ የጥቅሎች መጫንን እንዲጠይቅ ይፈቅዳል።"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"የባትሪ ማትባቶችን ችላ ለማለት መጠየቅ"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"አንድ መተግበሪያ ለዚያ መተግበሪያ የባትሪ ማትባቶችን ችላ ለማለት እንዲጠይቅ ይፈቅድለታል።"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ለአጉላ መቆጣጠሪያ ሁለት ጊዜ ነካ አድርግ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ምግብር ማከል አልተቻለም።"</string>
<string name="ime_action_go" msgid="8320845651737369027">"ሂድ"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"ዓመት ይምረጡ"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ተሰርዟል"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2ኛ ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3ኛ ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ይህን ማያ ገጽ ለመንቀል ተመለስን ይንኩትና ያዙት።"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"መተግበሪያ ተሰክቷል፦ በዚህ መሣሪያ ላይ ማላቀቅ አይፈቀድም።"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ማያ ገጽ ተሰክቷል"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"አሁን ዳግም አስጀምር"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> ተሰናክሏል"</string>
<string name="conference_call" msgid="3751093130790472426">"የስብሰባ ጥሪ"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"የመሣሪያ ጥቆማ ብቅ-ባይ"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"የመሣሪያ ጥቆማ"</string>
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 7c9baeb..feb9c85 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -389,6 +389,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"للسماح للتطبيق باستخدام خدمة الرسائل الفورية لإجراء المكالمات دون تدخل منك."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"قراءة حالة الهاتف والهوية"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"للسماح للتطبيق بالدخول إلى ميزات الهاتف في الجهاز. ويتيح هذا الإذن للتطبيق تحديد رقم الهاتف ومعرّفات الجهاز، وما إذا كانت هناك مكالمة نشطة والرقم البعيد الذي تم الاتصال به في المكالمة."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"قراءة رقم الهاتف"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"للسماح للتطبيق بالوصول إلى رقم الهاتف على الجهاز."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"منع الجهاز اللوحي من الدخول في وضع السكون"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"منع التلفزيون من الدخول في وضع السكون"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"منع الهاتف من الدخول في وضع السكون"</string>
@@ -783,7 +785,7 @@
<string name="js_dialog_before_unload_title" msgid="2619376555525116593">"تأكيد الانتقال"</string>
<string name="js_dialog_before_unload_positive_button" msgid="3112752010600484130">"مغادرة هذه الصفحة"</string>
<string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"البقاء في هذه الصفحة"</string>
- <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nهل تريد بالتأكيد الانتقال بعيدًا عن هذه الصفحة؟"</string>
+ <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nهل تريد فعلًا الانتقال بعيدًا عن هذه الصفحة؟"</string>
<string name="save_password_label" msgid="6860261758665825069">"تأكيد"</string>
<string name="double_tap_toast" msgid="4595046515400268881">"نصيحة: اضغط مرتين للتكبير والتصغير."</string>
<string name="autofill_this_form" msgid="4616758841157816676">"ملء تلقائي"</string>
@@ -1310,6 +1312,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"للسماح لأحد التطبيقات بقراءة جلسات التثبيت. ويسمح لك هذا بالاطلاع على تفاصيل بشأن عمليات تثبيت الحزم النشطة."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"طلب حزم التثبيت"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"للسماح لتطبيق ما بطلب تثبيت الحزم."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"طلب تجاهل تحسينات البطارية"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"للسماح للتطبيق بطلب الإذن لتجاهل تحسينات البطارية في هذا التطبيق."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"اضغط مرتين للتحكم في التكبير/التصغير"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"تعذرت إضافة أداة."</string>
<string name="ime_action_go" msgid="8320845651737369027">"تنفيذ"</string>
@@ -1668,10 +1672,8 @@
<string name="select_year" msgid="7952052866994196170">"تحديد العام"</string>
<string name="deleted_key" msgid="7659477886625566590">"تم حذف <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> المخصص للعمل"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"العمل الثاني <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"العمل الثالث <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"لإزالة تثبيت هذه الشاشة، يمكنك لمس زر الرجوع مع الاستمرار."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"التطبيق مقيد: ولا يسمح بإلغاء التقييد على هذا الجهاز."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"تم تثبيت الشاشة"</string>
@@ -1827,5 +1829,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"إعادة التعيين الآن"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"تم تعطيل <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"مكالمة جماعية"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"نافذة منبثقة لتلميح"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"تلميح"</string>
</resources>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 11133d1..b3094e1 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Tətbiqə müdaxilə olmadan zəng etmək üçün IMS xidmətindən istifadə etməyə imkan verir."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"telefon statusunu və identifikasiyanı oxuyur"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Tətbiqə cihazın telefon funksiyalarına giriş icazəsi verir. Belə icazəli tətbiq bu telefonun nömrəsini və cihaz İD\'ni, zəngin aktiv olub-olmadığını və zəng edilən nömrəni müəyyən edə bilər."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"telefon nömrəsini oxuyun"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Tətbiqə cihazın telefon nömrəsinə daxil olmağa icazə verir."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"planşetin yuxu rejiminin qarşısını almaq"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV-ni yuxu rejiminə keçməyə qoyma"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"telefonun yuxu rejiminə keçməsini əngəllə"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Tətbiqə quraşdırma sessiyalarını oxumağa yardım edir. Bu da aktiv paket quraşdırmaları haqqında məlumatları görməyə imkan verir."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"paketləri quraşdırma sorğusu"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Tətbiqə paketləri quraşdırma sorğusu göndərməyə icazə verir."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"batareya optimallaşdırmasını iqnor etmək üçün soruşun"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Tatareya optimallaşdırılmasını o tətbiq üçün iqnor edilməsinə icazə vermək məqsədilə soruşmağa tətbiqə icazə verilir."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Zoom kontrolu üçün iki dəfə toxunun"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget əlavə edilə bilmədi."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Get"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"İl seçin"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> silindi"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"İş <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-ci İş <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-cü İş <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Sancağı götürmək üçün Geri düyməsinə toxunun və saxlayın."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Tətbiq sancılıb: Açmağa bu cihazda icazə verilmir."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Screen pinned"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"İndi sıfırlayın"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> deaktiv edildi"</string>
<string name="conference_call" msgid="3751093130790472426">"Konfrans Zəngi"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Tooltip Popap"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Tooltip"</string>
</resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index d2799c4..588d3ba 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -380,6 +380,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Dozvoljava aplikaciji da koristi uslugu razmene trenutnih poruka da bi upućivala pozive bez vaše intervencije."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"čitanje statusa i identiteta telefona"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Dozvoljava aplikaciji da pristupa funkcijama telefona na uređaju. Ova dozvola omogućava aplikaciji da utvrdi broj telefona i ID-ove uređaja, zatim da li je poziv aktivan, kao i broj daljinskog uređaja sa kojim je uspostavljen poziv."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"čitanje broja telefona"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Dozvoljava aplikaciji da pristupa broju telefona na uređaju."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"sprečavanje prelaska tableta u stanje spavanja"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"sprečavanje TV-a da pređe u stanje spavanja"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"sprečavanje prelaska telefona u stanje spavanja"</string>
@@ -1235,6 +1237,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Dozvoljava aplikaciji da čita sesije instaliranja. To joj dozvoljava da vidi detalje o aktivnim instalacijama paketa."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"zahtevanje paketa za instaliranje"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Omogućava da aplikacija zahteva instalaciju paketa."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"traženje dozvole za ignorisanje optimizacija baterije"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Dozvoljava aplikaciji da traži dozvolu za ignorisanje optimizacija baterije za tu aplikaciju."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Dodirnite dvaput za kontrolu zumiranja"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nije moguće dodati vidžet."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Idi"</string>
@@ -1587,10 +1591,8 @@
<string name="select_year" msgid="7952052866994196170">"Izaberite godinu"</string>
<string name="deleted_key" msgid="7659477886625566590">"Izbrisali ste <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> na poslu"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. poslovni imejl <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Da biste otkačili ovaj ekran, dodirnite i zadržite Nazad."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacija je zakačena: otkačinjanje nije dozvoljeno na ovom uređaju."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran je zakačen"</string>
@@ -1719,5 +1721,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Resetuj"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Vidžet <xliff:g id="LABEL">%1$s</xliff:g> je onemogućen"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferencijski poziv"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Iskačuće objašnjenje"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Objašnjenje"</string>
</resources>
diff --git a/core/res/res/values-be-rBY/strings.xml b/core/res/res/values-be-rBY/strings.xml
index a7be24e..e5b0a5c 100644
--- a/core/res/res/values-be-rBY/strings.xml
+++ b/core/res/res/values-be-rBY/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Дазваляе праграмам выкарыстоўваць службу IMS, каб рабіць выклікі без вашага ўмяшання."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"чытанне статусу тэлефона і ідэнтыфікацыя"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Дазваляе прыкладанням атрымлiваць доступ да функцый тэлефона на прыладзе. Дзякуючы гэтаму дазволу прыкладанне можа вызначаць iдэнтыфiкатары нумару тэлефона i прылады, незалежна ад таго, цi актыўны выклiк, i аддалены нумар, на якi робiцца выклiк."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"чытаць нумар тэлефона"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Праграма зможа атрымліваць доступ да тэлефоннага нумара прылады."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"прадухіліць планшэт ад пераходу ў рэжым сну"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"прадухіленне пераходу тэлевізара ў рэжым сну"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"забараняць тэлефону пераходзіць ў рэжым сну"</string>
@@ -1260,6 +1262,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Дазваляе праграме счытваць сеансы ўсталёўкі. Гэта дазваляе ёй праглядаць інфармацыю аб актыўных усталёўках пакета."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"запытваць усталёўку пакетаў"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Дазваляе праграме запытваць усталёўку пакетаў."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"запытваць дазвол на ігнараванне аптымізацыі акумулятара"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Дазваляе праграме запытваць дазвол на ігнараванне аптымізацыі акумулятара для гэтай праграмы."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Націсніце двойчы, каб кіраваць маштабаваннем"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Немагчыма дадаць віджэт."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Пачаць"</string>
@@ -1614,10 +1618,8 @@
<string name="select_year" msgid="7952052866994196170">"Выберыце год"</string>
<string name="deleted_key" msgid="7659477886625566590">"Выдалена: <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (праца)"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Другая праца <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Трэцяя праца <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Каб адмацаваць гэты экран, дакраніцеся і ўтрымлівайце кнопку \"Назад\"."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Праграма замацавана: адмацаванне на гэтай прыладзе не дапускаецца."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Экран замацаваны"</string>
@@ -1755,5 +1757,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Выканаць скід"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Адключаны <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Канферэнц-выклік"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Усплывальная падказка"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Падказка"</string>
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 1900b074..f0acf39 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Разрешава на приложението да използва услугата за незабавни съобщения за извършване на обаждания без намеса от ваша страна."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"четене на състоянието и идентификационните данни на телефона"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Разрешава на приложението достъп до телефонните функции на устройството. Това разрешение позволява на приложението да определя телефонния номер и идентификационния номер на устройството, дали се води разговор и отдалечения номер, до който е установена връзка с обаждането."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"четене на телефонния номер"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Разрешава на приложението да осъществява достъп до телефонния номер на устройството."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"предотвратяване на спящия режим на таблета"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"предотвратяване на преминаването на телевизора в спящ режим"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"предотвратява спящ режим на телефона"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Разрешава на приложението да чете сесии за инсталиране. Това му позволява да вижда подробности за активните инсталирания на пакети."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"заявка на пакети за инсталиране"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Разрешава на приложението да заявява инсталиране на пакети."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"искане за пренебрегване на оптимизациите на батерията"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Разрешава на дадено приложение да иска разрешение за пренебрегване на свързаните с него оптимизации на батерията."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Докоснете двукратно за управление на промяната на мащаба"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Приспособлението не можа да бъде добавено."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Старт"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Избиране на година"</string>
<string name="deleted_key" msgid="7659477886625566590">"Изтрихте <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> за работа"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Втори служебен профил (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Трети служебен профил (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"За да освободите този екран, докоснете и задръжте бутона за връщане назад."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Приложението е фиксирано. Освобождаването му не е разрешено на това устройство."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Екранът е фиксиран"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Нулиране сега"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g>: Деактивирано"</string>
<string name="conference_call" msgid="3751093130790472426">"Конферентно обаждане"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Изскачащ прозорец с подсказка"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Подсказка"</string>
</resources>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index bdbea68..01bcce5 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"আপনার হস্তক্ষেপ ছাড়াই কল করতে অ্যাপ্লিকেশানটিকে IMS পরিষেবা ব্যবহারের অনুমতি দিন৷"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ফোনের স্থিতি এবং পরিচয় পড়ুন"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"অ্যাপ্লিকেশানটিকে ডিভাইসের ফোন বৈশিষ্ট্যগুলিকে অ্যাক্সেস করার অনুমতি দেয়৷ এই অনুমতিটি অ্যাপ্লিকেশানটিকে একটি কল সক্রিয় থাকা অবস্থায় এবং দূরবর্তী নম্বর একটি কল দ্বারা সংযুক্ত থাকাকালীনও ফোন নম্বর এবং ডিভাইসের IDগুলি নির্ধারণ করার অনুমতি দেয়৷"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"অ্যাপটিকে ফোন নম্বর পড়ার অনুমতি দিন"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"অ্যাপটিকে এই ডিভাইসের ফোন নম্বর অ্যাক্সেস করার মঞ্জুরি দেয়"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ঘুমানো থেকে ট্যাবলেটকে প্রতিরোধ করে"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"টিভিকে নিদ্রায় যাওয়া থেকে প্রতিরোধ করে"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ঘুমানো থেকে ফোনটিকে প্রতিরোধ করে"</string>
@@ -605,7 +607,7 @@
<string name="phoneTypeRadio" msgid="4093738079908667513">"রেডিও"</string>
<string name="phoneTypeTelex" msgid="3367879952476250512">"টেলেক্স"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
- <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"কার্যক্ষেত্রের মোবাইল"</string>
+ <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"অফিসের মোবাইল"</string>
<string name="phoneTypeWorkPager" msgid="649938731231157056">"কার্যক্ষেত্রের পেজার"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"সহায়ক"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"মিডিয়ার ভলিউম"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"বিজ্ঞপ্তির ভলিউম"</string>
<string name="ringtone_default" msgid="3789758980357696936">"ডিফল্ট রিংটোন"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ডিফল্ট (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"কোনো কিছুই নয়"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"রিংটোনগুলি"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"অ্যালার্মের শব্দ"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"বিজ্ঞপ্তির শব্দ"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"অজানা"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">ওয়াই-ফাই নেটওয়ার্কগুলি উপলব্ধ রয়েছে</item>
<item quantity="other">ওয়াই-ফাই নেটওয়ার্কগুলি উপলব্ধ রয়েছে</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"কোনো অ্যাপ্লিকেশানকে সেশনগুলি পড়ার অনুমতি দেয়। এটি সক্রিয় প্যাকেজ ইনস্টলেশনের বিশদ বিবরণ দেখতে দেয়।"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"প্যাকেজগুলি ইনস্টল করার অনুরোধ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"একটি অ্যাপ্লিকেশানকে প্যাকেজগুলির ইনস্টল করার অনুরোধ জানাতে অনুমতি দেয়৷"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ব্যাটারি অপ্টিমাইজেশন উপেক্ষা করার জন্য অনুমতি চাওয়া"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"কোনো অ্যাপের জন্য ব্যাটারি অপ্টিমাইজেশন উপেক্ষা করতে সেটিকে অনুমতির চাওয়ার মঞ্জুরি দেয়৷"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"জুম নিয়ন্ত্রণের জন্য দুবার আলতো চাপুন"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"উইজেট যোগ করা যায়নি৷"</string>
<string name="ime_action_go" msgid="8320845651737369027">"যান"</string>
@@ -1240,7 +1240,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"ওয়ালপেপার"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"ওয়ালপেপার পরিবর্তন করুন"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"বিজ্ঞপ্তির শ্রোতা"</string>
- <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR শ্রোতা"</string>
+ <string name="vr_listener_binding_label" msgid="4316591939343607306">"(ভিআর)VR শ্রোতা"</string>
<string name="condition_provider_service_binding_label" msgid="1321343352906524564">"শর্ত প্রদানকারী"</string>
<string name="notification_ranker_binding_label" msgid="774540592299064747">"বিজ্ঞপ্তি র্যাঙ্কার পরিষেবা"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN সক্রিয়"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"বছর নির্বাচন করুন"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> মুছে ফেলা হয়েছে"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"কর্মক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"দ্বিতীয় কার্যক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"তৃতীয় কার্যক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"এই স্ক্রীনটিকে আনপিন করতে, \'ফিরুন\' স্পর্শ করুন এবং ধরে রাখুন৷"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"অ্যাপ্লিকেশান পিন করা আছে: এই ডিভাইস এটিকে পিনমুক্ত করা মঞ্জুরিপ্রাপ্ত নয়৷"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"স্ক্রীন পিন করা হয়েছে"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"এখনই পুনরায় সেট করুন"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"অক্ষম করা <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"কনফারেন্স কল"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"টুলটিপ"</string>
</resources>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index f62dac7..1d74ce7 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -380,6 +380,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Omogućava aplikaciji da koristi IMS uslugu za pozivanje bez vaše intervencije."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"čitanje statusa i identiteta telefona"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Omogućava aplikaciji pristup telefonskim funkcijama uređaja. Ova dozvola omogućava aplikaciji određivanje telefonskog i identifikacionog broja uređaja, bez obzira da li je poziv aktivan i da li je uspostavljena veza sa pozivanim brojem."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"čitanje telefonskog broja"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Dopušta aplikaciji pristup telefonskom broju telefona."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"sprečavanje tableta da uđe u režim mirovanja"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"spriječi ulazak TV-a u režim mirovanja"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"sprečavanje telefona da uđe u režim mirovanja"</string>
@@ -646,17 +648,17 @@
<string name="relationTypeAssistant" msgid="6274334825195379076">"Pomoćnik"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"Brat"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"Dijete"</string>
- <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Domaći partner"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Nevjenčani partner"</string>
<string name="relationTypeFather" msgid="5228034687082050725">"Otac"</string>
<string name="relationTypeFriend" msgid="7313106762483391262">"Prijatelj"</string>
- <string name="relationTypeManager" msgid="6365677861610137895">"Menadžer"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"Šef"</string>
<string name="relationTypeMother" msgid="4578571352962758304">"Majka"</string>
<string name="relationTypeParent" msgid="4755635567562925226">"Roditelj"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"Partner"</string>
<string name="relationTypeReferredBy" msgid="101573059844135524">"Uputio(la)"</string>
- <string name="relationTypeRelative" msgid="1799819930085610271">"Rođak"</string>
+ <string name="relationTypeRelative" msgid="1799819930085610271">"Rođak/ica"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"Sestra"</string>
- <string name="relationTypeSpouse" msgid="394136939428698117">"Bračni partner"</string>
+ <string name="relationTypeSpouse" msgid="394136939428698117">"Suprug/a"</string>
<string name="sipAddressTypeCustom" msgid="2473580593111590945">"Prilagođeno"</string>
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Kuća"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Posao"</string>
@@ -1237,6 +1239,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Dozvoljava aplikaciji da čita sesije instalacija. Ovim se aplikaciji omogućava da vidi detalje o aktivnim instalacijama paketa."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"zahtijevanje paketa za instaliranje"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Omogućava aplikaciji da zahtijeva instalaciju paket ā."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"traži zanemarivanje optimizacije baterije"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Omogućava aplikaciji da traži dozvolu za zanemarivanje optimizacije baterije za tu aplikaciju."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Dodirnite dvaput za kontrolu uvećanja"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Dodavanje vidžeta nije uspjelo."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Počni"</string>
@@ -1589,10 +1593,8 @@
<string name="select_year" msgid="7952052866994196170">"Odaberite godinu"</string>
<string name="deleted_key" msgid="7659477886625566590">"Broj <xliff:g id="KEY">%1$s</xliff:g> je izbrisan"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Da biste otkačili ovaj ekran, dodirnite i držite dugme Nazad."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacija je prikačena. Na ovom uređaju nije dozvoljeno otkačivanje."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran je zakačen"</string>
@@ -1721,5 +1723,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Vrati sada na početne postavke"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Onemogućen <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferencijski poziv"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Iskočni prozor sa savjetom u vezi alata"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Savjet za alat"</string>
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index f335d44..00e1a2f 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permet que l\'aplicació utilitzi el servei IMS per fer trucades sense la teva intervenció."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"veure l\'estat i la identitat del telèfon"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permet que l\'aplicació accedeixi a les funcions de telèfon del dispositiu. Aquest permís permet que l\'aplicació determini el número de telèfon i els identificadors del dispositiu, si hi ha una trucada activa i el número remot connectat amb una trucada."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"llegeix el número de telèfon"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permet que l\'aplicació accedeixi al número de telèfon del dispositiu."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"evita que la tauleta entri en mode de repòs"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"impedir que el televisor entri en mode de repòs"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"impedir que el telèfon entri en mode de repòs"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permet que una aplicació llegeixi les sessions d\'instal·lació i això permet veure detalls sobre les instal·lacions de paquet actives."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"sol·licitar la instal·lació de paquets"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permet que una aplicació sol·liciti la instal·lació de paquets."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"Demanar permís per ignorar les optimitzacions de bateria"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Permet que una aplicació demani permís per ignorar les optimitzacions de bateria per a l\'aplicació."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Piqueu dos cops per controlar el zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"No s\'ha pogut afegir el widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Vés"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Selecciona un any"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> suprimit"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2n <xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3r <xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Toca i mantén premuda l\'opció Enrere per deixar de fixar aquesta pantalla."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"S\'ha fixat l\'aplicació. En aquest dispositiu no es permet anul·lar-ne la fixació."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantalla fixada"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Restableix ara"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> s\'ha desactivat"</string>
<string name="conference_call" msgid="3751093130790472426">"Conferència"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Descripció emergent"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Descripció emergent"</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 0bdd212..f622d9d 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Umožňuje aplikaci používat službu zasílání rychlých zpráv k uskutečňování hovorů bez vašeho zásahu."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"čtení stavu a identity telefonu"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Umožňuje aplikaci získat přístup k telefonním funkcím zařízení. Toto oprávnění umožňuje aplikaci zjistit telefonní číslo telefonu, identifikační čísla zařízení, zda zrovna probíhá hovor, a vzdálené číslo, ke kterému je hovor připojen."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"přístup k telefonnímu číslu"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Umožňuje aplikaci zobrazit telefonní číslo zařízení."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"bránění přechodu tabletu do režimu spánku"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"zabránění přechodu televize do režimu spánku"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"bránění přechodu telefonu do režimu spánku"</string>
@@ -1260,6 +1262,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Povoluje aplikaci číst instalační relace. Díky tomu můžete zobrazit podrobnosti o aktivních instalacích balíčku."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"odesílání žádostí o přístup k instalačním balíčkům"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Umožňuje aplikaci požádat o instalaci balíčků."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"požádat o ignorování optimalizace využití baterie"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Povoluje aplikaci požádat o oprávnění ignorovat optimalizaci využití baterie, která pro ni je nastavena."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Poklepáním můžete ovládat přiblížení"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget nelze přidat."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Přejít"</string>
@@ -1614,10 +1618,8 @@
<string name="select_year" msgid="7952052866994196170">"Vyberte rok"</string>
<string name="deleted_key" msgid="7659477886625566590">"Číslice <xliff:g id="KEY">%1$s</xliff:g> byla smazána"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Pracovní <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Chcete-li tuto obrazovku uvolnit, klepněte na tlačítko Zpět a podržte jej."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikace je připnutá: Odepnutí v tomto zařízení není povoleno."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Obrazovka připnuta"</string>
@@ -1755,5 +1757,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Resetovat"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> – zakázáno"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferenční hovor"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Vyskakovací okno s popiskem"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Popisek"</string>
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index f80f5f0..723c08e 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Tillader, at appen kan bruge chat-tjenesten til at foretage opkald, uden du gør noget."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"læse telefonens status og identitet"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Tillader, at appen kan få adgang til telefonfunktionerne på enheden. Med denne tilladelse kan appen fastslå telefonnummeret og enheds-id\'erne, hvorvidt et opkald er aktivt samt det eksterne nummer, der oprettes forbindelse til via et opkald."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"læs telefonnummer"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Tillader, at appen har adgang til enhedens telefonnummer."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"afholde tabletcomputeren fra at gå i dvale"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"forhindre tv i at gå i dvale"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"afholde telefonen fra at gå i dvale"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Medielydstyrke"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Lydstyrke for meddelelser"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Standardringetone"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Standard (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Ingen"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Ringetoner"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Alarmlyde"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Meddelelseslyde"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Ukendt"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Tilgængelige Wi-Fi-netværk</item>
<item quantity="other">Tilgængelige Wi-Fi-netværk</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Tillader, at en applikation læser installationssessioner. Dermed kan applikationen se oplysninger om aktive pakkeinstallationer."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"anmod om installation af pakker"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Tillader, at en app anmoder om installation af pakker."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"bede om at ignorere batterioptimeringer"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Gør det muligt for en app at bede om tilladelse til at ignorere batterioptimeringer for den pågældende app."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tryk to gange for zoomkontrol"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget kunne ikke tilføjes."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Gå"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Vælg år"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> er slettet"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> – arbejde"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> til arbejde"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> til arbejde"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Hvis du vil frigøre dette skærmbillede, skal du trykke på Tilbage og holde fingeren nede."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Appen er fastgjort: Det er ikke tilladt at frigøre den på denne enhed."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skærmen blev fastgjort"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Nulstil nu"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> – deaktiveret"</string>
<string name="conference_call" msgid="3751093130790472426">"Telefonmøde"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Værktøjstip"</string>
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 1ceb0cc..96307f2 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Ermöglicht der App die Verwendung des IMS-Dienstes zum Tätigen von Anrufen ohne Nutzereingriffe"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"Telefonstatus und Identität abrufen"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Ermöglicht der App, auf die Telefonfunktionen des Geräts zuzugreifen. Die Berechtigung erlaubt der App, die Telefonnummer und Geräte-IDs zu erfassen, festzustellen, ob gerade ein Gespräch geführt wird, und die Rufnummer verbundener Anrufer zu lesen."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"Telefonnummer lesen"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Der App den Zugriff auf die Telefonnummer des Geräts erlauben."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"Ruhezustand des Tablets deaktivieren"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"Ruhemodus des Fernsehers deaktivieren"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Ruhezustand deaktivieren"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Medienlautstärke"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Benachrichtigungslautstärke"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Standard-Klingelton"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Standard (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Ohne"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Klingeltöne"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Weckertöne"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Benachrichtigungstöne"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Unbekannt"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">WLAN-Netzwerke verfügbar</item>
<item quantity="one">WLAN-Netzwerk verfügbar</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Ermöglicht der App, Installationssitzungen zu lesen. Dadurch kann sie Details aktiver Paketinstallationen abrufen."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"Installation von Paketen anfordern"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Ermöglicht der App, die Installation von Paketen anzufordern"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"Fragen, ob Akku-Leistungsoptimierungen ignoriert werden können"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Erlaubt einer App, nach der Berechtigung zum Ignorieren der Akku-Leistungsoptimierungen zu fragen."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Für Zoomeinstellung zweimal berühren"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget konnte nicht hinzugefügt werden."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Los"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Jahr auswählen"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> gelöscht"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Um die Fixierung dieses Bildschirms aufzuheben, \"Zurück\" berühren und halten."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Die App ist fixiert. Das Aufheben der Fixierung ist auf diesem Gerät nicht zulässig."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Bildschirm fixiert"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Jetzt zurücksetzen"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> deaktiviert"</string>
<string name="conference_call" msgid="3751093130790472426">"Telefonkonferenz"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Kurzinfo"</string>
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index b9d9503..d767abf 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Επιτρέπει στην εφαρμογή τη χρήση της υπηρεσίας IMS για την πραγματοποίηση κλήσεων χωρίς τη δική σας παρέμβαση."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"διαβάζει την κατάσταση και ταυτότητα τηλεφώνου"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Επιτρέπει στην εφαρμογή την πρόσβαση στις λειτουργίες τηλεφώνου της συσκευής. Αυτή η άδεια δίνει τη δυνατότητα στην εφαρμογή να καθορίζει τον αριθμό τηλεφώνου και τα αναγνωριστικά συσκευών, εάν μια κλήση είναι ενεργή, καθώς και τον απομακρυσμένο αριθμό που συνδέεται από μια κλήση."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ανάγνωση αριθμού τηλεφώνου"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Επιτρέπει στην εφαρμογή να έχει πρόσβαση στον αριθμό τηλεφώνου της συσκευής."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"αποτρέπει την μετάβαση του tablet σε κατάσταση αδράνειας"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"αποτρέπει την μετάβαση της τηλεόρασης σε κατάσταση αδράνειας"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"αποτρέπει το τηλεφώνο να μεταβεί σε κατάσταση αδράνειας"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Επιτρέπει σε μια εφαρμογή την ανάγνωση των περιόδων σύνδεσης εγκατάστασης. Αυτό της επιτρέπει να βλέπει λεπτομέρειες σχετικά με τις εγκαταστάσεις του ενεργού πακέτου."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ζητά πακέτα εγκατάστασης"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Επιτρέπει σε μια εφαρμογή να ζητά εγκατάσταση πακέτων."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"αίτημα αγνόησης βελτιστοποιήσεων μπαταρίας"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Επιτρέπει σε μια εφαρμογή να ζητήσει άδεια για την αγνόηση βελτιστοποιήσεων της μπαταρίας για τη συγκεκριμένη εφαρμογή."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Πατήστε δύο φορές για έλεγχο εστίασης"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Δεν ήταν δυνατή η προσθήκη του γραφικού στοιχείου."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Μετάβαση"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Επιλογή έτους"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> διαγράφηκε"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Εργασία <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> εργασίας 2"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> εργασίας 3"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Για να ξεκαρφιτσώσετε αυτήν την οθόνη, αγγίξτε παρατεταμένα \"Επιστροφή\"."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Η εφαρμογή καρφιτσώθηκε: Το ξεκαρφίτσωμα δεν επιτρέπεται σε αυτήν τη συσκευή."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Η οθόνη καρφιτσώθηκε"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Επαναφορά τώρα"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Απενεργοποιημένο <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Κλήση συνδιάσκεψης"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Αναδυόμενο παράθυρο επεξήγησης εργαλείου"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Επεξήγηση εργαλείου"</string>
</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 5bc43e0..03795d4 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Allows the app to use the IMS service to make calls without your intervention."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"read phone status and identity"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active and the remote number connected by a call."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"read phone number"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Allows the app to access the phone number of the device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"prevent tablet from sleeping"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"prevent TV from sleeping"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"prevent phone from sleeping"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Allows an application to read install sessions. This allows it to see details about active package installations."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"request install packages"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Allows an application to request installation of packages."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ask to ignore battery optimisations"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Allows an app to ask for permission to ignore battery optimisations for that app."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tap twice for zoom control"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Couldn\'t add widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Go"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Select year"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> deleted"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"To unpin this screen, touch & hold Back."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App is pinned: unpinning isn\'t allowed on this device."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Screen pinned"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Reset now"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Disabled <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Conference Call"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Tooltip Pop-up"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Tooltip"</string>
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 5bc43e0..03795d4 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Allows the app to use the IMS service to make calls without your intervention."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"read phone status and identity"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active and the remote number connected by a call."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"read phone number"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Allows the app to access the phone number of the device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"prevent tablet from sleeping"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"prevent TV from sleeping"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"prevent phone from sleeping"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Allows an application to read install sessions. This allows it to see details about active package installations."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"request install packages"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Allows an application to request installation of packages."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ask to ignore battery optimisations"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Allows an app to ask for permission to ignore battery optimisations for that app."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tap twice for zoom control"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Couldn\'t add widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Go"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Select year"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> deleted"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"To unpin this screen, touch & hold Back."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App is pinned: unpinning isn\'t allowed on this device."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Screen pinned"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Reset now"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Disabled <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Conference Call"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Tooltip Pop-up"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Tooltip"</string>
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 5bc43e0..03795d4 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Allows the app to use the IMS service to make calls without your intervention."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"read phone status and identity"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Allows the app to access the phone features of the device. This permission allows the app to determine the phone number and device IDs, whether a call is active and the remote number connected by a call."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"read phone number"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Allows the app to access the phone number of the device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"prevent tablet from sleeping"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"prevent TV from sleeping"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"prevent phone from sleeping"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Allows an application to read install sessions. This allows it to see details about active package installations."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"request install packages"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Allows an application to request installation of packages."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ask to ignore battery optimisations"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Allows an app to ask for permission to ignore battery optimisations for that app."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tap twice for zoom control"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Couldn\'t add widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Go"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Select year"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> deleted"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"To unpin this screen, touch & hold Back."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App is pinned: unpinning isn\'t allowed on this device."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Screen pinned"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Reset now"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Disabled <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Conference Call"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Tooltip Pop-up"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Tooltip"</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index cd2c5aa..e984c65 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite que la aplicación utilice el servicio IMS para hacer llamadas sin tu intervención."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"leer la identidad y el estado del dispositivo"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que la aplicación acceda a las funciones de teléfono del dispositivo. La aplicación puede utilizar este permiso para descubrir identificadores de dispositivos y números de teléfono, para saber si una llamada está activa y para conocer el número remoto con el que se ha establecido conexión mediante una llamada."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"leer el número de teléfono"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permite que la app acceda al número de teléfono del dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"evitar que el tablet entre en estado de inactividad"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"evitar que la TV entre en suspensión"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"evitar que el dispositivo entre en estado de inactividad"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que una aplicación lea sesiones de instalación. Esto le permite ver detalles acerca de instalaciones de paquetes activas."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar la instalación de paquetes"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite que una aplicación solicite la instalación de paquetes."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"solicitar permiso para ignorar las optimizaciones de la batería"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Permite que una app solicite permiso para ignorar las optimizaciones de la batería."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Presiona dos veces para obtener el control del zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"No se pudo agregar el widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ir"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Seleccionar año"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> borrado"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 2"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 3"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Para dejar de fijar esta pantalla, mantén presionado Atrás."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"La aplicación está fijada, no se puede anular la fijación en este dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantalla fija"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Restablecer ahora"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Se inhabilitó <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Conferencia"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Ventana emergente de la información sobre la herramienta"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Información sobre la herramienta"</string>
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index fe7d1ac..0e1df79 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite que la aplicación utilice el servicio IMS para realizar llamadas sin tu intervención."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"consultar la identidad y el estado del teléfono"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que la aplicación acceda a las funciones de teléfono del dispositivo. La aplicación puede utilizar este permiso para descubrir identificadores de dispositivos y números de teléfono, para saber si una llamada está activa y para conocer el número remoto con el que se ha establecido conexión mediante una llamada."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"leer el número de teléfono"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permite que la aplicación acceda al número de teléfono del dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir que el tablet entre en modo de suspensión"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"evitar que la TV entre en suspensión"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"impedir que el teléfono entre en modo de suspensión"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que una aplicación consulte sesiones de instalación para ver detalles sobre instalaciones de paquetes activos."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar instalación de paquetes"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite a una aplicación solicitar la instalación de paquetes."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"solicitar permiso para ignorar las optimizaciones de la batería"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Permite que una aplicación solicite permiso para ignorar las optimizaciones de la batería."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Da dos toques para acceder al control de zoom."</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"No se ha podido añadir el widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ir"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Seleccionar año"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminado"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 2"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 3"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Mantén pulsado el botón Atrás para dejar de fijar esta pantalla."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"La aplicación está fijada: no se puede deshacer la fijación en este dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantalla fijada"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Restablecer ahora"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> inhabilitado"</string>
<string name="conference_call" msgid="3751093130790472426">"Conferencia"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Descripción emergente"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Descripción emergente"</string>
</resources>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 09668cb..6429193 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Võimaldab rakendusel kasutada IMS-teenust kõnede tegemiseks ilma, et peaksite sekkuma."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lugege telefoni olekut ja identiteeti"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Annab rakendusele juurdepääsu seadme telefonifunktsioonidele. See luba võimaldab rakendusel määrata telefoninumbri ja seadme ID-d ning kontrollida, kas kõne on aktiivne ja kaugnumber on kõne kaudu telefoniga ühendatud."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lugeda telefoninumbrit"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Lubab rakendusel juurde pääseda seadme telefoninumbrile."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"tahvelarvuti uinumise vältimine"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"teleri unerežiimi lülitumise takistamine"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"väldi telefoni uinumist"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Meediumi helitugevus"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Teatise helitugevus"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Vaikehelin"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Vaikimisi (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Puudub"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Helinad"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Äratuse helid"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Märguannete helid"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Teadmata"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">WiFi-võrgud on saadaval</item>
<item quantity="one">WiFi-võrk on saadaval</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Lubab rakendusel lugeda installiseansse. See võimaldab näha aktiivse paketi installimise üksikasju."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"installipakettide taotlemine"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Võimaldab rakendusel pakettide installimist taotleda."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"küsida luba aku optimeerimise eiramiseks"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Lubab rakendusel küsida luba rakenduse aku optimeerimise eiramiseks."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Suumi kasutamiseks koputage kaks korda"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Vidinat ei saanud lisada."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Mine"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Aasta valimine"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> on kustutatud"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Ekraani vabastamiseks puudutage pikalt nuppu Tagasi."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Rakendus on kinnitatud: vabastamine pole selles seadmes lubatud."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekraan on kinnitatud"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Lähtesta kohe"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Keelatud <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Konverentskõne"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Tööriistavihje"</string>
</resources>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 2ea4bed..d8cd634 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Zuk ezer egin beharrik gabe deiak egiteko IMS zerbitzua erabiltzea baimentzen die aplikazioei."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"telefonoaren egoera eta identitatea irakurtzea"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Gailuaren telefono-eginbideak atzitzeko baimena ematen die aplikazioei. Baimen horrek aplikazioari telefono-zenbakia eta gailu IDak zein diren, deirik aktibo dagoen eta deia zer zenbakirekin konektatuta dagoen zehazteko baimena ematen die aplikazioei."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"Irakurri telefono-zenbakia"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Gailuaren telefono-zenbakia atzitzea baimentzen dio aplikazioari."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"Eragotzi tableta inaktibo ezartzea"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"Eragotzi telebista inaktibo geratzea"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Eragotzi telefonoa inaktibo ezartzea"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Instalazio-saioak irakurtzea baimentzen die aplikazioei. Horrela, pakete-instalazio aktiboei buruzko xehetasunak ikus ditzakete."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"Eskatu instalazio-paketeak"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Paketeak instalatzeko eskatzea baimentzen die aplikazioei."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"Eskatu bateriaren optimizazioei ez ikusi egitea"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Bateriaren optimizazioei ez ikusi egiteko baimena eskatzea baimentzen die aplikazioei."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Sakatu birritan zooma kontrolatzeko"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Ezin izan da widgeta gehitu."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Joan"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Hautatu urtea"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ezabatu da"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Laneko <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Laneko 2. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Laneko 3. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Pantailari aingura kentzeko, eduki sakatuta Atzera botoia."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikazioa ainguratuta dago. Gailu honetan ezin da aingura kendu."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantaila ainguratu da"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Berrezarri"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> desgaituta dago"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferentzia-deia"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Aholkudun leiho gainerakorra"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Aholkua"</string>
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 55e67bc..457127a 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"به برنامه اجازه میدهد از سرویس IMS برای برقراری تماسها بدون دخالت شما استفاده کند."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"خواندن وضعیت تلفن و شناسه"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"به برنامه اجازه میدهد به ویژگیهای تلفن دستگاه شما دسترسی پیدا کند. این مجوز به برنامه اجازه میدهد شماره تلفن و شناسههای دستگاه، فعال بودن یک تماس و شماره راه دوری که با یک تماس متصل شده است را مشخص کند."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"خواندن شماره تلفن"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"به برنامه اجازه میدهد به شماره تلفن دستگاه دسترسی پیدا کند."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ممانعت از به خواب رفتن رایانهٔ لوحی"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"جلوگیری از به حالت خواب رفتن تلویزیون"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ممانعت از به خواب رفتن تلفن"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"میزان صدای رسانه"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"میزان صدای اعلان"</string>
<string name="ringtone_default" msgid="3789758980357696936">"آهنگ زنگ پیشفرض"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"پیشفرض (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"هیچکدام"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"آهنگهای زنگ"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"صداهای زنگ هشدار"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"صداهای اعلان"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"نامشخص"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">شبکه Wi-Fi در دسترس</item>
<item quantity="other">شبکه Wi-Fi در دسترس</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"به برنامه اجازه میدهد جلسات نصب را بخواند. این کار به برنامه اجازه میدهد جزئیات نصبهای بسته فعال را ببیند."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"درخواست نصب بسته"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"به برنامه اجازه میدهد درخواست نصب بستهبندی کند."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"درخواست نادیدهگرفتن بهینهسازی باتری"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"به یک برنامه اجازه میدهد جهت نادیده گرفتن بهینهسازی باتری برای خود مجوز درخواست کند."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"برای کنترل بزرگنمایی، دو بار ضربه بزنید"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"افزودن ابزارک انجام نشد."</string>
<string name="ime_action_go" msgid="8320845651737369027">"برو"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"انتخاب سال"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> حذف شد"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> محل کار"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"کار دوم <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"کار سوم <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"برای برداشتن پین این صفحه، «برگشت» را لمس کنید و نگه دارید."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"برنامه پین شده است: برداشتن پین در این دستگاه مجاز نیست."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"صفحه پین شد"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"بازنشانی در این لحظه"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> غیرفعال شد"</string>
<string name="conference_call" msgid="3751093130790472426">"تماس کنفرانسی"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"نکتهابزار"</string>
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 6800fa8..36c3e6c 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Antaa sovelluksen soittaa puheluita pikaviestipalvelun avulla ilman käyttäjän toimia."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lue puhelimen tila ja identiteetti"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Antaa sovelluksen käyttää laitteen puhelinominaisuuksia. Sovellus voi määrittää puhelinnumeron ja laitteen tunnuksen, puhelun tilan sekä soitetun numeron."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lukea puhelinnumeron"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Anna sovelluksen käyttää laitteen puhelinnumeroa."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"estä tablet-laitetta menemästä virransäästötilaan"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"Estä television siirtyminen virransäästötilaan"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"estä puhelinta menemästä virransäästötilaan"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Sallii sovelluksen lukea asennusistuntoja. Toiminto sallii sovelluksen lukea aktiivisten asennuspakettien tietoja."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"pyytää asennuspaketteja"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Antaa sovelluksen pyytää pakettien asennusta."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"Lupa ohittaa akun optimoinnit"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Sallii sovelluksen pyytää lupaa ohittaa tietyn sovelluksen akun optimoinnit."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Hallitse zoomausta napauttamalla kahdesti"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widgetin lisääminen epäonnistui."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Siirry"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Valitse vuosi"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> poistettiin"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (työ)"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Toinen <xliff:g id="LABEL">%1$s</xliff:g>, työ"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Kolmas <xliff:g id="LABEL">%1$s</xliff:g>, työ"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Irrota näyttö koskettamalla Takaisin-painiketta pitkään."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Sovellus on kiinnitetty. Irrottaminen ei ole sallittua tällä laitteella."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Näyttö kiinnitetty"</string>
@@ -1612,7 +1614,7 @@
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Kunnes kello on <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> asti (seuraava hälytys)"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Kunnes poistat tämän käytöstä"</string>
+ <string name="zen_mode_forever" msgid="7420011936770086993">"Kunnes otat tämän pois päältä"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Kunnes poistat Varattu-tilan käytöstä."</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Kutista"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Palauta nyt"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> ei ole käytössä."</string>
<string name="conference_call" msgid="3751093130790472426">"Puhelinneuvottelu"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Työkaluvinkki ponnahdusikkunassa"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Työkaluvinkki"</string>
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 009b9eb..9dd10fa 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permet à l\'application d\'utiliser le service IMS pour faire des appels sans votre intervention."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"voir l\'état et l\'identité du téléphone"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permet à l\'application d\'accéder aux fonctionnalités téléphoniques de l\'appareil. Cette autorisation permet à l\'application de déterminer le numéro de téléphone et les identifiants de l\'appareil, si un appel est actif et le numéro distant connecté par un appel."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lire le numéro de téléphone"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permet à l\'application d\'accéder au numéro de téléphone de l\'appareil."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"empêcher la tablette de passer en mode veille"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"empêcher le téléviseur de passer en mode veille"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"empêcher le téléphone de passer en mode veille"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Volume"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume des notifications"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Sonnerie par défaut"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Défaut (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Aucune"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Sonneries"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Sons d\'alarme"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Sons de notification"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Inconnu"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Réseau Wi-Fi à proximité</item>
<item quantity="other">Réseaux Wi-Fi à proximité</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permet à une application d\'accéder aux sessions d\'installation. Cela lui permet de consulter les détails relatifs à l\'installation des paquets actifs."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"demander l\'installation de paquets"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permet à une application de demander l\'installation de paquets."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"demander d\'ignorer les optimisations de la pile"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Permet à une application de demander la permission d\'ignorer les optimisations de la pile."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Appuyer deux fois pour régler le zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Impossible d\'ajouter le widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Aller"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Sélectionnez une année"</string>
<string name="deleted_key" msgid="7659477886625566590">"« <xliff:g id="KEY">%1$s</xliff:g> » a été supprimé"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (travail)"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2e <xliff:g id="LABEL">%1$s</xliff:g> professionnel(le)"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3e <xliff:g id="LABEL">%1$s</xliff:g> professionnel(le)"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Pour annuler l\'épinglage de cet écran, maintenez enfoncée la touche Retour."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"L\'application est épinglée : l\'annulation de l\'épinglage n\'est pas autorisée sur cet appareil."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Écran épinglé"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Réinitialiser maintenant"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Désactivé : <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Conférence téléphonique"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Infobulle"</string>
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 5b21dd4..e9a4681 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permet à l\'application d\'utiliser le service IMS pour passer des appels sans votre intervention."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"Voir l\'état et l\'identité du téléphone"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permet à l\'application d\'accéder aux fonctionnalités téléphoniques de l\'appareil. Cette autorisation permet à l\'application de déterminer le numéro de téléphone et les identifiants de l\'appareil, si un appel est actif et le numéro distant connecté par un appel."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lire le numéro de téléphone"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permet à l\'application d\'accéder au numéro de téléphone de l\'appareil."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"empêcher la tablette de passer en mode veille"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"empêcher l\'activation du mode veille sur le téléviseur"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"empêcher le téléphone de passer en mode veille"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Volume"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume des notifications"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Sonnerie par défaut"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Sonnerie par défaut (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Aucune"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Sonneries"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Sons de l\'alarme"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Sons de notification"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Inconnue"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Réseau Wi-Fi disponible</item>
<item quantity="other">Réseaux Wi-Fi disponibles</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permet à une application d\'accéder aux sessions d\'installation. Cela lui permet de consulter les détails relatifs à l\'installation des packages actifs."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"demander l\'installation de packages"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permet à une application de demander l\'installation de packages."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"demander à ignorer les optimisations de batterie"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Autorise une application à demander l\'autorisation d\'ignorer les optimisations de batterie pour cette application."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Appuyer deux fois pour régler le zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Impossible d\'ajouter le widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"OK"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Sélectionner une année"</string>
<string name="deleted_key" msgid="7659477886625566590">"\"<xliff:g id="KEY">%1$s</xliff:g>\" supprimé"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (travail)"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2e <xliff:g id="LABEL">%1$s</xliff:g> professionnelle"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3e <xliff:g id="LABEL">%1$s</xliff:g> professionnelle"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Pour annuler l\'épinglage, appuyez de manière prolongée sur \"Retour\"."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"L\'application est épinglée. L\'annulation de l\'épinglage n\'est pas autorisée sur cet appareil."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Écran épinglé."</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Réinitialiser maintenant"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Élément \"<xliff:g id="LABEL">%1$s</xliff:g>\" désactivé"</string>
<string name="conference_call" msgid="3751093130790472426">"Conférence téléphonique"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Info-bulle"</string>
</resources>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 10a7647..10ab490 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite que a aplicación use o servizo de IMS para facer chamadas sen a túa intervención."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ler o estado e a identidade do teléfono"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite á aplicación acceder ás funcións de teléfono do dispositivo. Con este permiso a aplicación pode determinar o número de teléfono e os ID do dispositivo, se unha chamada está activa e o número remoto conectado mediante unha chamada."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ler número de teléfono"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permite que a aplicación acceda ao número de teléfono do dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"evitar que a tableta entre en modo de inactividade"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"evitar que a televisión entre en modo de suspensión"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"evitar que o teléfono entre en modo de suspensión"</string>
@@ -551,7 +553,7 @@
<item msgid="7897544654242874543">"Traballo"</item>
<item msgid="1103601433382158155">"Fax do traballo"</item>
<item msgid="1735177144948329370">"Fax particular"</item>
- <item msgid="603878674477207394">"Busca"</item>
+ <item msgid="603878674477207394">"Buscapersoas"</item>
<item msgid="1650824275177931637">"Outros"</item>
<item msgid="9192514806975898961">"Personalizado"</item>
</string-array>
@@ -594,7 +596,7 @@
<string name="phoneTypeWork" msgid="8863939667059911633">"Traballo"</string>
<string name="phoneTypeFaxWork" msgid="3517792160008890912">"Fax do traballo"</string>
<string name="phoneTypeFaxHome" msgid="2067265972322971467">"Fax particular"</string>
- <string name="phoneTypePager" msgid="7582359955394921732">"Busca"</string>
+ <string name="phoneTypePager" msgid="7582359955394921732">"Buscapersoas"</string>
<string name="phoneTypeOther" msgid="1544425847868765990">"Outro"</string>
<string name="phoneTypeCallback" msgid="2712175203065678206">"Devolver chamada"</string>
<string name="phoneTypeCar" msgid="8738360689616716982">"Coche"</string>
@@ -606,7 +608,7 @@
<string name="phoneTypeTelex" msgid="3367879952476250512">"Télex"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
<string name="phoneTypeWorkMobile" msgid="1311426989184065709">"Móbil do traballo"</string>
- <string name="phoneTypeWorkPager" msgid="649938731231157056">"Busca do traballo"</string>
+ <string name="phoneTypeWorkPager" msgid="649938731231157056">"Buscapersoas do traballo"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"Asistente"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
<string name="eventTypeCustom" msgid="7837586198458073404">"Personalizados"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que unha aplicación consulte as sesións de instalación. Desta forma, pode ver os detalles acerca das instalacións de paquetes activas."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar instalación de paquetes"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite a unha aplicación solicitar a instalación dos paquetes."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"solicitar ignorar optimizacións da batería"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Permite que unha aplicación solicite permiso para ignorar optimizacións da batería para esa aplicación."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Toca dúas veces para controlar o zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Non se puido engadir o widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ir"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Seleccionar ano"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminado"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2.º <xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3.º <xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Para soltar a pantalla, mantén premido Volver."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"A aplicación está fixada: non se permite soltala neste dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantalla fixada"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Restablecer agora"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Desactivouse <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Conferencia telefónica"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Ventá emerxente do cadro de información"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Cadro de información"</string>
</resources>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 9a7d432..e648ba5 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"તમારા હસ્તક્ષેપ વગર કૉલ્સ કરવા માટે IMS સેવાનો ઉપયોગ કરવાની એપ્લિકેશનને મંજૂરી આપે છે."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ફોન સ્થિતિ અને ઓળખ વાંચો"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"એપ્લિકેશનને ફોન સુવિધાઓને ઍક્સેસ કરવાની મંજૂરી આપે છે. આ પરવાનગી એપ્લિકેશનને ફોન નંબર અને ઉપકરણ ID, કૉલ સક્રિય છે અને કોઈ કૉલ દ્વારા કનેક્ટ થયેલ રિમોટ નંબર નિર્ધારિત કરવાની મંજૂરી આપે છે."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ફોન નંબર વાંચવા"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"ઍપ્લિકેશનને ઉપકરણના ફોન નંબરને ઍક્સેસ કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ટેબ્લેટને નિષ્ક્રિય થતું અટકાવો"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ટીવીને નિષ્ક્રિય થતો અટકાવો"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ફોનને નિષ્ક્રિય થતો અટકાવો"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"એપ્લિકેશનને ઇન્સ્ટોલ સત્રોને વાંચવાની મંજૂરી આપે છે. આ તેને સક્રિય પૅકેજ ઇન્સ્ટોલેશન્સ વિશે વિગતો જોવાની મંજૂરી આપે છે."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"પૅકેજેસ ઇન્સ્ટૉલ કરવાની વિનંતી કરો"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"એપ્લિકેશનને પૅકેજેસના ઇન્સ્ટોલેશનની વિનંતી કરવાની મંજૂરી આપો."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"બૅટરી ઓપ્ટિમાઇઝેશન્સને અવગણવા માટે પૂછો"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"ઍપ્લિકેશનને તે ઍપ્લિકેશન માટે બૅટરી ઓપ્ટિમાઇઝેશન્સને અવગણવાની પરવાનગી આપવા માટે પૂછવાની મંજૂરી આપે છે."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ઝૂમ નિયંત્રણ માટે બેવાર ટૅપ કરો"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"વિજેટ ઉમેરી શકાયું નથી."</string>
<string name="ime_action_go" msgid="8320845651737369027">"જાઓ"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"વર્ષ પસંદ કરો"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> કાઢી નાખી"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"કાર્યાલય <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2જું કાર્ય <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3જું કાર્ય <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"આ સ્ક્રીનને અનપિન કરવા માટે, પાછળને ટચ કરીને પકડી રાખો."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ઍપ્લિકેશન પિન કરેલ છે. આ ઉપકરણ પર અનપિન કરવાની મંજૂરી નથી."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"સ્ક્રીન પિન કરી"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"હમણાં ફરીથી સેટ કરો"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> અક્ષમ કર્યું"</string>
<string name="conference_call" msgid="3751093130790472426">"કોન્ફરન્સ કૉલ"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"ટૂલટિપ પોપઅપ"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ટૂલટિપ"</string>
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index c46102b..6cd8fd94 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"आपके हस्तक्षेप के बिना कॉल करने के लिए, ऐप को IMS सेवा का उपयोग करने देती है."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"फ़ोन की स्थिति और पहचान पढ़ें"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ऐप्स को डिवाइस की फ़ोन सुविधाओं तक पहुंचने देता है. यह अनुमति ऐप्स को फ़ोन नंबर और डिवाइस आईडी, कॉल सक्रिय है या नहीं, और कॉल द्वारा कनेक्ट किया गया दूरस्थ नंबर निर्धारित करने देती है."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"फ़ोन नंबर पढ़ें"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"ऐप्लिकेशन को डिवाइस का फ़ोन नंबर एक्सेस करने देती है."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"टेबलेट को निष्क्रिय होने से रोकें"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"टीवी को निष्क्रिय होने से रोकना"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"फ़ोन को निष्क्रिय होने से रोकें"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"मीडिया वॉल्यूम"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"नोटिफिकेशन वॉल्यूम"</string>
<string name="ringtone_default" msgid="3789758980357696936">"डिफ़ॉल्ट रिंगटोन"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"डिफ़ॉल्ट (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"कोई नहीं"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"रिंगटोन"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"अलार्म ध्वनियां"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"नोटिफ़िकेशन ध्वनि"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"अज्ञात"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">वाई-फ़ाई नेटवर्क उपलब्ध</item>
<item quantity="other">वाई-फ़ाई नेटवर्क उपलब्ध</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ऐप्लिकेशन को इंस्टॉल सत्रों को पढ़ने देती है. इससे उसे सक्रिय पैकेज इंस्टॉलेशन के बारे में विवरण देखने की अनुमति मिल जाती है."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"पैकेज इंस्टॉल करने का अनुरोध करें"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"किसी ऐप्लिकेशन को पैकेज इंस्टॉल करने के अनुरोध की अनुमति देता है."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"बैटरी ऑप्टिमाइज़ेशन पर ध्यान ना देने के लिए पूछें"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"किसी ऐप्लिकेशन को उस ऐप्लिकेशन के लिए बैटरी ऑप्टिमाइज़ेशन पर ध्यान ना देने की अनुमति के लिए पूछने देता है."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ज़ूम नियंत्रण के लिए दो बार टैप करें"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"विजेट नहीं जोड़ा जा सका."</string>
<string name="ime_action_go" msgid="8320845651737369027">"जाएं"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"वर्ष चुनें"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> को हटा दिया गया"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्यस्थल का <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"दूसरा कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"तीसरा कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"इस स्क्रीन को अनपिन करने के लिए, वापस जाएं को स्पर्श करके रखें."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ऐप पिन किया गया है: इस डिवाइस पर अनपिन करने की अनुमति नहीं है."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"स्क्रीन पिन की गई"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"अभी रीसेट करें"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"अक्षम <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"कॉन्फ़्रेंस कॉल"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"टूलटिप"</string>
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index fa593acd..cd4ef80 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -380,6 +380,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Omogućuje aplikaciji upotrebu usluge izravnih poruka za uspostavljanje poziva bez vaše intervencije."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"čitanje statusa i identiteta telefona"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Aplikaciji omogućuje pristup telefonskim značajkama uređaja. Ta dozvola aplikaciji omogućuje utvrđivanje telefonskog broja i ID-ova uređaja, je li poziv aktivan te udaljeni broj koji je povezan pozivom."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"čitati telefonski broj"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Omogućuje aplikaciji da pristupi telefonskom broju uređaja."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"spriječi mirovanje tabletnog uređaja"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"sprječavanje mirovanja televizora"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"sprečava telefon da prijeđe u stanje mirovanja"</string>
@@ -646,7 +648,7 @@
<string name="relationTypeAssistant" msgid="6274334825195379076">"Pomoćnik"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"Brat"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"Dijete"</string>
- <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Partner u kućan."</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Vanbračni partner"</string>
<string name="relationTypeFather" msgid="5228034687082050725">"Otac"</string>
<string name="relationTypeFriend" msgid="7313106762483391262">"Prijatelj"</string>
<string name="relationTypeManager" msgid="6365677861610137895">"Voditelj"</string>
@@ -1235,6 +1237,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Omogućuje aplikaciji čitanje sesija instaliranja. Aplikacija može vidjeti pojedinosti o aktivnim instaliranjima paketa."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"zahtijevati instaliranje paketa"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Aplikaciji omogućuje zahtijevanje instaliranja paketa."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"tražiti zanemarivanje optimizacija baterije"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Aplikaciji omogućuje da traži dopuštenje za zanemarivanje optimizacija baterije za tu aplikaciju."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Dvaput dotaknite za upravljanje zumiranjem"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget nije moguće dodati."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Idi"</string>
@@ -1587,10 +1591,8 @@
<string name="select_year" msgid="7952052866994196170">"Odaberite godinu"</string>
<string name="deleted_key" msgid="7659477886625566590">"Izbrisan je broj <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Da biste otkvačili ovaj zaslon, dodirnite i zadržite Natrag."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacija je prikvačena: otkvačivanje nije dopušteno na tom uređaju."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Zaslon je pričvršćen"</string>
@@ -1719,5 +1721,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Vrati na zadano sada"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> – onemogućeno"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferencijski poziv"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Skočni prozor opisa"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Opis"</string>
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index d21e47e..f06a006 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Az alkalmazás az IMS-szolgáltatást használhatja híváskezdeményezéshez az Ön közbeavatkozása nélkül."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"telefonállapot és azonosító olvasása"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Lehetővé teszi az alkalmazás számára, hogy hozzáférjen az eszköz telefonálási funkcióihoz. Az engedéllyel rendelkező alkalmazás meghatározhatja a telefonszámot és eszközazonosítókat, hogy egy hívás aktív-e, valamint híváskor a másik fél telefonszámát."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"telefonszám beolvasása"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Engedélyezi az alkalmazás számára, hogy hozzáférjen az eszköz telefonszámához."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"táblagép alvás üzemmódjának megakadályozása"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"a tévé alvó üzemmódba való lépésének megakadályozása"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"telefon alvó üzemmódjának megakadályozása"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Engedélyezi az alkalmazásnak a telepítési munkamenetek olvasását. Ezáltal részleteket kaphat az egyes csomagok éppen folyamatban lévő telepítéséről."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"telepítőcsomagok kérése"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Lehetővé teszi az alkalmazás számára csomagok telepítésének kérését."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"Akkumulátoroptimalizálási beállítások mellőzésének kérése"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Az alkalmazás engedélyt kérhet az akkumulátoroptimalizálási beállítások mellőzésére."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Érintse meg kétszer a nagyítás beállításához"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nem sikerült hozzáadni a modult."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ugrás"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Válassza ki az évet"</string>
<string name="deleted_key" msgid="7659477886625566590">"A(z) <xliff:g id="KEY">%1$s</xliff:g> érték törölve"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"A képernyő rögzítésének feloldásához tartsa lenyomva a Vissza lehetőséget."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Az alkalmazás rögzítve van: a rögzítés feloldása nem engedélyezett ezen az eszközön."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Képernyő rögzítve"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Visszaállítás most"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"A(z) <xliff:g id="LABEL">%1$s</xliff:g> letiltva"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferenciahívás"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Elemleíró előugró ablak"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Elemleírás"</string>
</resources>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 10072a2..25f3213 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Թույլ է տալիս հավելվածին IMS ծառայության միջոցով կատարել զանգեր՝ առանց ձեր միջամտության:"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"կարդալ հեռախոսի կարգավիճակը և ինքնությունը"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Թույլ է տալիս հավելվածին օգտագործել սարքի հեռախոսային գործիքները: Այս թույլտվությունը հավելվածին հնարավորություն է տալիս որոշել հեռախոսահամարը և սարքի ID-ները, արդյոք զանգը ակտիվ է և միացված զանգի հեռակա հեռախոսահամարը:"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"կարդալ հեռախոսահամարը"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Հավելվածին թույլ է տալիս օգտագործել սարքի հեռախոսահամարը:"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"զերծ պահել պլանշետը քնելուց"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"թույլ չտալ հեռուստացույցին մտնել քնի ռեժիմ"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"կանխել հեռախոսի քնի ռեժիմին անցնելը"</string>
@@ -598,7 +600,7 @@
<string name="phoneTypeOther" msgid="1544425847868765990">"Այլ"</string>
<string name="phoneTypeCallback" msgid="2712175203065678206">"Ետզանգ"</string>
<string name="phoneTypeCar" msgid="8738360689616716982">"Մեքենա"</string>
- <string name="phoneTypeCompanyMain" msgid="540434356461478916">"Ընկերության գլխավոր"</string>
+ <string name="phoneTypeCompanyMain" msgid="540434356461478916">"Ընկերության հիմնական"</string>
<string name="phoneTypeIsdn" msgid="8022453193171370337">"ISDN"</string>
<string name="phoneTypeMain" msgid="6766137010628326916">"Հիմնական"</string>
<string name="phoneTypeOtherFax" msgid="8587657145072446565">"Այլ ֆաքս"</string>
@@ -643,14 +645,14 @@
<string name="relationTypeAssistant" msgid="6274334825195379076">"Օգնական"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"Եղբայր"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"Երեխա"</string>
- <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Տեղական գործընկեր"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Կենակից"</string>
<string name="relationTypeFather" msgid="5228034687082050725">"Հայր"</string>
<string name="relationTypeFriend" msgid="7313106762483391262">"Ընկեր"</string>
<string name="relationTypeManager" msgid="6365677861610137895">"Կառավարիչ"</string>
<string name="relationTypeMother" msgid="4578571352962758304">"Մայր"</string>
<string name="relationTypeParent" msgid="4755635567562925226">"Ծնող"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"Գործընկեր"</string>
- <string name="relationTypeReferredBy" msgid="101573059844135524">"Հղված է"</string>
+ <string name="relationTypeReferredBy" msgid="101573059844135524">"Հանձնարարված"</string>
<string name="relationTypeRelative" msgid="1799819930085610271">"Բարեկամ"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"Քույր"</string>
<string name="relationTypeSpouse" msgid="394136939428698117">"Ամուսին"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Մեդիա ձայնի բարձրություն"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Ծանուցումների ձայնի ուժգնությունը"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Կանխադրված զանգերանգ"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Կանխադրված (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Ոչ մեկը"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Զանգերանգներ"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Զարթուցիչի զանգերանգներ"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Ծանուցման զանգերանգներ"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Անհայտ է"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Հասանելի են Wi-Fi ցանցեր</item>
<item quantity="other">Հասանելի են Wi-Fi ցանցեր</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Ծրագրին թույլ է տալիս կարդալ տեղադրման աշխատաշրջանները: Սա թույլ է տալիս տեղեկանալ փաթեթների ակտիվ տեղադրումների մանրամասներին:"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"պահանջել տեղադրման փաթեթներ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Թույլ է տալիս հավելվածին պահանջել փաթեթների տեղադրումը:"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"հայցել մարտկոցի օպտիմալացումն անտեսելու թույլտվություն"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Հավելվածին հնարավորություն է տալիս հայցելու թույլտվություն՝ տվյալ հավելվածի համար մարտկոցի օպտիմալացումն անտեսելու համար:"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Հպեք երկու անգամ` խոշորացման վերահսկման համար"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Չհաջողվեց վիջեթ ավելացնել:"</string>
<string name="ime_action_go" msgid="8320845651737369027">"Առաջ"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Ընտրեք տարին"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> թիվը ջնջված է"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Աշխատանքային <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-րդ աշխատանք <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-րդ աշխատանք <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Այս էկրանն ապամրացնելու համար հպեք և պահեք Հետ կոճակը:"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Հավելվածն ամրացված է: Ապամրացումն այս սարքում չի թույլատրվում:"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Էկրանն ամրացված է"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Վերակայել հիմա"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Անջատած <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Կոնֆերանս զանգ"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Հուշակ"</string>
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 29d820e..944583d 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Memungkinkan aplikasi menggunakan layanan IMS untuk melakukan panggilan tanpa campur tangan Anda."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"baca identitas dan status ponsel"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Memungkinkan aplikasi mengakses fitur telepon perangkat. Izin ini memungkinkan aplikasi menentukan nomor telepon dan ID perangkat, apakah suatu panggilan aktif atau tidak, dan nomor jarak jauh yang tersambung oleh sebuah panggilan."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"baca nomor telepon"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Mengizinkan aplikasi mengakses nomor telepon perangkat ini."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"cegah tablet dari tidur"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"cegah agar TV tidak tidur"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"mencegah ponsel menjadi tidak aktif"</string>
@@ -988,7 +990,7 @@
<string name="whichImageCaptureApplicationLabel" msgid="6390303445371527066">"Jepret gambar"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Gunakan secara default untuk tindakan ini."</string>
<string name="use_a_different_app" msgid="8134926230585710243">"Gunakan aplikasi yang berbeda"</string>
- <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Menghapus default di Setelan sistem > Apl > Terunduh."</string>
+ <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Menghapus default di Setelan sistem > Apl > Terdownload."</string>
<string name="chooseActivity" msgid="7486876147751803333">"Pilih tindakan"</string>
<string name="chooseUsbActivity" msgid="6894748416073583509">"Pilih apl untuk perangkat USB"</string>
<string name="noApplications" msgid="2991814273936504689">"Tidak ada apl yang dapat melakukan tindakan ini."</string>
@@ -1016,7 +1018,7 @@
<string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> telah diluncurkan aslinya."</string>
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Skala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Selalu tampilkan"</string>
- <string name="screen_compat_mode_hint" msgid="1064524084543304459">"Aktifkan kembali dialog ini di Setelan sistem > Apl > Terunduh."</string>
+ <string name="screen_compat_mode_hint" msgid="1064524084543304459">"Aktifkan kembali dialog ini di Setelan sistem > Apl > Terdownload."</string>
<string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak mendukung setelan Ukuran layar saat ini dan dapat menunjukkan perilaku yang tak diharapkan."</string>
<string name="unsupported_display_size_show" msgid="7969129195360353041">"Selalu tampilkan"</string>
<string name="smv_application" msgid="3307209192155442829">"Apl <xliff:g id="APPLICATION">%1$s</xliff:g> (proses <xliff:g id="PROCESS">%2$s</xliff:g>) telah melanggar kebijakan StrictMode yang diberlakukannya sendiri."</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Memungkinkan aplikasi membaca sesi pemasangan. Tindakan ini memungkinkannya melihat detail tentang pemasangan paket aktif."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"minta pasang paket"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Mengizinkan aplikasi meminta pemasangan paket."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"meminta mengabaikan pengoptimalan baterai"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Mengizinkan aplikasi meminta izin untuk mengabaikan pengoptimalan baterai bagi aplikasi tersebut."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Ketuk dua kali untuk kontrol perbesar/perkecil"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Tidak dapat menambahkan widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Buka"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Pilih tahun"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> dihapus"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Kantor <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Upaya ke-2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Upaya ke-3 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Untuk melepas pin layar ini, sentuh & tahan tombol Kembali."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Pin dipasang ke aplikasi. Melepas pin tidak diizinkan di perangkat ini."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Layar disematkan"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Setel ulang sekarang"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> dinonaktifkan"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferensi Telepon"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Munculan Keterangan Alat"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Keterangan alat"</string>
</resources>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 655c521..9986dd8 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Leyfir forriti að nota IMS-þjónustu til að hringja án inngrips frá þér."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lesa stöðu símans og auðkenni"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Leyfir forriti að fá aðgang að símaeiginleikum tækisins. Þessi heimild gerir forritinu kleift að komast að símanúmeri og auðkennum tækisins, hvort símtal er í gangi og símanúmeri viðmælanda í símtali."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lesa símanúmer"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Veitir forritinu aðgang að símanúmeri tækisins."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"koma í veg fyrir að spjaldtölvan fari í biðstöðu"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"koma í veg fyrir að sjónvarpið fari í biðstöðu"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"koma í veg fyrir að síminn fari í biðstöðu"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Leyfir forriti að lesa uppsetningarlotur. Þetta gerir því kleift að sjá upplýsingar um virkar pakkauppsetningar."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"fara fram á uppsetningu pakka"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Leyfir forriti að fara fram á uppsetningu pakka."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"biðja um að hunsa rafhlöðusparnað"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Gerir forriti kleift að biðja um heimild til að hunsa rafhlöðusparnað fyrir forritið."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Ýttu tvisvar til að opna aðdráttarstýringar"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Ekki tókst að bæta græju við."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Áfram"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Veldu ár"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eytt"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu (2)"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu (3)"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Til að taka lásinn af þessari skjámynd skaltu halda inni bakkhnappinum."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Forritið er fest: Ekki er hægt að losa forrit í þessu tæki."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skjár festur"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Endurstilla núna"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Slökkt <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Símafundur"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Ábendingarsprettigluggi"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Ábending"</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 446e367..4496dfe 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Consente all\'app di utilizzare il servizio IMS per fare chiamate senza il tuo intervento."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lettura stato e identità telefono"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Consente all\'applicazione di accedere alle funzioni telefoniche del dispositivo. Questa autorizzazione consente all\'applicazione di determinare il numero di telefono e gli ID dei dispositivi, se una chiamata è attiva e il numero remoto connesso da una chiamata."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"leggi il numero di telefono"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Consente all\'app di accedere al numero di telefono del dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"disattivazione stand-by del tablet"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"divieto di attivazione della modalità di sospensione della TV"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"disattivazione stand-by del telefono"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Consente a un\'applicazione di leggere le sessioni di installazione. L\'app può conoscere i dettagli sulle installazioni di pacchetti attive."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"richiesta di pacchetti di installazione"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Consente a un\'applicazione di richiedere l\'installazione di pacchetti."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"chiedi di ignorare le ottimizzazioni della batteria"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Consente a un\'app di chiedere l\'autorizzazione a ignorare le ottimizzazioni della batteria per quell\'app."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tocca due volte per il comando dello zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Aggiunta del widget non riuscita."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Vai"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Seleziona anno"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminato"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> lavoro"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> di lavoro (2°)"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> di lavoro (3°)"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Per sbloccare questa schermata tieni premuta l\'opzione Indietro."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"L\'app è bloccata. Su questo dispositivo non è consentito lo sblocco."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Schermata bloccata"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Ripristina ora"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Widget <xliff:g id="LABEL">%1$s</xliff:g> disattivato"</string>
<string name="conference_call" msgid="3751093130790472426">"Audioconferenza"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Popup descrizione comando"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Descrizione comando"</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 1881ae4..465f5e9 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"מאפשר לאפליקציה להשתמש בשירות ה-IMS לביצוע שיחות ללא התערבותך."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"קריאת הסטטוס והזהות של הטלפון"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"מאפשר לאפליקציה לגשת לתכונות הטלפון של המכשיר. אישור זה מתיר לאפליקציה לגלות את מספר הטלפון ואת זיהויי המכשיר, האם שיחה פעילה ואת המספר המרוחק המחובר באמצעות שיחה."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"קריאת מספר טלפון"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"מאפשרת לאפליקציה לגשת למספר הטלפון של המכשיר."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"מנע מהטאבלט לעבור למצב שינה"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"מניעת מעבר למצב שינה בטלוויזיה"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"מניעת מעבר הטלפון למצב שינה"</string>
@@ -599,7 +601,7 @@
<string name="phoneTypeMobile" msgid="6501463557754751037">"נייד"</string>
<string name="phoneTypeWork" msgid="8863939667059911633">"עבודה"</string>
<string name="phoneTypeFaxWork" msgid="3517792160008890912">"פקס בעבודה"</string>
- <string name="phoneTypeFaxHome" msgid="2067265972322971467">"מס\' פקס בבית"</string>
+ <string name="phoneTypeFaxHome" msgid="2067265972322971467">"פקס בבית"</string>
<string name="phoneTypePager" msgid="7582359955394921732">"זימונית"</string>
<string name="phoneTypeOther" msgid="1544425847868765990">"אחר"</string>
<string name="phoneTypeCallback" msgid="2712175203065678206">"התקשרות חזרה"</string>
@@ -612,7 +614,7 @@
<string name="phoneTypeTelex" msgid="3367879952476250512">"טלקס"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
<string name="phoneTypeWorkMobile" msgid="1311426989184065709">"נייד של העבודה"</string>
- <string name="phoneTypeWorkPager" msgid="649938731231157056">"איתורית של העבודה"</string>
+ <string name="phoneTypeWorkPager" msgid="649938731231157056">"זימונית מהעבודה"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"מסייע"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
<string name="eventTypeCustom" msgid="7837586198458073404">"מותאם אישית"</string>
@@ -1105,16 +1107,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"עוצמת קול של מדיה"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"עוצמת קול של התראות"</string>
<string name="ringtone_default" msgid="3789758980357696936">"רינגטון ברירת מחדל"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ברירת מחדל (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ללא"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"רינגטונים"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"צלילי התראה"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"צלילי הודעה"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"לא ידוע"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="two">יש רשתות Wi-Fi זמינות</item>
<item quantity="many">יש רשתות Wi-Fi זמינות</item>
@@ -1264,6 +1262,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"מאפשר לאפליקציה לקרוא הפעלות התקנה. הרשאה זו מאפשרת לה לראות פרטים על התקנות פעילות של חבילות."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"בקשה להתקנת חבילות"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"מתיר לאפליקציה לבקש התקנה של חבילות."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"בקשה להתעלם מאופטימיזציות של הסוללה"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"מאפשר לאפליקציה לבקש רשות להתעלם מאופטימיזציות של הסוללה לאפליקציה הזו."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"הקש פעמיים לבקרת מרחק מתצוגה"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"לא ניתן להוסיף widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"התחל"</string>
@@ -1618,10 +1618,8 @@
<string name="select_year" msgid="7952052866994196170">"בחר שנה"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> נמחק"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"עבודה <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> שני בעבודה"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> שלישי בעבודה"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"כדי לבטל את הצמדת המסך הזה, לחץ לחיצה ממושכת על הלחצן \'הקודם\'."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"האפליקציה מוצמדת: ביטול ההצמדה אסור במכשיר הזה."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"המסך מוצמד"</string>
@@ -1759,6 +1757,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"אפס עכשיו"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> הושבת"</string>
<string name="conference_call" msgid="3751093130790472426">"שיחת ועידה"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"הסבר קצר"</string>
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index fdfb890..ee3ff99 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"IMSサービスがユーザー操作なしで電話をかけることをアプリに許可します。"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"端末情報と ID の読み取り"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"端末の電話機能へのアクセスをアプリに許可します。これにより、電話番号、端末ID、通話中かどうか、通話相手の電話番号をアプリから特定できるようになります。"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"電話番号の読み取り"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"端末の電話番号へのアクセスをアプリに許可します。"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"タブレットのスリープを無効化"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"テレビのスリープを無効化"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"端末のスリープを無効にする"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"メディアの音量"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
<string name="ringtone_default" msgid="3789758980357696936">"プリセット着信音"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"デフォルト(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"なし"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"着信音"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"アラーム音"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"通知音"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"不明"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">複数のWi-Fiネットワークが利用できます</item>
<item quantity="one">Wi-Fiネットワークが利用できます</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"インストールセッションの読み取りをアプリに許可します。これにより、アプリはアクティブパッケージのインストールに関する詳細情報を参照できるようになります。"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"インストールパッケージのリクエスト"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"パッケージのインストールをリクエストすることをアプリケーションに許可します。"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"電池の最適化を無視するかどうかの確認"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"電池の最適化の無視についてアプリが確認することを許可します。"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ダブルタップでズームします"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ウィジェットを追加できませんでした。"</string>
<string name="ime_action_go" msgid="8320845651737369027">"移動"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"年を選択"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g>を削除しました"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"仕事の<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2 番目の仕事用<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3 番目の仕事用<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"この画面の固定を解除するには [戻る] を押し続けます。"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"アプリは固定されています。この端末では固定を解除できません。"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"画面を固定しました"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"今すぐリセット"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"停止済みの「<xliff:g id="LABEL">%1$s</xliff:g>」"</string>
<string name="conference_call" msgid="3751093130790472426">"グループ通話"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ツールチップ"</string>
</resources>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 56f0a62..79fc4638 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"აპს შეეძლება, გამოიყენოს IMS სერვისი ზარების თქვენი ჩარევის გარეშე განსახორციელებლად."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ტელეფონის სტატუსისა და იდენტობის წაკითხვა"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"აპს შეეძლება ჰქონდეს წვდომა მოწყობილობის სატელეფონო ფუნქციებზე. აპმა მსგავსი უფლებით შეძლებს დაადგინოს ტელეფონის ნომერი, მისი სერიული გამოცემა, აქტიური ზარი, დაკავშირებული ნომერი და მსგავსი."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ტელეფონის ნომრის წაკითხვა"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"აპს მოწყობილობის ტელეფონის ნომერზე წვდომის საშუალებას მისცემს."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"დაიცავით ტაბლეტი დაძინებისგან"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ტელევიზორის დაცვა დაძინებისაგან"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ტელეფონის ძილის რეჟიმში გადასვლის აღკვეთა"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"საშუალებას აძლევს აპლიკაციას წაიკითხოს ინსტალაციის სესიები. ამით მას საშუალება აქვს იხილოს პაკეტის აქტიური ინსტალაციები."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"პაკეტების ინსტალაციის მოთხოვნა"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"აპლიკაციას შეეძლება მოითხოვოს პაკეტების ინსტალაცია."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ბატარეის ოპტიმიზაციის იგნორირების მოთხოვნა"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"საშუალებას მისცემს აპს, მოითხოვოს მასთან დაკავშირებული ბატარეის ოპტიმიზაციის იგნორირების ნებართვა."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"მასშტაბის ცვლილებისთვის შეეხეთ ორჯერ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ვერ დაემატა ვიჯეტი."</string>
<string name="ime_action_go" msgid="8320845651737369027">"გადასვლა"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"აირჩიეთ წელი"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> წაიშალა"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"მე-2 სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"მე-3 სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ამ ეკრანის ჩამაგრების მოსახსნელად, ხანგრძლივად შეეხეთ ღილაკს „უკან“."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"აპი მიმაგრებულია: მიმაგრების მოხსნა არ არის ნებადართული ამ მოწყობილობაზე."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ეკრანი დაფიქსირდა"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ახლავე გადაყენება"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"გათიშული <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"საკონფერენციო ზარი"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"მინიშნების კონტექსტური სარკმელი"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"მინიშნება"</string>
</resources>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 51d1dcc..bbb34cb 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Сіздің қатысуыңызсыз қоңыраулар соғу үшін қолданбаға IMS қызметін пайдалануға рұқсат етеді."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"телефон күйін оқу немесе анықтау"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Қолданбаға құрылғыдағы телефон функцияларына кіру мүмкіндігін береді. Бұл рұқсат қолданбаға телефон нөмірі, құрылғы жеке анықтағышы, қоңырау белсенділігі және сол қоңырауға байланысты қашықтағы нөмірді анықтау мүмкіндігін береді."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"телефон нөмірін оқу"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Қолданбаға құрылғының телефон нөмірін алуға рұқсат береді."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"планшетті ұйқыдан бөгеу"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ТД ұйықтауын болдырмау"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"телефонды ұйқыдан бөгеу"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Meдиа дыбысының қаттылығы"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Хабар дыбысының қаттылығы"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Әдепкі рингтон"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Әдепкі (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Ешқандай"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Қоңырау әуендері"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Дабыл сигналдары"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Хабарландыру сигналдары"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Белгісіз"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Wi-Fi желілері қол жетімді</item>
<item quantity="one">Wi-Fi желісі қол жетімді</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Қолданбаға орнату сеанстарын оқуға рұқсат етеді. Бұл оған белсенді бума орнатулары туралы мәліметтерді көруге рұқсат етеді."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"орнату бумаларын сұрау"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Қолданбаның бумаларды орнатуға рұқсат сұрауына мүмкіндік береді."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"батареяны оңтайландыру әрекетін елемеуді сұрау"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Қолданба батареяны оңтайландыру әрекетін елемеуді сұрай алады."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Масштабтау параметрін басқару үшін екі рет түртіңіз"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Виджетті қосу."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Өту"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Жыл таңдау"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> жойылды"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Жұмыс <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-ші жұмыс профилі (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-ші жұмыс профилі (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Осы экранды босату үшін \"Артқа\" түймесін басып тұрыңыз."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Бағдарлама белгіленді: Бұл құрылғыда белгіні алуға рұқсат берілмейді."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Экран түйрелді"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Қазір бастапқы күйге қайтару"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> өшірулі"</string>
<string name="conference_call" msgid="3751093130790472426">"Конференциялық қоңырау"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Қалқыма сөзкөмек"</string>
</resources>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index aa6cb77..1566c92 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"អនុញ្ញាតឲ្យកម្មវិធីនេះប្រើសេវាកម្ម IMS ដើម្បីធ្វើការហៅដោយគ្មានការអន្តរាគមន៍ពីអ្នក។"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"អានស្ថានភាព និងអត្តសញ្ញាណទូរស័ព្ទ"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ឲ្យកម្មវិធីចូលដំណើរការលក្ខណៈទូរស័ព្ទនៃឧបករណ៍។ សិទ្ធិនេះឲ្យកម្មវិធីកំណត់លេខទូរស័ព្ទ និងលេខសម្គាល់ឧបករណ៍ ថាតើការហៅសកម្ម និងលេខពីចម្ងាយបានភ្ជាប់ដោយការហៅ។"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"អានលេខទូរសព្ទ"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"អនុញ្ញាតឲ្យកម្មវិធីនេះចូលប្រើលេខទូរសព្ទរបស់ឧបករណ៍នេះ។"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ការពារកុំព្យូទ័របន្ទះមិនឲ្យដេក"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"បង្ការទូរទស្សន៍ពីការបិទពន្លឺ"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ការពារទូរស័ព្ទមិនឲ្យដេក"</string>
@@ -605,9 +607,9 @@
<string name="phoneTypeRadio" msgid="4093738079908667513">"វិទ្យុ"</string>
<string name="phoneTypeTelex" msgid="3367879952476250512">"ទូរសារ"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
- <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"ទូរស័ព្ទកន្លែងធ្វើការ"</string>
+ <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"ទូរសព្ទកន្លែងធ្វើការ"</string>
<string name="phoneTypeWorkPager" msgid="649938731231157056">"ភេយ័រកន្លែងធ្វើការ"</string>
- <string name="phoneTypeAssistant" msgid="5596772636128562884">"អ្នកជំនួយការ"</string>
+ <string name="phoneTypeAssistant" msgid="5596772636128562884">"ជំនួយការ"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"សារ MMS"</string>
<string name="eventTypeCustom" msgid="7837586198458073404">"តាមតម្រូវការ"</string>
<string name="eventTypeBirthday" msgid="2813379844211390740">"ថ្ងៃខួបកំណើត"</string>
@@ -640,10 +642,10 @@
<string name="orgTypeOther" msgid="3951781131570124082">"ផ្សេងៗ"</string>
<string name="orgTypeCustom" msgid="225523415372088322">"តាមតម្រូវការ"</string>
<string name="relationTypeCustom" msgid="3542403679827297300">"តាមបំណង"</string>
- <string name="relationTypeAssistant" msgid="6274334825195379076">"អ្នកជំនួយការ"</string>
+ <string name="relationTypeAssistant" msgid="6274334825195379076">"ជំនួយការ"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"បងប្អូនប្រុស"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"កូន"</string>
- <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"ដៃគូក្នុងស្រុក"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"ដៃគូរួមរស់ជាមួយគ្នា"</string>
<string name="relationTypeFather" msgid="5228034687082050725">"ឪពុក"</string>
<string name="relationTypeFriend" msgid="7313106762483391262">"មិត្តភ័ក្ដិ"</string>
<string name="relationTypeManager" msgid="6365677861610137895">"អ្នកគ្រប់គ្រង"</string>
@@ -1061,16 +1063,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"កម្រិតសំឡេងមេឌៀ"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"កម្រិតសំឡេងការជូនដំណឹង"</string>
<string name="ringtone_default" msgid="3789758980357696936">"សំឡេងរោទ៍លំនាំដើម"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>) លំនាំដើម"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"គ្មាន"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"សំឡេងរោទ៍"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"សំឡេងម៉ោងរោទិ៍"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"សំឡេងជូនដំណឹង"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"មិនស្គាល់"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">មានបណ្តាញ Wi-Fi</item>
<item quantity="one">មានបណ្តាញ Wi-Fi</item>
@@ -1216,6 +1214,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ឲ្យកម្មវិធីអានសម័យដំឡើង។ វាអនុញ្ញាតឲ្យឃើញព័ត៌មានលម្អិតអំពីការដំឡើងកញ្ចប់សកម្ម។"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ស្នើសុំកញ្ចប់ដំឡើង"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"អនុញ្ញាតឲ្យកម្មវិធីស្នើសុំដំឡើងកញ្ចប់ (ឯកសារ/មាតិកា)។"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ស្នើឲ្យមិនអើពើចំពោះការបង្កើនប្រសិទ្ធភាពថ្ម"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"អនុញ្ញាតឲ្យកម្មវិធីស្នើសុំការអនុញ្ញាត ដើម្បីមិនអើពើចំពោះការបង្កើនប្រសិទ្ធភាពថ្ម។"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ប៉ះ ពីរដងដើម្បីពិនិត្យការពង្រីក"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"មិនអាចបន្ថែមធាតុក្រាហ្វិក។"</string>
<string name="ime_action_go" msgid="8320845651737369027">"ទៅ"</string>
@@ -1566,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"ជ្រើសឆ្នាំ"</string>
<string name="deleted_key" msgid="7659477886625566590">"បានលុប <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"កន្លែងធ្វើការ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> ការងារទី 2"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> ការងារទី 3"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ដើម្បីផ្តាច់អេក្រង់នេះ សូមប៉ះ និងសង្កត់ប៊ូតុងថយក្រោយឲ្យជាប់។"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"កម្មវិធីនេះត្រូវបានខ្ទាស់។ មិនអនុញ្ញាតឲ្យដោះការខ្ទាស់នៅលើឧបករណ៍នេះទេ។"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"បានភ្ជាប់អេក្រង់"</string>
@@ -1689,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"កំណត់ឡើងវិញឥឡូវនេះ"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> ដែលបានបិទដំណើរការ"</string>
<string name="conference_call" msgid="3751093130790472426">"ការហៅជាក្រុម"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ផ្ទាំងលោត"</string>
</resources>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 30d7e4e0..5c60fbe 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"ನಿಮ್ಮ ಮಧ್ಯಸ್ಥಿಕೆ ಇಲ್ಲದೆಯೇ ಕರೆಗಳನ್ನು ಮಾಡಲು IMS ಸೇವೆಯನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ಫೋನ್ ಸ್ಥಿತಿ ಮತ್ತು ಗುರುತಿಸುವಿಕೆಯನ್ನು ಓದಿ"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ಸಾಧನದ ಫೋನ್ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು ಫೋನ್ ಸಂಖ್ಯೆ ಮತ್ತು ಸಾಧನದ ID ಗಳನ್ನು ನಿರ್ಧರಿಸಲು, ಕರೆಯು ಸಕ್ರಿಯವಾಗಿದೆಯೇ ಮತ್ತು ಕರೆಯ ಮೂಲಕ ರಿಮೋಟ್ ಸಂಖ್ಯೆಯು ಸಂಪರ್ಕಗೊಂಡಿವೆಯೇ ಎಂಬುದನ್ನೂ ನಿರ್ಧರಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ಕಲ್ಪಿಸುತ್ತದೆ."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ಫೋನ್ ಸಂಖ್ಯೆ ಓದಿ"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"ಸಾಧನದ ಫೋನ್ ಸಂಖ್ಯೆ ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ಟ್ಯಾಬ್ಲೆಟ್ ನಿದ್ರಾವಸ್ಥೆಯನ್ನು ತಡೆಯಿರಿ"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ಟಿವಿಗೆ ನಿದ್ರಿಸುವುದನ್ನು ತಪ್ಪಿಸಿ"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ಫೋನ್ ಆಫ್ ಆಗುವುದರಿಂದ ತಡೆಯಿರಿ"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"ಮೀಡಿಯಾ ವಾಲ್ಯೂಮ್"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"ಅಧಿಸೂಚನೆಯ ವಾಲ್ಯೂಮ್"</string>
<string name="ringtone_default" msgid="3789758980357696936">"ಡಿಫಾಲ್ಟ್ ರಿಂಗ್ಟೋನ್"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ಡಿಫಾಲ್ಟ್ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ಯಾವುದೂ ಇಲ್ಲ"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"ರಿಂಗ್ಟೋನ್ಗಳು"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"ಅಲಾರಮ್ ಧ್ವನಿಗಳು"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"ಅಧಿಸೂಚನೆ ಧ್ವನಿಗಳು"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"ಅಪರಿಚಿತ"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗಳು ಲಭ್ಯವಿವೆ</item>
<item quantity="other">ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗಳು ಲಭ್ಯವಿವೆ</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ಸ್ಥಾಪಿತ ಸೆಷನ್ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅನುಮತಿಸುತ್ತದೆ. ಸಕ್ರಿಯ ಪ್ಯಾಕೇಜ್ ಸ್ಥಾಪನೆಗಳ ಕುರಿತು ವಿವರಣೆಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಇದು ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ಸ್ಥಾಪನೆ ಪ್ಯಾಕೇಜ್ಗಳನ್ನು ವಿನಂತಿಸಿ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ಪ್ಯಾಕೇಜ್ಗಳ ಸ್ಥಾಪನೆಯನ್ನು ವಿನಂತಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ಬ್ಯಾಟರಿ ಆಪ್ಟಿಮೈಸೇಶನ್ಗಳನ್ನು ಕಡೆಗಣಿಸಲು ಕೇಳಿ"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"ಈ ಅಪ್ಲಿಕೇಶನ್ಗೆ ಬ್ಯಾಟರಿ ಆಪ್ಟಿಮೈಸೇಶನ್ಗಳನ್ನು ಕಡೆಗಣಿಸುವುದಕ್ಕೆ ಅನುಮತಿಯನ್ನು ಕೇಳಲು ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ಝೂಮ್ ನಿಯಂತ್ರಿಸಲು ಎರಡು ಬಾರಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ವಿಜೆಟ್ ಸೇರಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ."</string>
<string name="ime_action_go" msgid="8320845651737369027">"ಹೋಗು"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"ವರ್ಷವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ಅಳಿಸಲಾಗಿದೆ"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ಕೆಲಸ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2 ನೇ ಕೆಲಸದ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3 ನೇ ಕೆಲಸದ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ಈ ಪರದೆಯನ್ನು ಅನ್ಪಿನ್ ಮಾಡಲು, ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಂಂದೆ ಒತ್ತಿ ಹಿಡಿಯಿರಿ."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ಅಪ್ಲಿಕೇಶನ್ ಪಿನ್ ಮಾಡಲಾಗಿದೆ: ಈ ಸಾಧನದಲ್ಲಿ ಅನ್ಪಿನ್ ಮಾಡುವುದನ್ನು ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ಸ್ಕ್ರೀನ್ ಪಿನ್ ಮಾಡಲಾಗಿದೆ"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ಈಗಲೇ ಮರುಹೊಂದಿಸು"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="conference_call" msgid="3751093130790472426">"ಕಾನ್ಫರೆನ್ಸ್ ಕರೆ"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ಟೂಲ್ಟಿಪ್"</string>
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index dbb14890..07491a9 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"앱이 IMS 서비스를 사용하여 자동으로 전화를 걸 수 있도록 허용합니다."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"휴대전화 상태 및 ID 읽기"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"앱이 기기의 휴대전화 기능에 액세스할 수 있도록 허용합니다. 이 권한을 사용하면 앱이 전화번호 및 기기의 ID, 활성 통화인지 여부, 통화가 연결된 원격 번호 등을 확인할 수 있습니다."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"전화번호 읽기"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"앱에서 기기의 전화번호에 액세스할 수 있도록 허용합니다."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"태블릿이 절전 모드로 전환되지 않도록 설정"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV의 절전 모드 전환 방지"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"휴대전화가 절전 모드로 전환되지 않도록 설정"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"미디어 볼륨"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"알림 볼륨"</string>
<string name="ringtone_default" msgid="3789758980357696936">"기본 벨소리"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"기본값(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"없음"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"벨소리"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"알람 소리"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"알림 사운드"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"알 수 없음"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Wi-Fi 네트워크 사용 가능</item>
<item quantity="one">Wi-Fi 네트워크 사용 가능</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"애플리케이션의 설치 세션 읽기를 허용하면, 활성 패키지 설치에 대한 세부 정보를 볼 수 있습니다."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"패키지 설치 요청"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"애플리케이션이 패키지 설치를 요청하도록 허용합니다."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"배터리 최적화를 무시하도록 요청"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"앱에서 배터리 최적화를 무시할 수 있는 권한을 요청할 수 있도록 허용합니다."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"확대/축소하려면 두 번 탭하세요."</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"위젯을 추가할 수 없습니다."</string>
<string name="ime_action_go" msgid="8320845651737369027">"이동"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"연도 선택"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> 삭제됨"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"업무용 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"두 번째 업무용 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"세 번째 업무용<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"이 화면을 고정 해제하려면 \'뒤로\'를 길게 터치합니다."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"앱이 고정되었습니다. 이 기기에서는 고정 해제를 허용하지 않습니다."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"화면 고정됨"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"지금 초기화"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> 사용 중지됨"</string>
<string name="conference_call" msgid="3751093130790472426">"다자간 통화"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"도움말"</string>
</resources>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 3583189..86128bd 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Колдонмого сизди катыштырбай туруп, IMS кызматынын жардамы менен чалууларды жасоо мүмкүнчүлүгүн берет."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"телефондун абалын жана аныктыгын окуу"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Колдонмого түзмөктүн чалуу мүмкүнчүлүктөрүнө жетки алуу уруксатын берет. Бул уруксат колдонмого, телефондун номурун, түзмөктүн ID-син, чалуунун абалын жана байланышта чыккан номурду аныктоого жол берет."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"телефон номерин окуу"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Колдонмого түзмөктүн телефон номерин окуу мүмкүнчүлүгү берилет."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"планшетти уктатпай сактоо"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"сыналгыны көшүтпөө"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"телефонду уктатпай сактоо"</string>
@@ -641,18 +643,18 @@
<string name="orgTypeCustom" msgid="225523415372088322">"Өзгөчө"</string>
<string name="relationTypeCustom" msgid="3542403679827297300">"Өзгөчө"</string>
<string name="relationTypeAssistant" msgid="6274334825195379076">"Жардамчы"</string>
- <string name="relationTypeBrother" msgid="8757913506784067713">"Ага-ини"</string>
- <string name="relationTypeChild" msgid="1890746277276881626">"Баласы"</string>
- <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Жергиликтүү Өнөктөш"</string>
- <string name="relationTypeFather" msgid="5228034687082050725">"Атасы"</string>
- <string name="relationTypeFriend" msgid="7313106762483391262">"Досу"</string>
- <string name="relationTypeManager" msgid="6365677861610137895">"Менежер"</string>
- <string name="relationTypeMother" msgid="4578571352962758304">"Энеси"</string>
+ <string name="relationTypeBrother" msgid="8757913506784067713">"Ага/Ини"</string>
+ <string name="relationTypeChild" msgid="1890746277276881626">"Бала"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Жарандык нике"</string>
+ <string name="relationTypeFather" msgid="5228034687082050725">"Ата"</string>
+ <string name="relationTypeFriend" msgid="7313106762483391262">"Дос"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"Башчы"</string>
+ <string name="relationTypeMother" msgid="4578571352962758304">"Эне"</string>
<string name="relationTypeParent" msgid="4755635567562925226">"Ата/эне"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"Өнөк"</string>
- <string name="relationTypeReferredBy" msgid="101573059844135524">"Төмөнкүдөй аталат"</string>
+ <string name="relationTypeReferredBy" msgid="101573059844135524">"Сунушталган"</string>
<string name="relationTypeRelative" msgid="1799819930085610271">"Тууган"</string>
- <string name="relationTypeSister" msgid="1735983554479076481">"Эже-сиңди"</string>
+ <string name="relationTypeSister" msgid="1735983554479076481">"Эже/Сиңди"</string>
<string name="relationTypeSpouse" msgid="394136939428698117">"Жубай"</string>
<string name="sipAddressTypeCustom" msgid="2473580593111590945">"Өзгөчө"</string>
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Үй"</string>
@@ -1058,10 +1060,10 @@
<string name="volume_icon_description_incall" msgid="8890073218154543397">"Чалуунун үн деңгээли"</string>
<string name="volume_icon_description_media" msgid="4217311719665194215">"Медиа үнүнүн деңгээли"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Эскертме үнүнүн деңгээли"</string>
- <string name="ringtone_default" msgid="3789758980357696936">"Демейки рингтон"</string>
- <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Демейки рингтон (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+ <string name="ringtone_default" msgid="3789758980357696936">"Демейки шыңгыр"</string>
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Демейки шыңгыр (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Эч бир"</string>
- <string name="ringtone_picker_title" msgid="3515143939175119094">"Ринтондор"</string>
+ <string name="ringtone_picker_title" msgid="3515143939175119094">"Шыңгырлар"</string>
<string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Ойготкучтун добуштары"</string>
<string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Эскертменин добуштары"</string>
<string name="ringtone_unknown" msgid="3914515995813061520">"Белгисиз"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Колдонмого орнотуу сеанстарын окуу мүмкүнчүлүгүн берет. Ушуну менен, ал жигердүү топтом орнотууларынын чоо-жайын көрө алат."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"орнотуу топтомдорун суроо"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Колдонмо топтомдорду орнотууга уруксат сурай алат."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"батареянын кубатын көп керектей берсин"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Колдонмо батареянын кубатын керектегенден мурун уруксат суралсын."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Масштабдын параметрлерин өзгөртүү үчүн бул жерди эки жолу басыңыз."</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Виджетти кошуу мүмкүн болбоду."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Өтүү"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Жылды тандаңыз"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> өчүрүлдү"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Бул экранды бошотуу үчүн \"Артка\" баскычын басып, кармап туруңуз."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Колдонмо кадалган: Бул түзмөктө бошотууга уруксат жок."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Экран кадалды"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Баштапкы абалга келтирүү"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> өчүрүлдү"</string>
<string name="conference_call" msgid="3751093130790472426">"Конференц чалуу"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Калкып чыгуучу кеңеш"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Калкып чыгуучу кеңеш"</string>
</resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index baf6d51..db08110 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"ອະນຸຍາດໃຫ້ແອັບໃຊ້ການບໍລິການ IMS ເພື່ອໂທໂດຍບໍ່ມີການຊ່ວຍເຫຼືອຂອງທ່ານ."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ອ່ານສະຖານະ ແລະຂໍ້ມູນລະບຸໂຕຕົນຂອງໂທລະສັບ"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ອະນຸຍາດໃຫ້ແອັບຯ ເຂົ້າເຖິງຄວາມສາມາດການໂທລະສັບຂອງອຸປະກອນ. ການກຳນົດສິດນີ້ເຮັດໃຫ້ແອັບຯສາມາດກວດສອບເບີໂທລະສັບ ແລະ ID ຂອງອຸປະກອນ, ບໍ່ວ່າການໂທຈະຍັງດຳເນີນຢູ່ ແລະເບີປາຍທາງເຊື່ອມຕໍ່ຢູ່ຫຼືບໍ່ກໍຕາມ."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"read phone number"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Allows the app to access the phone number of the device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ຂັດຂວາງບໍ່ໃຫ້ປິດໜ້າຈໍແທັບເລັດ"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ປ້ອງກັນບໍ່ໃຫ້ໂທລະພາບຫຼັບພັກ"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ຂັດຂວາງບໍ່ໃຫ້ໂທລະສັບປິດໜ້າຈໍ"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"ລະດັບສຽງຂອງສື່"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"ລະດັບສຽງການແຈ້ງເຕືອນ"</string>
<string name="ringtone_default" msgid="3789758980357696936">"ຣິງໂທນເລີ່ມຕົ້ນ"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Default (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ບໍ່ມີ"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"ຣິງໂທນ"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Alarm sounds"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Notification sounds"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"ບໍ່ຮູ້ຈັກ"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">ເຄືອຂ່າຍ Wi-Fi ທີ່ມີໃຫ້</item>
<item quantity="one">ເຄືອຂ່າຍ Wi-Fi ທີ່ມີໃຫ້</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນອ່ານເຊດຊັນການຕິດຕັ້ງໄດ້. ນີ້ຈະອະນຸຍາດໃຫ້ມັນເບິ່ງເຫັນລາຍລະອຽດກ່ຽວກັບການຕິດຕັ້ງແພັກເກດທີ່ເຮັດວຽກຢູ່ໄດ້."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ຂໍຕິດຕັ້ງແພັກເກດ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນຂອງການຕິດຕັ້ງແພັກເກດ."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ຖາມເພື່ອໃຫ້ເພີກເສີຍການປັບແຕ່ງແບັດເຕີຣີ"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"ອະນຸຍາດໃຫ້ແອັບຖາມສິດອະນຸຍາດເພື່ອເພີກເສີຍຕໍ່ການປັບແຕ່ງແບັດເຕີຣີສຳລັບແອັບນັ້ນ."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ແຕະສອງເທື່ອເພື່ອຄວບຄຸມການຊູມ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ບໍ່ສາມາດເພີ່ມວິດເຈັດໄດ້."</string>
<string name="ime_action_go" msgid="8320845651737369027">"ໄປ"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"ເລືອກປີ"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ຖືກລຶບແລ້ວ"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ບ່ອນເຮັດວຽກ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"ບ່ອນເຮັດວຽກທີ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"ບ່ອນເຮັດວຽກທີ 3 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ກົດປຸ່ມກັບຄືນຄ້າງໄວ້ເພື່ອເຊົາປັກໝຸດໜ້າຈໍນີ້."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ແອັບຖືກປັກໝຸດແລ້ວ: ບໍ່ອະນຸຍາດໃຫ້ຖອນປັກໝຸດຢູ່ເທິງອຸປະກອນນີ້."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ປັກໝຸດໜ້າຈໍແລ້ວ"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ຣີເຊັດດຽວນີ້"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"ປິດການນຳໃຊ້ <xliff:g id="LABEL">%1$s</xliff:g> ແລ້ວ"</string>
<string name="conference_call" msgid="3751093130790472426">"ການປະຊຸມສາຍ"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ຄຳອະທິບາຍເຄື່ອງມື"</string>
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index f9293c4..888a312 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Programai leidžiama naudoti IMS paslaugą, kad būtų galima atlikti skambučius be jūsų įsikišimo."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"skaityti telefono būseną ir tapatybę"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Leidžiama programai pasiekti telefono funkcijas įrenginyje. Šis leidimas suteikia teisę programai nustatyti telefono numerį ir įrenginio ID, tai, ar skambutis aktyvus, ir skambučiu prijungtą nuotolinį numerį."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"skaityti telefono numerį"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Programai leidžiama pasiekti įrenginio telefono numerį."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"neleisti planšetiniam kompiuteriui užmigti"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"neleisti įjungti TV miego būsenos"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"neleisti telefonui snausti"</string>
@@ -1105,16 +1107,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Medijos garsumas"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Pranešimo apimtis"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Numatytasis skambėjimo tonas"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Numatytasis („<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>“)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Nėra"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Skambėjimo tonai"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Įspėjimų garsai"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Pranešimų garsai"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Nežinoma"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Pasiekiami „Wi-Fi“ tinklai</item>
<item quantity="few">Pasiekiami „Wi-Fi“ tinklai</item>
@@ -1264,6 +1262,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Leidžiama programai skaityti diegimo seansus. Leidžiama peržiūrėti išsamią aktyvių paketų diegimo informaciją."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"pateikti užklausą dėl diegimo paketų"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Programai leidžiama pateikti užklausą dėl paketų diegimo."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"prašyti nepaisyti akumuliatoriaus optimizavimo nustatymų"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Programai leidžiama prašyti leidimo nepaisyti tai programai skirto akumuliatoriaus optimizavimo nustatymų."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Bakstelėkite du kartus, kad valdytumėte mastelio keitimą"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nepavyko pridėti."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Pradėti"</string>
@@ -1618,10 +1618,8 @@
<string name="select_year" msgid="7952052866994196170">"Pasirinkite metus"</string>
<string name="deleted_key" msgid="7659477886625566590">"Ištrinta: <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-asis darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-iasis darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Kad atsegtumėte šį ekraną, palieskite ir palaikykite „Atgal“."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Programa prisegta: šiame įrenginyje negalima atsegti."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekrano prisegtas"</string>
@@ -1759,6 +1757,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Nustatyti iš naujo dabar"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Išj. valdiklis „<xliff:g id="LABEL">%1$s</xliff:g>“"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferencinis skambutis"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Patarimas"</string>
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 04ea14e..3092fd6 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -380,6 +380,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Ļauj lietotnei izmantot tūlītējās ziņojumapmaiņas pakalpojumu, lai veiktu zvanus bez jūsu ziņas."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lasīt tālruņa statusu un identitāti"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Ļauj lietotnei piekļūt ierīces tālruņa funkcijām. Ar šo atļauju lietotne var noteikt tālruņa numuru un ierīču ID, zvana statusu un attālo numuru, ar ko ir izveidots savienojums, veicot zvanu."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lasīt tālruņa numuru"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Ļauj lietotnei piekļūt ierīces tālruņa numuram."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"novērst planšetdatora pāriešanu miega režīmā"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"novērst televizora pāreju miega režīmā"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"novērst tālruņa pāriešanu miega režīmā"</string>
@@ -1082,16 +1084,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Multivides skaļums"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Paziņojumu skaļums"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Noklusējuma zvana signāls"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Noklusējuma (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Nav"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Zvana signāli"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Modinātāja signāla skaņas"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Paziņojumu skaņas"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Nezināms"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="zero">Pieejami Wi-Fi tīkli</item>
<item quantity="one">Pieejami Wi-Fi tīkli</item>
@@ -1239,6 +1237,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Ļauj lietojumprogrammai lasīt instalēšanas sesijas. Tādējādi lietojumprogrammai ir pieejama informācija par aktīvajām pakotņu instalācijām."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"Pieprasīt pakotņu instalēšanu"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Ļauj lietojumprogrammai pieprasīt pakotņu instalēšanu."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"Lūgt akumulatora optimizācijas ignorēšanu"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Ļauj lietotnei lūgt atļauju ignorēt akumulatora optimizāciju šai lietotnei."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Pieskarieties divreiz, lai kontrolētu tālummaiņu."</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nevarēja pievienot logrīku."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Doties uz"</string>
@@ -1591,10 +1591,8 @@
<string name="select_year" msgid="7952052866994196170">"Atlasiet gadu."</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> tika dzēsts."</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Darbā: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. darba profils: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. darba profils: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Lai atspraustu šo ekrānu, pieskarieties pogai “Atpakaļ” un turiet to."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Lietotne ir piesprausta. Atspraušana šajā ierīcē nav atļauta."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekrāns ir piesprausts"</string>
@@ -1723,6 +1721,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Atiestatīt tūlīt"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> atspējots"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferences zvans"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Rīka padoms"</string>
</resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index aeb0c41..ad79b88 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Дозволува апликацијата да ја користи услугата IMS за повици без ваша интервенција."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"прочитај ги статусот и идентитетот на телефонот"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Овозможува апликацијата да пристапи кон карактеристиките на телефонот на уредот. Оваа дозвола овозможува апликацијата да ги утврди телефонскиот број и ID на уредот, дали повикот е активен и далечинскиот број поврзан со повикот."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"да го чита телефонскиот број"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Ѝ дозволува на апликацијата да пристапи до телефонскиот број на уредот."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"спречи режим на штедење кај таблет"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"спречи го телевизорот да премине во режим на мирување"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"спречи телефон од режим на штедење"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Дозволува апликација да чита сесии на инсталирање. Тоа овозможува апликацијата да гледа детали за активни инсталации на пакет."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"барање пакети за инсталирање"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Дозволува апликацијата да бара инсталација на пакети."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"прашај дали да се игнорираат оптимизациите на батеријата"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Овозможува апликацијата да побара дозвола за игнорирање на оптимизациите на батеријата за таа апликација."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Допрете двапати за контрола на зумот"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Не можеше да се додаде виџет."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Оди"</string>
@@ -1562,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"Избери година"</string>
<string name="deleted_key" msgid="7659477886625566590">"Избришано <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Работа <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Втора деловна <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Трета деловна <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"За откачување на екранов, допрете и задржете Назад."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Апликацијата е закачена: откачување не е дозволено на уредов."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Екранот е закачен"</string>
@@ -1685,5 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Ресетирај сега"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Оневозможен <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Конференциски повик"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Појавен прозорец на совет за алатка"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Совет за алатка"</string>
</resources>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 4193079..2d4cf65 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -163,7 +163,7 @@
<string name="notification_title" msgid="8967710025036163822">"<xliff:g id="ACCOUNT">%1$s</xliff:g> എന്നതിൽ സൈൻ ഇൻ ചെയ്യുന്നതിൽ പിശക്"</string>
<string name="contentServiceSync" msgid="8353523060269335667">"സമന്വയിപ്പിക്കുക"</string>
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"സമന്വയിപ്പിക്കുക"</string>
- <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"വളരെയധികം <xliff:g id="CONTENT_TYPE">%s</xliff:g> ഇല്ലാതാക്കലുകൾ."</string>
+ <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"വളരെയധികം <xliff:g id="CONTENT_TYPE">%s</xliff:g> ഇല്ലാതാക്കുന്നു."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"ടാബ്ലെറ്റ് സ്റ്റോറേജ് കഴിഞ്ഞു. ഇടം ശൂന്യമാക്കാൻ ചില ഫയലുകൾ ഇല്ലാതാക്കുക."</string>
<string name="low_memory" product="watch" msgid="4415914910770005166">"വാച്ചിലെ സ്റ്റോറേജ് നിറഞ്ഞു. ഇടം ശൂന്യമാക്കാൻ കുറച്ച് ഫയലുകൾ ഇല്ലാതാക്കുക."</string>
<string name="low_memory" product="tv" msgid="516619861191025923">"ടിവി സ്റ്റോറേജ് നിറഞ്ഞു. ഇടം ശൂന്യമാക്കാൻ കുറച്ച് ഫയലുകൾ ഇല്ലാതാക്കുക."</string>
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"നിങ്ങളുടെ ഇടപെടൽ ഇല്ലാതെ കോളുകൾ ചെയ്യാൻ IMS സേവനം ഉപയോഗിക്കുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ഫോൺ നിലയും ഐഡന്റിറ്റിയും റീഡുചെയ്യുക"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ഉപകരണത്തിന്റെ ഫോൺ സവിശേഷതകൾ ആക്സസ്സുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഈ അനുമതി ഫോൺ നമ്പർ, ഉപകരണ ഐഡികൾ, ഒരു കോൾ സജീവമാണോയെന്നത്, ഒരു കോൾ കണക്റ്റുചെയ്ത വിദൂര നമ്പർ എന്നിവ നിർണ്ണയിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ഫോൺ നമ്പർ വായിക്കുക"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"ഉപകരണത്തിന്റെ ഫോൺ നമ്പർ ആക്സസ്സ് ചെയ്യുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"സുഷുപ്തിയിലാകുന്നതിൽ നിന്ന് ടാബ്ലെറ്റിനെ തടയുക"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ടിവിയെ നിർജ്ജീവമാകുന്നതിൽ നിന്ന് തടയുക"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"സുഷുപ്തിയിലാകുന്നതിൽ നിന്ന് ഫോണിനെ തടയുക"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"മീഡിയ വോളിയം"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"അറിയിപ്പ് വോളിയം"</string>
<string name="ringtone_default" msgid="3789758980357696936">"ഡിഫോൾട്ട് റിംഗ്ടോൺ"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ഡിഫോൾട്ട് (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ഒന്നും വേണ്ട"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"റിംഗ്ടോണുകൾ"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"അലാറം ശബ്ദങ്ങൾ"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"അറിയിപ്പ് ശബ്ദങ്ങൾ"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"അറിഞ്ഞുകൂടാത്തത്"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">വൈഫൈ നെറ്റ്വർക്കുകൾ ലഭ്യമാണ്</item>
<item quantity="one">വൈഫൈ നെറ്റ്വർക്ക് ലഭ്യമാണ്</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ഇൻസ്റ്റാൾ ചെയ്ത സെഷനുകൾ റീഡുചെയ്യുന്നതിന് ഒരു അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. സജീവ പാക്കേജ് ഇൻസ്റ്റാളേഷനുകളെക്കുറിച്ചുള്ള വിശദാംശങ്ങൾ കാണുന്നതിന് ഇത് അനുവദിക്കുന്നു."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"പാക്കേജുകൾ ഇൻസ്റ്റാൾ ചെയ്യാൻ അഭ്യർത്ഥിക്കുക"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"പാക്കേജുകളുടെ ഇൻസ്റ്റാളേഷൻ അഭ്യർത്ഥിക്കാൻ ഒരു അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ബാറ്ററി ഒപ്റ്റിമൈസേഷനുകൾ അവഗണിക്കാൻ ആവശ്യപ്പെടുക"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"ആപ്പിന് വേണ്ടിയുള്ള ബാറ്ററി ഒപ്റ്റിമൈസേഷനുകളെ അവഗണിക്കാനുള്ള അനുമതി ചോദിക്കുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"സൂം നിയന്ത്രണം ലഭിക്കാൻ രണ്ടുതവണ ടാപ്പുചെയ്യുക"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"വിജറ്റ് ചേർക്കാനായില്ല."</string>
<string name="ime_action_go" msgid="8320845651737369027">"പോവുക"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"വർഷം തിരഞ്ഞെടുക്കുക"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ഇല്ലാതാക്കി"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ഔദ്യോഗികം <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"രണ്ടാമത്തെ ഔദ്യോഗിക <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"മൂന്നാമത്തെ ഔദ്യോഗിക <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ഈ സ്ക്രീൻ അൺപിൻ ചെയ്യാൻ, ബാക്ക് ബട്ടൺ സ്പർശിച്ച് പിടിക്കുക"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"അപ്ലിക്കേഷൻ പിൻ ചെയ്തു: ഈ ഉപകരണത്തിൽ അൺപിൻ ചെയ്യാനാവില്ല."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"സ്ക്രീൻ പിൻ ചെയ്തു"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ഇപ്പോൾ പുനക്രമീകരിക്കുക"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="conference_call" msgid="3751093130790472426">"കോൺഫറൻസ് കോൾ"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ടൂൾ ടിപ്പ്"</string>
</resources>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 74006da..c364488 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Апп нь дуудлага хийхдээ таны оролцоогүйгээр IMS үйлчилгээг ашиглах боломжтой."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"утасны статус ба таниулбарыг унших"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Апп нь төхөөрөмжийн утасны функцд хандах боломжтой. Энэ зөвшөөрөл нь апп-д утасны дугаар болон төхөөрөмжийн ID-г, дуудлага идэвхтэй эсэх, холын дугаар дуудлагаар холбогдсон байгаа эсэхийг тогтоох боломжийг олгоно,"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"утасны дугаарыг харах"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Төхөөрөмжийн утасны дугаарт хандах зөвшөөрлийг аппд олгоно."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"таблетыг унтуулахгүй байлгах"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"Телевиз-ийн гэрэл унтрахаас сэргийл"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"утсыг унтуулахгүй байлгах"</string>
@@ -436,7 +438,7 @@
<string name="permlab_manageFingerprint" msgid="5640858826254575638">"хурууны хээний програм хангамжийг удирдах"</string>
<string name="permdesc_manageFingerprint" msgid="178208705828055464">"Хурууны хээний загварыг нэмэх эсвэл усгтах үйлдлийг хийх зөвшөөрлийг програмд олгодог."</string>
<string name="permlab_useFingerprint" msgid="3150478619915124905">"хурууны хээний програм хангамжийг ашиглах"</string>
- <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Баталгаажуулалт хийх зорилгоор хурууны хээний програм хамгамжийг ашиглах зөвшөөрлийг програмд олгодог"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Баталгаажуулалт хийх зорилгоор хурууны хээний апп хамгамжийг ашиглах зөвшөөрлийг аппд олгодог"</string>
<string name="fingerprint_acquired_partial" msgid="735082772341716043">"Хурууны хээг дутуу уншуулсан байна. Дахин оролдоно уу."</string>
<string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Хурууны хээ боловсруулж чадахгүй байна. Дахин оролдоно уу."</string>
<string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Хурууны хээ мэдрэгч бохирдсон байна. Та цэвэрлэсний дараагаар дахин оролдоно уу."</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Медиа дууны хэмжээ"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Мэдэгдлийн дууны хэмжээ"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Үндсэн хонхны ая"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Үндсэн (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Алийг нь ч биш"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Хонхны ая"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Сэрүүлгийн ая"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Мэдэгдлийн дуу"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Тодорхойгүй"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Wi-Fi сүлжээ ашиглах боломжтой</item>
<item quantity="one">Wi-Fi сүлжээ ашиглах боломжтой</item>
@@ -1208,12 +1206,14 @@
<string name="ext_media_status_formatting" msgid="1085079556538644861">"Хэлбэршүүлж байна..."</string>
<string name="ext_media_status_missing" msgid="5638633895221670766">"Оруулаагүй байна"</string>
<string name="activity_list_empty" msgid="1675388330786841066">"Таарах активити олдсонгүй."</string>
- <string name="permlab_route_media_output" msgid="6243022988998972085">"медиа гаралтын маршрут"</string>
+ <string name="permlab_route_media_output" msgid="6243022988998972085">"медиа гаралтын чиглэл"</string>
<string name="permdesc_route_media_output" msgid="4932818749547244346">"Аппликешн нь медиа гаралтыг бусад гадаад төхөөрөмжрүү чиглүүлэх боломжтой."</string>
<string name="permlab_readInstallSessions" msgid="3713753067455750349">"Суулгах харилцан үйлдлийг унших"</string>
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Аппликешн-д суулгах сешн уншихыг зөвшөөрнө. Энэ нь идэвхтэй багцуудыг суулгалтын талаар дэлгэрэнгүй мэдээллийг үзэх боломж олгоно."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"багц суулгахыг хүсэх"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Аппликейшн нь багц суулгахыг хүсэх боломжтой."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"батерейны оновчлол алгасахыг асуух"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Тухайн аппaaс батерейны оновчлол алгасах зөвшөөрөл асуухыг зөвшөөрдөг."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Өсгөх контрол дээр хоёр удаа товшино уу"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Виджет нэмж чадсангүй."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Очих"</string>
@@ -1240,7 +1240,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Ханын зураг"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Ханын зураг солих"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Мэдэгдэл сонсогч"</string>
- <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR сонсогч"</string>
+ <string name="vr_listener_binding_label" msgid="4316591939343607306">"Виртуал Орчин (VR) сонсогч"</string>
<string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Нөхцөл нийлүүлэгч"</string>
<string name="notification_ranker_binding_label" msgid="774540592299064747">"Мэдэгдлийг ангилах үйлчилгээ"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN идэвхтэй болов"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Жилийг сонгоно уу"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> устсан"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Ажлын <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2 дахь ажил <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3 дахь ажил <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Энэ дэлгэцийг эхэнд нээхийг болиулахын тулд Буцах товчлуурыг дараад, хүлээнэ үү."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App-ыг тусгайлан тэмдэглэсэн байна: Энэ төхөөрөмж дээр тусгайлан тэмдэглэсэн сонголтыг устгах боломжгүй."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Дэлгэцийг тогтоосон"</string>
@@ -1685,6 +1683,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Одоо шинэчлэх"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g>-г цуцалсан"</string>
<string name="conference_call" msgid="3751093130790472426">"Хурлын дуудлага"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Зөвлөмж"</string>
</resources>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index dd99f15..03721ce 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"आपल्या हस्तक्षेपाशिवाय अॅपला कॉल करण्यासाठी IMS सेवा वापरण्याची अनुमती देते."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"फोन स्थिती आणि ओळख वाचा"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"डिव्हाइसच्या फोन वैशिष्ट्यांवर प्रवेश करण्यास अॅप ला अनुमती देते. ही परवानगी कॉल सक्रिय असला किंवा नसला तरीही, फोन नंबर आणि डिव्हाइस ID आणि कॉलद्वारे कनेक्ट केलेला रीमोट नंबर निर्धारित करण्यासाठी अॅप ला अनुमती देते."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"फोन नंबर वाचा"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"अॅपला डिव्हाइसच्या फोन नंबरमध्ये प्रवेश करण्याची अनुमती देते."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"टॅबलेट निष्क्रिय होण्यापासून प्रतिबंधित करा"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"निष्क्रिय होण्यापासून प्रतिबंध करा"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"फोन निष्क्रिय होण्यापासून प्रतिबंधित करा"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"अनुप्रयोगास स्थापना सत्र वाचण्याची अनुमती देते. हे सक्रिय पॅकेज स्थापनांविषयी तपशील पाहाण्याची यास अनुमती देते."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"पॅकेज स्थापित करण्यासाठी विनंती करा"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"पॅकेजच्या स्थापना करण्यासाठी अनुप्रयोगास अनुमती देते."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"बॅटरी ऑप्टिमायझेशन दुर्लक्षित करण्यास सांगा"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"त्या अॅपसाठी बॅटरी ऑप्टिमायझेशन दुर्लक्षित करण्यासाठी अॅपला परवानगी मागण्याची अनुमती देते."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"झूम नियंत्रणासाठी दोनदा टॅप करा"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"विजेट जोडू शकलो नाही."</string>
<string name="ime_action_go" msgid="8320845651737369027">"जा"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"वर्ष निवडा"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> हटविली"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2 रे कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3 रे कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ही स्क्रीन अनपिन करण्यासाठी, परत ला स्पर्श करा आणि धरून ठेवा."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"अॅप पिन केलेला आहे: या डिव्हाइसवर अनपिन करण्यास अनुमती नाही."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"स्क्रीन पिन केली"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"आता रीसेट करा"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> अक्षम केले"</string>
<string name="conference_call" msgid="3751093130790472426">"परिषद कॉल"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"टूलटिप पॉपअप"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"टूलटिप"</string>
</resources>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 57edab8..3684ebe 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Membenarkan apl menggunakan perkhidmatan IMS untuk membuat panggilan tanpa campur tangan anda."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"baca status dan identiti telefon"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Membenarkan apl mengakses ciri telefon pada peranti. Kebenaran ini membolehkan apl menentukan nombor telefon dan ID peranti, sama ada panggilan aktif dan nombor jauh yang dihubungkan dengan panggilan."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"baca nombor telefon"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Membenarkan apl mengakses nombor telefon peranti."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"menghalang tablet daripada tidur"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"halang TV daripada tidur"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"halang telefon daripada tidur"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Kelantangan media"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Kelantangan pemberitahuan"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Nada dering lalai"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Lalai (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Tiada"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Nada dering"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Bunyi penggera"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Bunyi pemberitahuan"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Tidak diketahui"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Rangkaian Wi-Fi tersedia</item>
<item quantity="one">Rangkaian Wi-Fi tersedia</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Membenarkan aplikasi membaca sesi pemasangan Ini membenarkan apl melihat butiran mengenai pemasangan pakej yang aktif."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"minta pakej pemasangan"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Membenarkan aplikasi meminta pemasangan pakej."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"minta kebenaran untuk mengabaikan pengoptimuman bateri"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Membenarkan apl meminta kebenaran untuk mengabaikan pengoptimuman bateri untuk apl itu."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Ketik dua kali untuk mendapatkan kawalan zum"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Tidak dapat menambahkan widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Pergi"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Pilih tahun"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> dipadamkan"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Kerja <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> kerja ke-2"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> kerja ke-3"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Untuk menyahsematkan skrin ni, ketik & tahan Kembali."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Apl disemat: Nyahsemat tidak dibenarkan pada peranti ini."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skrin disemat"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Tetapkan semula sekarang"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> dilumpuhkan"</string>
<string name="conference_call" msgid="3751093130790472426">"Panggilan Sidang"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Keterangan item"</string>
</resources>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 834a665..50c3b8c 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"သင့်ရဲ့ဝင်ရောက်စွက်ဖက်မှုမပါဘဲ IMS ဝန်ဆောင်မှုကိုအသုံးပြုပြီး ဖုန်းခေါ်ဆိုနိုင်ရန် အပ်ဖ်ကို ခွင့်ပြုထားပါ။"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ဖုန်းရဲ့ အခြေအနေ နှင့် အမှတ်သညာအား ဖတ်ခြင်း"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"အပလီကေးရှင်းအား ဖုန်းရဲ့ စွမ်းဆောင်ချက်များအား သုံးခွင့်ပြုပါ။ အပလီကေးရှင်းအနေဖြင့် ဖုန်းနံပါတ်၊ စက်နံပါတ်၊ ဖုန်းခေါ်နေမှု ရှိမရှိနှင့် တဖက်မှ ဖုန်းနံပါတ် များအား သိရှိနိုင်ပါသည်"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ဖုန်းနံပါတ်ကို ဖတ်ရန်"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"အက်ပ်ကို စက်ပစ္စည်း၏ ဖုန်းနံပါတ် အသုံးပြုခွင့်ပေးပါ။"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"တက်ပလက်အား ပိတ်ခြင်းမှ ကာကွယ်ခြင်း"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"တီဗွီအား နားနေခြင်းမှ ကာကွယ်ရန်"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ဖုန်းအနားယူခြင်းမပြုလုပ်စေရန်"</string>
@@ -643,7 +645,7 @@
<string name="relationTypeAssistant" msgid="6274334825195379076">"အထောက်အကူ"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"ညီအကို"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"သားသမီး"</string>
- <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"အတူနေအပေါင်းအဖော်"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"အတူနေအဖော်"</string>
<string name="relationTypeFather" msgid="5228034687082050725">"ဖခင်"</string>
<string name="relationTypeFriend" msgid="7313106762483391262">"သူငယ်ချင်း"</string>
<string name="relationTypeManager" msgid="6365677861610137895">"မန်နေဂျာ"</string>
@@ -651,7 +653,7 @@
<string name="relationTypeParent" msgid="4755635567562925226">"မိဘ"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"လုပ်ဖော်ကိုင်ဖက်"</string>
<string name="relationTypeReferredBy" msgid="101573059844135524">"မှရည်ညွှန်းပေးသည်"</string>
- <string name="relationTypeRelative" msgid="1799819930085610271">"ဆွေးမျိုး"</string>
+ <string name="relationTypeRelative" msgid="1799819930085610271">"ဆွေမျိုး"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"ညီအမ"</string>
<string name="relationTypeSpouse" msgid="394136939428698117">"အိမ်ထောင်ဖက်"</string>
<string name="sipAddressTypeCustom" msgid="2473580593111590945">"မိမိစိတ်ကြိုက်"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"အပလီကေးရှင်းအား တပ်ဆင်ရေး ချိတ်ဆက်မှုများကို ဖတ်ခွင့်ပြုသည်။ ၎င်းသည် ဖွင့်သုံးနေသည့် အထုပ်အား တပ်ဆင်မှုဆိုင်ရာ အသေးိစတ်များကို ကြည့်ရှုခွင့် ပြုသည်။"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"တပ်ဆင်ရေး အထုပ်များကို တောင်းဆိုပါ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ပက်ကေ့များ သွင်းယူခြင်းအတွက် တောင်းဆိုရန် အပလီကေးရှင်းအား ခွင့်ပြုပါ"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ဘက်ထရီ ပိုမိုကောင်းမွန်အောင် ပြုလုပ်ခြင်းကို လျစ်လျူရှုရန် တောင်းဆိုပါ"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"ဘက်ထရီ ပိုမိုကောင်းမွန်အောင် ပြုလုပ်ခြင်းကို လျစ်လျူရှုရန်အတွက် ခွင့်ပြုချက်တောင်းရန် အက်ပ်ကို ခွင့်ပြုပါ။"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ဇူးမ်အသုံးပြုရန် နှစ်ချက်တို့ပါ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ဝဒ်ဂျက်ထည့်လို့ မရပါ"</string>
<string name="ime_action_go" msgid="8320845651737369027">"သွားပါ"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"ခုနှစ်ကို ရွေးပါ"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ကို ဖျက်ပြီးပါပြီ"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"အလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"ဒုတိယအလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"တတိယအလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ဤမျက်နှာပြင်ကို ပင်ဖြုတ်ရန် \"နောက်သို့\" ကိုထိပြီးဖိထားပါ။"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"အက်ပ်ကို ပင်ထိုးထားသည်။ ပင်ဖျက်ခြင်းကို ဒီစက်မှာ မရနိုင်ပါ။"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"မျက်နှာပြင်ကို ပင်ထိုးထား"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ယခုပြန်လည်သတ်မှတ်ပါ"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"ပိတ်ထားသည့် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"လူအမြောက်အမြားတပြိုင်နက် ခေါ်ဆိုမှု"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"အကြံပြုချက်ပြ ပေါ့အပ်ဝင်းဒိုး"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"အကြံပြုချက်ပြ ပေါ့အပ် ဝင်းဒိုး"</string>
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 61e74a2..e8bab9c 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Lar appen bruke nettprattjenesten til å ringe uten at du gjør noe."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lese telefonstatus og -identitet"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Lar appen bruke enhetens telefonfunksjoner. Med denne tillatelsen kan appen finne telefonnummer og enhets-ID-er, registrere om en samtale pågår, og se det eksterne nummeret det opprettes en forbindelse med via oppringing."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"les telefonnummeret"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Gir appen tilgang til telefonnummeret til enheten."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"hindre nettbrettet fra å gå over til sovemodus"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"hindre TV-en i å gå i hvilemodus"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"forhindre telefonen fra å sove"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Tillater en app å lese installeringsøkter. Dette gjør det mulig for den å se detaljer om aktive pakkeinstallasjoner."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"be om installasjon av pakker"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Lar apper be om installasjon av pakker."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"be om å ignorere batterioptimaliseringer"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Gjør det mulig for apper å be om tillatelse til å ignorere batterioptimaliseringer for disse appene."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Trykk to ganger for zoomkontroll"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Kunne ikke legge til modulen."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Utfør"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Velg året"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> er slettet"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Jobb-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Andre <xliff:g id="LABEL">%1$s</xliff:g> for jobben"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Tredje <xliff:g id="LABEL">%1$s</xliff:g> for jobben"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"For å løsne denne skjermen, trykk og hold inne Tilbake."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Appen er festet – du kan ikke løsne apper på denne enheten."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skjermen er festet"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Tilbakestill nå"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> er slått av"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferansesamtale"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Verktøytips i forgrunnen"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Verktøytips"</string>
</resources>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index d6c8612..838c83b 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"तपाईँको हस्तक्षेप बिना नै कल गर्न IMS सेवा प्रयोग गर्न अनुप्रयोगलाई अनुमति दिन्छ।"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"फोन स्थिति र पहिचान पढ्नुहोस्"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"उपकरणको फोन विशेषताहरूको पहुँच गर्न अनुप्रयोगलाई अनुमति दिन्छ। यस अनुमतिले फोन नम्बर र उपकरणको IDs, कल सक्षम छ कि छैन र कलद्वारा जोडिएको टाढाको नम्बर निर्धारण गर्न अनुमति दिन्छ।"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"फोन नम्बर पढ्ने"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"यस अनुप्रयोगलाई यस यन्त्रको फोन नम्बरमाथि पहुँच राख्न दिनुहोस्।"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ट्याब्लेटलाई निन्द्रामा जानबाट रोक्नुहोस्"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV निभ्नबाट जोगाउनुहोस्"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"फोनलाई निदाउनबाट रोक्नुहोस्"</string>
@@ -553,30 +555,30 @@
<item msgid="1735177144948329370">"घरको फ्याक्स"</item>
<item msgid="603878674477207394">"पेजर"</item>
<item msgid="1650824275177931637">"अन्य"</item>
- <item msgid="9192514806975898961">"अनुकूलन"</item>
+ <item msgid="9192514806975898961">"आफू अनुकूल"</item>
</string-array>
<string-array name="emailAddressTypes">
<item msgid="8073994352956129127">"गृह"</item>
<item msgid="7084237356602625604">"काम"</item>
<item msgid="1112044410659011023">"अन्य"</item>
- <item msgid="2374913952870110618">"अनुकूलन"</item>
+ <item msgid="2374913952870110618">"आफू अनुकूल"</item>
</string-array>
<string-array name="postalAddressTypes">
<item msgid="6880257626740047286">"गृह"</item>
<item msgid="5629153956045109251">"काम"</item>
<item msgid="4966604264500343469">"अन्य"</item>
- <item msgid="4932682847595299369">"अनुकूलन"</item>
+ <item msgid="4932682847595299369">"आफू अनुकूल"</item>
</string-array>
<string-array name="imAddressTypes">
<item msgid="1738585194601476694">"गृह"</item>
<item msgid="1359644565647383708">"काम"</item>
<item msgid="7868549401053615677">"अन्य"</item>
- <item msgid="3145118944639869809">"अनुकूलन"</item>
+ <item msgid="3145118944639869809">"आफू अनुकूल"</item>
</string-array>
<string-array name="organizationTypes">
<item msgid="7546335612189115615">"काम गर्नुहोस्"</item>
<item msgid="4378074129049520373">"अन्य"</item>
- <item msgid="3455047468583965104">"अनुकूलन"</item>
+ <item msgid="3455047468583965104">"आफू अनुकूल"</item>
</string-array>
<string-array name="imProtocols">
<item msgid="8595261363518459565">"AIM"</item>
@@ -588,7 +590,7 @@
<item msgid="2506857312718630823">"ICQ"</item>
<item msgid="1648797903785279353">"Jabber"</item>
</string-array>
- <string name="phoneTypeCustom" msgid="1644738059053355820">"अनुकूलन"</string>
+ <string name="phoneTypeCustom" msgid="1644738059053355820">"आफू अनुकूल"</string>
<string name="phoneTypeHome" msgid="2570923463033985887">"गृह"</string>
<string name="phoneTypeMobile" msgid="6501463557754751037">"मोबाइल"</string>
<string name="phoneTypeWork" msgid="8863939667059911633">"काम"</string>
@@ -609,24 +611,24 @@
<string name="phoneTypeWorkPager" msgid="649938731231157056">"कार्य पेजर"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"सहायक"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
- <string name="eventTypeCustom" msgid="7837586198458073404">"अनुकूलन"</string>
+ <string name="eventTypeCustom" msgid="7837586198458073404">"आफू अनुकूल"</string>
<string name="eventTypeBirthday" msgid="2813379844211390740">"जन्मदिन"</string>
<string name="eventTypeAnniversary" msgid="3876779744518284000">"वार्षिक समारोह"</string>
<string name="eventTypeOther" msgid="7388178939010143077">"अन्य"</string>
- <string name="emailTypeCustom" msgid="8525960257804213846">"अनुकूलन"</string>
+ <string name="emailTypeCustom" msgid="8525960257804213846">"आफू अनुकूल"</string>
<string name="emailTypeHome" msgid="449227236140433919">"गृह"</string>
<string name="emailTypeWork" msgid="3548058059601149973">"काम"</string>
<string name="emailTypeOther" msgid="2923008695272639549">"अन्य"</string>
<string name="emailTypeMobile" msgid="119919005321166205">"मोबाइल"</string>
- <string name="postalTypeCustom" msgid="8903206903060479902">"अनुकूलन"</string>
+ <string name="postalTypeCustom" msgid="8903206903060479902">"आफू अनुकूल"</string>
<string name="postalTypeHome" msgid="8165756977184483097">"गृह"</string>
<string name="postalTypeWork" msgid="5268172772387694495">"काम"</string>
<string name="postalTypeOther" msgid="2726111966623584341">"अन्य"</string>
- <string name="imTypeCustom" msgid="2074028755527826046">"अनुकूलन"</string>
+ <string name="imTypeCustom" msgid="2074028755527826046">"आफू अनुकूल"</string>
<string name="imTypeHome" msgid="6241181032954263892">"गृह"</string>
<string name="imTypeWork" msgid="1371489290242433090">"काम"</string>
<string name="imTypeOther" msgid="5377007495735915478">"अन्य"</string>
- <string name="imProtocolCustom" msgid="6919453836618749992">"अनुकूलन"</string>
+ <string name="imProtocolCustom" msgid="6919453836618749992">"आफू अनुकूल"</string>
<string name="imProtocolAim" msgid="7050360612368383417">"AIM"</string>
<string name="imProtocolMsn" msgid="144556545420769442">"Windows Live"</string>
<string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo"</string>
@@ -638,8 +640,8 @@
<string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string>
<string name="orgTypeWork" msgid="29268870505363872">"काम"</string>
<string name="orgTypeOther" msgid="3951781131570124082">"अन्य"</string>
- <string name="orgTypeCustom" msgid="225523415372088322">"अनुकूलन"</string>
- <string name="relationTypeCustom" msgid="3542403679827297300">"अनुकूलन"</string>
+ <string name="orgTypeCustom" msgid="225523415372088322">"आफू अनुकूल"</string>
+ <string name="relationTypeCustom" msgid="3542403679827297300">"आफू अनुकूल"</string>
<string name="relationTypeAssistant" msgid="6274334825195379076">"सहायक"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"भाइ"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"सन्तान"</string>
@@ -653,8 +655,8 @@
<string name="relationTypeReferredBy" msgid="101573059844135524">"द्वारा उल्लिखित"</string>
<string name="relationTypeRelative" msgid="1799819930085610271">"आफन्त"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"बहिनी"</string>
- <string name="relationTypeSpouse" msgid="394136939428698117">"पति-पत्नि"</string>
- <string name="sipAddressTypeCustom" msgid="2473580593111590945">"अनुकूलन"</string>
+ <string name="relationTypeSpouse" msgid="394136939428698117">"पति-पत्नी"</string>
+ <string name="sipAddressTypeCustom" msgid="2473580593111590945">"आफू अनुकूल"</string>
<string name="sipAddressTypeHome" msgid="6093598181069359295">"गृह"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"काम गर्नुहोस्"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"अन्य"</string>
@@ -1029,7 +1031,7 @@
<string name="smv_process" msgid="5120397012047462446">"प्रक्रिया <xliff:g id="PROCESS">%1$s</xliff:g> यसको आफ्नै कडामोड नीतिका कारण उल्लङ्घन गरिएको छ।"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"एन्ड्रोइड अपग्रेड हुँदैछ…"</string>
<string name="android_start_title" msgid="8418054686415318207">"Android शुरू हुँदैछ..."</string>
- <string name="android_upgrading_fstrim" msgid="8036718871534640010">"भण्डारण अनुकूलन गर्दै।"</string>
+ <string name="android_upgrading_fstrim" msgid="8036718871534640010">"भण्डारण आफू अनुकूल गर्दै।"</string>
<string name="android_upgrading_notification_title" msgid="8428357096969413169">"Android को अद्यावधिकलाई सम्पन्न गर्दै…"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"स्तरवृद्धि सम्पन्न नभएसम्म केही अनुप्रयोगहरू राम्ररी काम नगर्न सक्छन्"</string>
<string name="app_upgrading_toast" msgid="3008139776215597053">"<xliff:g id="APPLICATION">%1$s</xliff:g> को स्तरवृद्धि हुँदैछ…"</string>
@@ -1102,8 +1104,8 @@
<string name="wifi_connect_alert_message" msgid="6451273376815958922">"अनुप्रयोग %1$s Wifi सञ्जाल %2$s मा जडान गर्न चाहन्छ"</string>
<string name="wifi_connect_default_application" msgid="7143109390475484319">"एउटा अनुप्रयोग"</string>
<string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi प्रत्यक्ष"</string>
- <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi सिधा सुरु गर्नुहोस्। यसले Wi-Fi ग्राहक/हट्स्पटलाई बन्द गराउने छ।"</string>
- <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi सिधा सुरु हुन सकेन।"</string>
+ <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi सीधा सुरु गर्नुहोस्। यसले Wi-Fi ग्राहक/हट्स्पटलाई बन्द गराउने छ।"</string>
+ <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi सीधा सुरु हुन सकेन।"</string>
<string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi प्रत्यक्ष खुल्ला छ"</string>
<string name="wifi_p2p_enabled_notification_message" msgid="8064677407830620023">"सेटिङहरूका लागि ट्याप गर्नुहोस्"</string>
<string name="accept" msgid="1645267259272829559">"स्वीकार्नुहोस्"</string>
@@ -1216,6 +1218,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"स्थापित सत्र पढ्न अनुप्रयोगलाई अनुमति दिनुहोस्। यसले सक्रिय प्याकेज प्रतिष्ठानहरू बारेमा विवरण हेर्ने अनुमति दिन्छ।"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"स्थापना प्याकेजहरू अनुरोध गर्नुहोस्"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"प्याकेजहरूको स्थापना अनुरोध गर्न अनुप्रयोगलाई अनुमति दिन्छ।"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ब्याट्री सम्बन्धी अनुकूलनहरूलाई बेवास्ता गर्न सोध्नुहोस्"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"कुनै अनुप्रयोगलाई त्यसका ब्याट्री सम्बन्धी अनुकूलनहरूलाई बेवास्ता गर्नका लागि अनुमति माग्न दिन्छ।"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"जुम नियन्त्रणको लागि दुई चोटि ट्याप गर्नुहोस्"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"विजेट थप गर्न सकिँदैन।"</string>
<string name="ime_action_go" msgid="8320845651737369027">"जानुहोस्"</string>
@@ -1566,10 +1570,8 @@
<string name="select_year" msgid="7952052866994196170">"वर्ष चयन गर्नुहोस्"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> हटाइयो"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"कार्यालयको दोस्रो <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"कार्यालयको तेस्रो <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"यस स्क्रिनलाई अनपिन गर्न पछाडि बटनलाई छोइराख्नुहोस्।"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"अनुप्रयोग पिन गरियो: यस यन्त्रमा अनपिन गर्ने अनुमति छैन।"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"स्क्रिन पिन गरियो"</string>
@@ -1689,5 +1691,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"अहिले रिसेट गर्नुहोस्"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> लाई असक्षम गरियो"</string>
<string name="conference_call" msgid="3751093130790472426">"सम्मेलन कल"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"उपकरणको वर्णन गर्ने पपअप"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"उपकरणको वर्णन"</string>
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index f7c76cd..5c677be 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Hiermee kan de app de IMS-service gebruiken om te bellen zonder je tussenkomst."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"telefoonstatus en -identiteit lezen"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Hiermee kan de app toegang krijgen tot de telefoonfuncties van het apparaat, Met deze toestemming kan de app het telefoonnummer en de apparaat-ID\'s bepalen, of een oproep actief is, en het andere telefoonnummer waarmee wordt gebeld."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"telefoonnummer lezen"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Hiermee kan de app toegang krijgen tot het telefoonnummer van het apparaat."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"voorkomen dat tablet overschakelt naar slaapmodus"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"voorkomen dat tv overschakelt naar slaapmodus"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"voorkomen dat telefoon overschakelt naar slaapmodus"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Hiermee wordt een app toegestaan installatiesessies te lezen. Zo kan de app informatie bekijken over actieve pakketinstallaties."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"installatiepakketten aanvragen"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Hiermee kan een app installatie van pakketten aanvragen."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"vragen om batterijoptimalisatie te negeren"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Hiermee kan een app toestemming vragen om batterijoptimalisatie voor die app te negeren."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tik twee keer voor zoomregeling"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Kan widget niet toevoegen."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ga"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Jaar selecteren"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> verwijderd"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Werk <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2e <xliff:g id="LABEL">%1$s</xliff:g>, werk"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3e <xliff:g id="LABEL">%1$s</xliff:g>, werk"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Tik op Terug en houd vast om dit scherm los te maken."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App is vastgezet: losmaken is niet toegestaan op dit apparaat."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Scherm vastgezet"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Nu resetten"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> uitgeschakeld"</string>
<string name="conference_call" msgid="3751093130790472426">"Telefonische vergadering"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Pop-up met knopinfo"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Knopinfo"</string>
</resources>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index 39c5dfa..c1bfad7 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -40,7 +40,7 @@
<string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> ਸਕਿੰਟ"</string>
<string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> ਸਕਿੰਟ"</string>
<string name="untitled" msgid="4638956954852782576">"<ਬਿਨਾਂ ਸਿਰਲੇਖ>"</string>
- <string name="emptyPhoneNumber" msgid="7694063042079676517">"(ਕੋਈ ਫੋਨ ਨੰਬਰ ਨਹੀਂ)"</string>
+ <string name="emptyPhoneNumber" msgid="7694063042079676517">"(ਕੋਈ ਫ਼ੋਨ ਨੰਬਰ ਨਹੀਂ)"</string>
<string name="unknownName" msgid="6867811765370350269">"ਅਗਿਆਤ"</string>
<string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"ਵੌਇਸਮੇਲ"</string>
<string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
@@ -252,7 +252,7 @@
<string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
<string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS ਸੁਨੇਹੇ ਭੇਜਣ ਅਤੇ ਦੇਖਣ"</string>
<string name="permgrouplab_storage" msgid="1971118770546336966">"ਸਟੋਰੇਜ"</string>
- <string name="permgroupdesc_storage" msgid="637758554581589203">"ਆਪਣੀ ਡੀਵਾਈਸ ’ਤੇ ਫੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਫਾਈਲਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
+ <string name="permgroupdesc_storage" msgid="637758554581589203">"ਆਪਣੀ ਡੀਵਾਈਸ ’ਤੇ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਫਾਈਲਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"ਮਾਈਕ੍ਰੋਫੋਨ"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"ਔਡੀਓ ਰਿਕਾਰਡ ਕਰਨ"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"ਕੈਮਰਾ"</string>
@@ -376,7 +376,9 @@
<string name="permlab_accessImsCallService" msgid="3574943847181793918">"IMS ਕਾਲ ਸੇਵਾ ਤੱਕ ਪਹੁੰਚ"</string>
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਕਾਲਾਂ ਕਰਨ ਲਈ IMS ਸੇਵਾ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ਫੋਨ ਸਥਿਤੀ ਅਤੇ ਪਛਾਣ ਪੜ੍ਹੋ"</string>
- <string name="permdesc_readPhoneState" msgid="1639212771826125528">"ਐਪ ਨੂੰ ਡੀਵਾਈਸ ਦੀਆਂ ਫੋਨ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਅਨੁਮਤੀ ਐਪ ਨੂੰ ਫੋਨ ਨੰਬਰ ਅਤੇ ਡੀਵਾਈਸ ID ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ, ਇੱਕ ਕਾਲ ਸਕਿਰਿਆ ਹੈ ਜਾਂ ਨਹੀਂ ਅਤੇ ਰਿਮੋਟ ਨੰਬਰ ਇੱਕ ਕਾਲ ਨਾਲ ਕਨੈਕਟ ਹੈ ਜਾਂ ਨਹੀਂ।"</string>
+ <string name="permdesc_readPhoneState" msgid="1639212771826125528">"ਐਪ ਨੂੰ ਡੀਵਾਈਸ ਦੀਆਂ ਫੋਨ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਅਨੁਮਤੀ ਐਪ ਨੂੰ ਫ਼ੋਨ ਨੰਬਰ ਅਤੇ ਡੀਵਾਈਸ ID ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ, ਇੱਕ ਕਾਲ ਸਕਿਰਿਆ ਹੈ ਜਾਂ ਨਹੀਂ ਅਤੇ ਰਿਮੋਟ ਨੰਬਰ ਇੱਕ ਕਾਲ ਨਾਲ ਕਨੈਕਟ ਹੈ ਜਾਂ ਨਹੀਂ।"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ਫ਼ੋਨ ਨੰਬਰ ਪੜ੍ਹੋ"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"ਡੀਵਾਈਸ ਦੇ ਫ਼ੋਨ ਨੰਬਰ \'ਤੇ ਪਹੁੰਚ ਕਰਨ ਲਈ ਐਪ ਨੂੰ ਇਜਾਜ਼ਤ ਦਿੰਦੀ ਹੈ।"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ਟੈਬਲੇਟ ਨੂੰ ਸਲੀਪਿੰਗ ਤੋਂ ਰੋਕੋ"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV ਨੂੰ ਸਲੀਪਿੰਗ ਤੋਂ ਰੋਕੋ"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ਫੋਨ ਨੂੰ ਸਲੀਪਿੰਗ ਤੋਂ ਰੋਕੋ"</string>
@@ -549,7 +551,7 @@
<item msgid="8901098336658710359">"ਘਰ"</item>
<item msgid="869923650527136615">"ਮੋਬਾਈਲ"</item>
<item msgid="7897544654242874543">"ਕੰਮ"</item>
- <item msgid="1103601433382158155">"ਦਫ਼ਤਰ ਦੀ ਫੈਕਸ"</item>
+ <item msgid="1103601433382158155">"ਕਾਰਜ-ਸਥਾਨ ਫੈਕਸ"</item>
<item msgid="1735177144948329370">"ਘਰ ਦੀ ਫੈਕਸ"</item>
<item msgid="603878674477207394">"ਪੇਜਰ"</item>
<item msgid="1650824275177931637">"ਹੋਰ"</item>
@@ -592,7 +594,7 @@
<string name="phoneTypeHome" msgid="2570923463033985887">"ਘਰ"</string>
<string name="phoneTypeMobile" msgid="6501463557754751037">"ਮੋਬਾਈਲ"</string>
<string name="phoneTypeWork" msgid="8863939667059911633">"ਕੰਮ"</string>
- <string name="phoneTypeFaxWork" msgid="3517792160008890912">"ਦਫ਼ਤਰ ਦੀ ਫੈਕਸ"</string>
+ <string name="phoneTypeFaxWork" msgid="3517792160008890912">"ਕਾਰਜ-ਸਥਾਨ ਫੈਕਸ"</string>
<string name="phoneTypeFaxHome" msgid="2067265972322971467">"ਘਰ ਦੀ ਫੈਕਸ"</string>
<string name="phoneTypePager" msgid="7582359955394921732">"ਪੇਜਰ"</string>
<string name="phoneTypeOther" msgid="1544425847868765990">"ਹੋਰ"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"ਮੀਡੀਆ ਵੌਲਿਊਮ"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"ਸੂਚਨਾ ਵੌਲਿਊਮ"</string>
<string name="ringtone_default" msgid="3789758980357696936">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਰਿੰਗਟੋਨ"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ਪੂਰਵ-ਨਿਰਧਾਰਤ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ਕੋਈ ਨਹੀਂ"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"ਰਿੰਗਟੋਨਾਂ"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"ਅਲਾਰਮ ਧੁਨੀਆਂ"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"ਸੂਚਨਾ ਧੁਨੀਆਂ"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"ਅਗਿਆਤ"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Wi-Fi ਨੈੱਟਵਰਕਸ ਉਪਲਬਧ</item>
<item quantity="other">Wi-Fi ਨੈੱਟਵਰਕਸ ਉਪਲਬਧ</item>
@@ -1152,7 +1150,7 @@
<string name="usb_charging_notification_title" msgid="6895185153353640787">"ਇਹ ਡੀਵਾਈਸ USB ਰਾਹੀਂ ਚਾਰਜ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
<string name="usb_supplying_notification_title" msgid="5310642257296510271">"ਨੱਥੀ ਕੀਤੀ ਡੀਵਾਈਸ ਨੂੰ USB ਰਾਹੀਂ ਪਾਵਰ ਮਿਲ ਰਹੀ ਹੈ"</string>
<string name="usb_mtp_notification_title" msgid="8396264943589760855">"ਫ਼ਾਈਲ ਟ੍ਰਾਂਸਫ਼ਰ ਲਈ USB"</string>
- <string name="usb_ptp_notification_title" msgid="1347328437083192112">"ਫੋਟੋ ਟ੍ਰਾਂਸਫ਼ਰ ਲਈ USB"</string>
+ <string name="usb_ptp_notification_title" msgid="1347328437083192112">"ਫ਼ੋਟੋ ਟ੍ਰਾਂਸਫ਼ਰ ਲਈ USB"</string>
<string name="usb_midi_notification_title" msgid="4850904915889144654">"MIDI ਲਈ USB"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"ਇੱਕ USB ਐਕਸੈਸਰੀ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="usb_notification_message" msgid="3370903770828407960">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ।"</string>
@@ -1174,7 +1172,7 @@
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> ਤਿਆਰ ਹੋ ਰਿਹਾ ਹੈ"</string>
<string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ਤਰੁੱਟੀਆਂ ਦੀ ਜਾਂਚ ਕਰ ਰਿਹਾ ਹੈ"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"ਨਵੇਂ <xliff:g id="NAME">%s</xliff:g> ਦਾ ਪਤਾ ਲਗਾਇਆ ਗਿਆ"</string>
- <string name="ext_media_ready_notification_message" msgid="4083398150380114462">"ਫੋਟੋਆਂ ਅਤੇ ਮੀਡੀਆ ਨੂੰ ਟ੍ਰਾਂਸਫ਼ਰ ਕਰਨ ਲਈ"</string>
+ <string name="ext_media_ready_notification_message" msgid="4083398150380114462">"ਫ਼ੋਟੋਆਂ ਅਤੇ ਮੀਡੀਆ ਨੂੰ ਟ੍ਰਾਂਸਫ਼ਰ ਕਰਨ ਲਈ"</string>
<string name="ext_media_unmountable_notification_title" msgid="8295123366236989588">"ਕਰਪਟਿਡ <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_message" msgid="2343202057122495773">"<xliff:g id="NAME">%s</xliff:g> ਗ਼ਲਤ ਹੈ। ਠੀਕ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"ਅਸਮਰਥਿਤ <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਇੰਸਟੌਲ ਸੈਸ਼ਨ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਇਸਨੂੰ ਸਕਿਰਿਆ ਪੈਕੇਜ ਇੰਸਟੌਲੇਸ਼ਨਾਂ ਬਾਰੇ ਵੇਰਵੇ ਦੇਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ਪੈਕੇਜ ਸਥਾਪਿਤ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕਰੋ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ਪੈਕੇਜ ਦੀ ਸਥਾਪਨਾ ਦੀ ਬੇਨਤੀ ਕਰਨ ਲਈ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਅਨੁਮਤੀ ਦਿੰਦਾ ਹੈ"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ਬੈਟਰੀ ਸੁਯੋਗਤਾਵਾਂ ਨੂੰ ਅਣਡਿੱਠ ਕਰਨ ਲਈ ਪੁੱਛੋ"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"ਕਿਸੇ ਐਪ ਨੂੰ ਉਸ ਵਾਸਤੇ ਬੈਟਰੀ ਸੁਯੋਗਤਾਵਾਂ ਨੂੰ ਅਣਡਿੱਠ ਕਰਨ ਲਈ ਇਜਾਜ਼ਤ ਵਾਸਤੇ ਪੁੱਛਣ ਲਈ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ਜ਼ੂਮ ਕੰਟਰੋਲ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ਵਿਜੇਟ ਨਹੀਂ ਜੋੜ ਸਕਿਆ।"</string>
<string name="ime_action_go" msgid="8320845651737369027">"ਜਾਓ"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"ਸਾਲ ਚੁਣੋ"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ਹਟਾਇਆ ਗਿਆ"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ਕੰਮ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"ਦੂਸਰੀ ਕਾਰਜ-ਸਥਾਨ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"ਤੀਸਰੀ ਕਾਰਜ-ਸਥਾਨ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ਇਸ ਸਕ੍ਰੀਨ ਨੂੰ ਅਨਪਿੰਨ ਕਰਨ ਲਈ, ਸਪਰਸ਼ ਕਰੋ & ਦਬਾਈ ਰੱਖੋ।"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ਐਪ ਪਿੰਨਡ ਹੈ: ਇਸ ਡੀਵਾਈਸ ਤੇ ਅਨਪਿਨ ਕਰਨ ਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ।"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ਸਕ੍ਰੀਨ ਪਿੰਨ ਕੀਤੀ"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ਹੁਣੇ ਮੁੜ-ਸੈੱਟ ਕਰੋ"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"ਕਾਨਫਰੰਸ ਕਾਲ"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ਟੂਲਟਿਪ"</string>
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 4ffd963..8c80ab5 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Zezwala aplikacji na korzystanie z usługi komunikatora, by nawiązywać połączenia bez Twojego udziału."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"odczytywanie stanu i informacji o telefonie"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Pozwala aplikacji na dostęp do funkcji telefonicznych urządzenia. Aplikacja z tym uprawnieniem może odczytać numer telefonu i identyfikator urządzenia, sprawdzić, czy połączenie jest aktywne, oraz poznać numer, z którym jest nawiązane połączenie."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"odczyt numeru telefonu"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Zezwala aplikacji na dostęp do numeru telefonu urządzenia."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zapobieganie przechodzeniu tabletu do trybu uśpienia"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"powstrzymywanie usypiania telewizora"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"zapobieganie przejściu telefonu w stan uśpienia"</string>
@@ -1260,6 +1262,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Pozwala aplikacji odczytywać sesje instalacji. Umożliwia to jej na poznanie szczegółów aktywnych instalacji pakietów."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"żądanie instalacji pakietów"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Zezwala aplikacji żądanie instalacji pakietów."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"Prośba o ignorowanie optymalizacji wykorzystania baterii"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Zezwala aplikacji na proszenie o uprawnienia do ignorowania optymalizacji wykorzystania baterii w przypadku danej aplikacji."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Dotknij dwukrotnie, aby sterować powiększeniem"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nie można dodać widżetu."</string>
<string name="ime_action_go" msgid="8320845651737369027">"OK"</string>
@@ -1614,10 +1618,8 @@
<string name="select_year" msgid="7952052866994196170">"Wybierz rok"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> usunięte"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (praca)"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> – praca 2"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> – praca 3"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Aby odpiąć ten ekran, naciśnij i przytrzymaj Wstecz."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacja jest przypięta. Nie możesz jej odpiąć na tym urządzeniu."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran przypięty"</string>
@@ -1755,5 +1757,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Resetuj teraz"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Wyłączono: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Połączenie konferencyjne"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Wyskakujące okno z etykietką"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Etykietka"</string>
</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 482c1e9..26fb6bb 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite que o app use o serviço de mensagens instantâneas para fazer chamadas sem sua intervenção."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ler status e identidade do telefone"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que o app acesse os recursos de telefonia do dispositivo. Esta permissão autoriza o app a determinar o número de telefone e IDs de dispositivo, quando uma chamada está ativa, e o número remoto conectado a uma chamada."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ler número de telefone"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permite que o app acesse o número de telefone do dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir modo de inatividade do tablet"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"impedir a suspensão da TV"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"impedir modo de inatividade do telefone"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que um app leia sessões de instalação. Isso permite que ele veja detalhes sobre as instalações de pacote ativas."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar pacotes de instalação"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite que um app solicite a instalação de pacotes."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"solicitar que as otimizações de bateria sejam ignoradas"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Permite que um app peça permissão para ignorar as otimizações de bateria para esse app."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Toque duas vezes para ter controle do zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Não foi possível adicionar widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ir"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Selecione o ano"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> excluído"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Trabalho: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Segundo <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Terceiro <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Para liberar esta tela, toque no botão \"Voltar\" e mantenha-o pressionado."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"O app está fixado. A liberação não é permitida neste dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Tela fixada"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Reiniciar agora"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Widget <xliff:g id="LABEL">%1$s</xliff:g> desativado"</string>
<string name="conference_call" msgid="3751093130790472426">"Teleconferência"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Pop-up de dica"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Dica"</string>
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 3f9417e..18bb723 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite que a aplicação utilize o serviço IMS para fazer chamadas sem a sua intervenção."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ler o estado e a identidade do telemóvel"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que a aplicação aceda às funcionalidades de telefone do dispositivo. Esta autorização permite que a aplicação determine o número de telefone e IDs do dispositivo, se alguma chamada está ativa e qual o número remoto ligado por uma chamada."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ler o número de telefone"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permite que a aplicação aceda ao número de telefone do dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir que o tablet entre em inactividade"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"impedir a TV de entrar no modo de suspensão"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"impedir modo de inactividade do telefone"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que uma aplicação leia sessões de instalação. Isto permite que veja detalhes acerca de instalações de pacotes ativas."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar pacotes de instalação"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite que uma aplicação solicite a instalação de pacotes."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"pedir para ignorar as otimizações da bateria"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Permite que uma aplicação solicite autorização para ignorar as otimizações da bateria para a mesma."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tocar duas vezes para controlar o zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Não foi possível adicionar widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ir"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Selecionar ano"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminado"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2.º <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3.º <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Para soltar este ecrã, toque sem soltar em Anterior."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"A aplicação está fixa: não é permitido soltá-la neste dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ecrã fixo"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Repor agora"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> desativado"</string>
<string name="conference_call" msgid="3751093130790472426">"Conferência"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Pop-up de sugestão"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Sugestão"</string>
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 482c1e9..26fb6bb 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite que o app use o serviço de mensagens instantâneas para fazer chamadas sem sua intervenção."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ler status e identidade do telefone"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que o app acesse os recursos de telefonia do dispositivo. Esta permissão autoriza o app a determinar o número de telefone e IDs de dispositivo, quando uma chamada está ativa, e o número remoto conectado a uma chamada."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ler número de telefone"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permite que o app acesse o número de telefone do dispositivo."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir modo de inatividade do tablet"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"impedir a suspensão da TV"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"impedir modo de inatividade do telefone"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que um app leia sessões de instalação. Isso permite que ele veja detalhes sobre as instalações de pacote ativas."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar pacotes de instalação"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite que um app solicite a instalação de pacotes."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"solicitar que as otimizações de bateria sejam ignoradas"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Permite que um app peça permissão para ignorar as otimizações de bateria para esse app."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Toque duas vezes para ter controle do zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Não foi possível adicionar widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ir"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Selecione o ano"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> excluído"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Trabalho: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Segundo <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Terceiro <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Para liberar esta tela, toque no botão \"Voltar\" e mantenha-o pressionado."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"O app está fixado. A liberação não é permitida neste dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Tela fixada"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Reiniciar agora"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Widget <xliff:g id="LABEL">%1$s</xliff:g> desativado"</string>
<string name="conference_call" msgid="3751093130790472426">"Teleconferência"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Pop-up de dica"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Dica"</string>
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 5735f7c..938df9a 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -380,6 +380,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite aplicației să folosească serviciul IMS pentru apeluri, fără intervenția dvs."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"citește starea și identitatea telefonului"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite aplicației să acceseze funcțiile de telefon ale dispozitivului. Cu această permisiune aplicația stabilește numărul de telefon și ID-urile de dispozitiv, dacă un apel este activ, precum și numărul de la distanță conectat printr-un apel."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"să citească numărul de telefon"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Permite aplicației să acceseze numărul de telefon al dispozitivului."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"împiedicarea computerului tablet PC să intre în repaus"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"împiedică intrarea televizorului în stare de inactivitate"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"împiedicare intrare telefon în repaus"</string>
@@ -1082,16 +1084,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Volumul media"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Volum notificare"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Ton de apel prestabilit"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Prestabilit (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Niciunul"</string>
- <string name="ringtone_picker_title" msgid="3515143939175119094">"Tonuri de sonerie"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title" msgid="3515143939175119094">"Tonuri de apel"</string>
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Sunete de alarmă"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Sunete pentru notificare"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Necunoscut"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="few">Rețele Wi-Fi disponibile</item>
<item quantity="other">Rețele Wi-Fi disponibile</item>
@@ -1239,6 +1237,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite unei aplicații accesul la citirea sesiunilor de instalare. Aceasta poate vedea detalii despre instalările de pachete active."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"să solicite pachete de instalare"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite unei aplicații să solicite instalarea pachetelor."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"să solicite ignorarea optimizărilor bateriei"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Permite unei aplicații să solicite permisiunea de a ignora optimizările bateriei pentru aplicația respectivă."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Apăsați de două ori pentru a controla mărirea/micșorarea"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nu s-a putut adăuga widgetul."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Accesați"</string>
@@ -1591,10 +1591,8 @@
<string name="select_year" msgid="7952052866994196170">"Selectați anul"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> a fost șters"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de serviciu"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> pentru serviciu (2)"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> pentru serviciu (3)"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Pentru a anula fixarea acestui ecran, atingeți lung opțiunea Înapoi."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplicația este fixată: Anularea fixării nu este permisă pe acest dispozitiv."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ecran fixat"</string>
@@ -1723,6 +1721,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Resetați acum"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> a fost dezactivat"</string>
<string name="conference_call" msgid="3751093130790472426">"Conferință telefonică"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Balon explicativ"</string>
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 0d6ca06..f03d783 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -90,7 +90,7 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Идентификация абонента по умолчанию не запрещена. След. вызов: разрешена"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Услуга не предоставляется."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Невозможно изменить параметр идентификатора вызывающего абонента."</string>
- <string name="RestrictedOnData" msgid="8653794784690065540">"Служба данных заблокирована."</string>
+ <string name="RestrictedOnData" msgid="8653794784690065540">"Передача данных заблокирована."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Служба экстренной помощи заблокирована."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Служба передачи голосовых сообщений заблокирована."</string>
<string name="RestrictedOnAllVoice" msgid="3396963652108151260">"Все службы передачи голосовых сообщений заблокированы."</string>
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Позволяет приложению совершать звонки с помощью службы IMS без вашего вмешательства."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"Получение данных о статусе телефона"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Приложение получит доступ к функциям телефона на устройстве. Кроме того, оно сможет определять номера телефонов и серийные номера моделей, состояние активности вызова, а также удаленные номера, с которыми установлено соединение."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"Чтение номера телефона"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Приложение получит доступ к телефонному номеру устройства."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"Отключение спящего режима"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"запрещать переход в спящий режим"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Отключение спящего режима"</string>
@@ -1260,6 +1262,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Чтение данных текущих сеансов установки пакетов."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"Запрос пакетов установки"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Приложение сможет запрашивать разрешения на установку пакетов."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"Без ограничения расхода батареи"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Разрешает приложению игнорировать ограничение на расход заряда батареи."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Нажмите дважды для изменения масштаба"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Не удалось добавить виджет."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Выбрать"</string>
@@ -1614,10 +1618,8 @@
<string name="select_year" msgid="7952052866994196170">"Выберите год"</string>
<string name="deleted_key" msgid="7659477886625566590">"Цифра <xliff:g id="KEY">%1$s</xliff:g> удалена"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Рабочий <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Задача 2: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Задача 3: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Чтобы открепить экран, нажмите и удерживайте кнопку \"Назад\"."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Включена блокировка в приложении. Ее отключение запрещено правилами организации."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Блокировка включена"</string>
@@ -1755,5 +1757,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Сбросить"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Виджет <xliff:g id="LABEL">%1$s</xliff:g> отключен"</string>
<string name="conference_call" msgid="3751093130790472426">"Конференц-связь"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Подсказка"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Подсказка"</string>
</resources>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 7526c1e..8d3eaa1 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -284,7 +284,7 @@
<string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"කෙටිමං අස්ථාපනය කරන්න"</string>
<string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"පරිශීලක මැදිහත්වීමෙන් තොරව මුල්තිර කෙටිමං එක් කිරීමට යෙදුමකට අවසර දෙයි."</string>
<string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"පිටවන ඇමතුම් වල මග වෙනස් කිරීම"</string>
- <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"ඇමතුම වෙනත් අංකයකට හරවා යැවීම හෝ ඇමතුම මුළුමනින්ම නැවත් වීම වැනි විකල්ප සමඟ පිටතට යන ඇමතුමකදී ඩයල් කළ අංකය බැලීමට යෙදුමට ඉඩ දෙන්න."</string>
+ <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"ඇමතුම වෙනත් අංකයකට හරවා යැවීම හෝ ඇමතුම මුළුමනින්ම නැවත්වීම වැනි විකල්ප සමඟ පිටතට යන ඇමතුමකදී අංකනය කළ අංකය බැලීමට යෙදුමට ඉඩ දෙයි."</string>
<string name="permlab_receiveSms" msgid="8673471768947895082">"කෙටි පණිවිඩ ලබාගැනීම (SMS)"</string>
<string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS පණිවිඩ ලැබීමට සහ ක්රියාත්මක කිරීමට යෙදුමට අවසර දෙන්න. මෙහි තේරුම යෙදුමට ඔබගේ උපාංගයට ලැබෙන පණිවිඩ අධීක්ෂණය කිරීමට හැකිවීම වන අතර, ඒවා ඔබට නොපෙන්වා මකා දැමීමටද හැකි වීමයි."</string>
<string name="permlab_receiveMms" msgid="1821317344668257098">"පෙළ පණිවුඩ ලබාගන්න (MMS)"</string>
@@ -376,7 +376,9 @@
<string name="permlab_accessImsCallService" msgid="3574943847181793918">"IMS ඇමතුම් සේවාවට පිවිසෙන්න"</string>
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"ඔබේ මැදිහත්වීමකින් තොරව ඇමතුම් සිදු කිරීමට IMS සේවාව භාවිතයට යෙදුමට ඉඩ දෙන්න."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"දුරකථනයේ තත්වය සහ අනන්යතාවය කියවීම"</string>
- <string name="permdesc_readPhoneState" msgid="1639212771826125528">"උපාංගයේ දුරකථන විශේෂාංග වෙත පිවිසීමට යෙදුමට අවසර දෙන්න. ඇමතුම සක්රිය වුවත් සහ ඇමතුමකින් දුරස්ථ අංකය සම්බන්ධ වුවත් දුරකථන අංකය සහ උපාංග ID හඳුනා ගැනීමට මෙම අවසරය යෙදුමට අවසර දෙයි."</string>
+ <string name="permdesc_readPhoneState" msgid="1639212771826125528">"උපාංගයේ දුරකථන විශේෂාංග වෙත ප්රවේශයට යෙදුමට ඉඩ දෙයි. ඇමතුම සක්රිය වුවත්, සහ ඇමතුමකින් දුරස්ථ අංකය සම්බන්ධ වුවත් දුරකථන අංකය සහ උපාංග ID හඳුනා ගැනීමට මෙම අවසරය යෙදුමට ඉඩ දෙයි."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"දුරකථන අංකය කියවන්න"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"උපාංගයේ දුරකථන අංකය වෙත පිවිසීමට යෙදුමට ඉඩ දෙන්න."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ටැබ්ලටය නින්දෙන් වැළක්වීම"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"රූපවාහිනිය නින්දට යාමෙන් නවත්වන්න"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"දුරකථනය නින්දට යාමෙන් වළකන්න"</string>
@@ -1061,16 +1063,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"මාධ්ය ශබ්දය"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"දැනුම්දීමේ ශබ්ද ත්රීවතාව"</string>
<string name="ringtone_default" msgid="3789758980357696936">"සුපුරුදු රින්ටෝනය සකසන්න"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"පෙරනිමි (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"කිසිවක් නැත"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"රිගින්ටෝන"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"එලාම හඬ"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"දැනුම්දීම් හඬ"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"නොදනී"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Wi-Fi ජාල තිබේ</item>
<item quantity="other">Wi-Fi ජාල තිබේ</item>
@@ -1216,6 +1214,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ස්ථාපන සැසිය කියවීමට යෙදුමට ඉඩ දෙන්න. සක්රිය පැකේජ ස්ථාපනය පිළිබඳ විස්තර බැලීමට එයට මෙයින් ඉඩ දෙයි."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ස්ථාපන පැකේජ ඉල්ලීම"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ස්ථාපන පැකේජ ඉල්ලීමට යෙදුමකට අවසර දීම."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"බැටරි ප්රශස්තකරණ නොසලකා හැරීමට ඉල්ලන්න"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"යෙදුමකට එම යෙදුම සඳහා බැටරි ප්රශස්තකරණ නොසලකා හැරීමට අවසර ඉල්ලීමට ඉඩ දෙයි."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"විශාලන පාලක සඳහා දෙවතාවක් තට්ටු කරන්න"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"විජටය එකතු කිරීමට නොහැකි විය."</string>
<string name="ime_action_go" msgid="8320845651737369027">"යන්න"</string>
@@ -1566,10 +1566,8 @@
<string name="select_year" msgid="7952052866994196170">"වසර තෝරන්න"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> මකා දමන ලදි"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2වන වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3වන වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"මෙම තිරය ඇමුණුම් ඉවත් කිරීමට, ස්පර්ශ කර අල්ලා ගෙන සිටින්න."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"යෙදුම අමුණා ඇත: ගැලවීමට මෙම උපාංගය මත ඉඩ දිය නොහැකිය."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"තිරය අගුළු දමා ඇත"</string>
@@ -1689,6 +1687,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"දැන් යළි සකසන්න"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"අබල කළ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"සම්මන්ත්රණ ඇමතුම"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"මෙවලම් ඉඟිය"</string>
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 7ff3ce2..2f44ed6 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Umožňuje aplikácii používať službu okamžitých správ (IMS) na volanie bez intervencie používateľa."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"čítať stav a identitu telefónu"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Umožňuje aplikácii pristupovať k telefónnym funkciám zariadenia. Aplikácia s týmto povolením môže určiť telefónne číslo a ID zariadenia, či práve prebieha hovor, a vzdialené číslo, s ktorým je prostredníctvom hovoru nadviazané spojenie."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"čítanie telefónneho čísla"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Umožňuje aplikácii pristupovať k telefónnemu číslu daného zariadenia."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zabránenie prechodu tabletu do režimu spánku"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"zabránenie televízoru v prechode do režimu spánku"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"deaktivovať režim spánku"</string>
@@ -649,10 +651,10 @@
<string name="relationTypeAssistant" msgid="6274334825195379076">"Asistent"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"Brat"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"Dieťa"</string>
- <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Partner(ka)"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Druh(-žka)"</string>
<string name="relationTypeFather" msgid="5228034687082050725">"Otec"</string>
<string name="relationTypeFriend" msgid="7313106762483391262">"Kamarát(ka)"</string>
- <string name="relationTypeManager" msgid="6365677861610137895">"Manažér"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"Vedúci(-a)"</string>
<string name="relationTypeMother" msgid="4578571352962758304">"Matka"</string>
<string name="relationTypeParent" msgid="4755635567562925226">"Rodič"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"Partner(ka)"</string>
@@ -1260,6 +1262,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Toto povolenie umožňuje aplikácii čítať relácie inštalácií a zobraziť tak podrobnosti o aktívnych inštaláciách balíkov."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"odosielanie žiadostí o inštaláciu balíkov"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Umožňuje aplikácii vyžiadať inštaláciu balíkov."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"požiadať o ignorovanie optimalizácií výdrže batérie"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Umožňuje aplikácii požiadať o povolenie ignorovať optimalizácie výdrže batérie pre danú aplikáciu."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Dvojitým klepnutím môžete ovládať priblíženie"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Miniaplikáciu sa nepodarilo pridať."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Hľadať"</string>
@@ -1614,10 +1618,8 @@
<string name="select_year" msgid="7952052866994196170">"Vyberte rok"</string>
<string name="deleted_key" msgid="7659477886625566590">"Číslo <xliff:g id="KEY">%1$s</xliff:g> bolo odstránené"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Práca – <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Ak chcete uvoľniť túto obrazovku, klepnite na tlačidlo Späť a podržte ho."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikácia je pripnutá. Uvoľnenie nie je na tomto zariadení povolené."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Obrazovka bola pripnutá"</string>
@@ -1755,5 +1757,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Resetovať"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Deaktivovaná miniaplikácia <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferenčný hovor"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Kontextové okno s popisom"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Popis"</string>
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index f7b8096..eda90a3 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Aplikaciji dovoljuje uporabo storitev IMS za opravljanje klicev brez vašega posredovanja."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"branje stanja in identitete telefona"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Aplikaciji omogoča dostop do funkcij telefona v napravi. S tem dovoljenjem lahko aplikacija določi telefonsko številko in ID-je naprave, določi lahko tudi, ali je klic aktiven, in oddaljeno številko, s katero je klic povezan."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"branje telefonske številke"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Aplikaciji dovoljuje dostop do telefonske številke naprave."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"preprečitev prehoda tabličnega računalnika v stanje pripravljenosti"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"preprečevanje preklopa televizorja v stanje pripravljenosti"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"preprečevanje prehoda v stanje pripravljenosti telefona"</string>
@@ -1105,16 +1107,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Glasnost predstavnosti"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Glasnost obvestila"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Privzeta melodija zvonjenja"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Privzeto (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Brez"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Melodije zvonjenja"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Zvoki alarma"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Zvoki obvestil"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Neznano"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Na voljo so omrežja Wi-Fi</item>
<item quantity="two">Na voljo so omrežja Wi-Fi</item>
@@ -1264,6 +1262,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Aplikaciji omogoča branje sej namestitev. Tako lahko bere podrobnosti o aktivnih namestitvah paketov."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"zahtevanje paketov za namestitev"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Aplikaciji omogoča zahtevanje namestitve paketov."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"Dovoljenje za prezrtje optimizacij akumulatorja"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Aplikaciji dovoljuje, da vpraša za dovoljenje, ali naj prezre optimizacije akumulatorja."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tapnite dvakrat za nadzor povečave/pomanjšave"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Pripomočka ni bilo mogoče dodati."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Pojdi"</string>
@@ -1618,10 +1618,8 @@
<string name="select_year" msgid="7952052866994196170">"Izberite leto"</string>
<string name="deleted_key" msgid="7659477886625566590">"Številka <xliff:g id="KEY">%1$s</xliff:g> je izbrisana"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> za delo"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. službeni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. službeni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Če želite odpeti ta zaslon, se dotaknite tipke za nazaj in jo pridržite."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacija je pripeta: v tej napravi odpenjanje ni dovoljeno."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Zaslon je pripet"</string>
@@ -1759,6 +1757,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Ponastavi"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> – onemogočeno"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferenčni klic"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Opis orodja"</string>
</resources>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index c3ccaca..8a05ff8 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Lejon aplikacionin të përdorë shërbimin IMS për të kryer telefonata pa ndërhyrjen tënde."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"lexo statusin e telefonit dhe identitetin"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Lejon aplikacionin të hyjë në funksionet telefonike të pajisjes. Kjo leje i mundëson aplikacionit të përcaktojë numrin e telefonit dhe ID-të e pajisjes, nëse një telefonatë është aktive apo nëse numri në distancë është i lidhur me një telefonatë."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"lexo numrin e telefonit"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Lejon që aplikacioni të ketë qasje te numri i telefonit i pajisjes."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"parandalo kalimin e tabletit në fjetje"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"parandalo kalimin e televizorit në fjetje"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"parandalo kalimin e telefonit në fjetje"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"volumi i klipit \"media\""</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Volumi i njoftimeve"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Zile e paracaktuar."</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"I parazgjedhur (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Asnjë"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Zilet"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Tingujt e alarmeve"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Tingujt e njoftimeve"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"E panjohur"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Rrjete Wi-Fi ofrohen për përdorim</item>
<item quantity="one">Një rrjet Wi-Fi ofrohet për përdorim</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Lejon një aplikacion të lexojë sesionet e instalimit. Kjo e lejon atë të shohë detaje rreth instalimeve të paketave aktive."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"kërko paketat e instalimit"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Lejon që një aplikacion të kërkojë instalimin e paketave."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"kërko të shpërfillësh optimizimet e baterisë"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Lejon që një aplikacion të kërkojë leje për të shpërfillur optimizimet e baterisë për atë aplikacion."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Trokit dy herë për të kontrolluar zmadhimin"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nuk mundi të shtonte miniaplikacion."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Shko"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Përzgjidh vitin"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> u fshi"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Puna <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> i dytë i punës"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> i tretë i punës"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Për të hequr gozhdimin e ekranit, prek dhe mbaj të shtypur \"Prapa\"."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Ekrani është i gozhduar. Anulimi i mbërthimit nuk lejohet nga organizata jote."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekrani u gozhdua"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Rivendos tani"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> u çaktivizua"</string>
<string name="conference_call" msgid="3751093130790472426">"Telefonatë konferencë"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Këshilla për veglën"</string>
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index da44a65..aab90e4 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -380,6 +380,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Дозвољава апликацији да користи услугу размене тренутних порука да би упућивала позиве без ваше интервенције."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"читање статуса и идентитета телефона"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Дозвољава апликацији да приступа функцијама телефона на уређају. Ова дозвола омогућава апликацији да утврди број телефона и ИД-ове уређаја, затим да ли је позив активан, као и број даљинског уређаја са којим је успостављен позив."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"читање броја телефона"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Дозвољава апликацији да приступа броју телефона на уређају."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"спречавање преласка таблета у стање спавања"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"спречавање ТВ-а да пређе у стање спавања"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"спречавање преласка телефона у стање спавања"</string>
@@ -1235,6 +1237,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Дозвољава апликацији да чита сесије инсталирања. То јој дозвољава да види детаље о активним инсталацијама пакета."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"захтевање пакета за инсталирање"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Омогућава да апликација захтева инсталацију пакета."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"тражење дозволе за игнорисање оптимизација батерије"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Дозвољава апликацији да тражи дозволу за игнорисање оптимизација батерије за ту апликацију."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Додирните двапут за контролу зумирања"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Није могуће додати виџет."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Иди"</string>
@@ -1587,10 +1591,8 @@
<string name="select_year" msgid="7952052866994196170">"Изаберите годину"</string>
<string name="deleted_key" msgid="7659477886625566590">"Избрисали сте <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> на послу"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. пословни <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. пословни имејл <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Да бисте откачили овај екран, додирните и задржите Назад."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Апликација је закачена: откачињање није дозвољено на овом уређају."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Екран је закачен"</string>
@@ -1719,5 +1721,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Ресетуј"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Виџет <xliff:g id="LABEL">%1$s</xliff:g> је онемогућен"</string>
<string name="conference_call" msgid="3751093130790472426">"Конференцијски позив"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Искачуће објашњење"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Објашњење"</string>
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 1bf5196..57fa538 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -82,10 +82,10 @@
<string name="RuacMmi" msgid="7827887459138308886">"Avvisande av oönskade irriterande samtal"</string>
<string name="CndMmi" msgid="3116446237081575808">"Leverans av nummer för inkommande samtal"</string>
<string name="DndMmi" msgid="1265478932418334331">"Stör ej"</string>
- <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Nummerpresentatören är begränsad som standard. Nästa samtal: Begränsad"</string>
- <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Nummerpresentatörens standardinställning är begränsad. Nästa samtal: Inte begränsad"</string>
- <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Nummerpresentatörens standardinställning är inte begränsad. Nästa samtal: Begränsad"</string>
- <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Nummerpresentatörens standardinställning är inte begränsad. Nästa samtal: Inte begränsad"</string>
+ <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Nummerpresentatören är blockerad som standard. Nästa samtal: Blockerad"</string>
+ <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Nummerpresentatörens standardinställning är blockerad. Nästa samtal: Inte blockerad"</string>
+ <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Nummerpresentatörens standardinställning är inte blockerad. Nästa samtal: Blockerad"</string>
+ <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Nummerpresentatörens standardinställning är inte blockerad. Nästa samtal: Inte blockerad"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Tjänsten är inte etablerad."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Det går inte att ändra inställningen för nummerpresentatör."</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Datatjänsten är blockerad."</string>
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Tillåter att appen använder tjänsten för snabbmeddelanden för att ringa samtal utan åtgärd från dig."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"läsa telefonens status och identitet"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Tillåter att appen kommer åt enhetens telefonfunktioner. Med den här behörigheten tillåts appen att identifiera mobilens telefonnummer och enhets-ID, om ett samtal pågår och vilket nummer samtalet är kopplat till."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"läsa telefonnumret"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Ger appen åtkomst till mobilnumret på enheten."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"förhindra att surfplattan går in i viloläge"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"förhindra att TV:n försätts i viloläge"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"förhindra att telefonen sätts i viloläge"</string>
@@ -650,7 +652,7 @@
<string name="relationTypeMother" msgid="4578571352962758304">"Mamma"</string>
<string name="relationTypeParent" msgid="4755635567562925226">"Förälder"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"Partner"</string>
- <string name="relationTypeReferredBy" msgid="101573059844135524">"Genom"</string>
+ <string name="relationTypeReferredBy" msgid="101573059844135524">"Känner genom"</string>
<string name="relationTypeRelative" msgid="1799819930085610271">"Släkting"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"Syster"</string>
<string name="relationTypeSpouse" msgid="394136939428698117">"Make/maka"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Tillåt appen att läsa installationssessioner. Det ger den tillgång till uppgifter om aktiva paketinstallationer."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"begära installationspaket"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Tillåter att en app begär paketinstallation."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"får be om tillstånd att ignorera batterioptimering"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Appen får be om tillstånd att ignorera batterioptimering."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Peka två gånger för zoomkontroll"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Det gick inte att lägga till widgeten."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Kör"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Välj år"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> har tagits bort"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> för arbetet"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Andra <xliff:g id="LABEL">%1$s</xliff:g> för jobbet"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Tredje <xliff:g id="LABEL">%1$s</xliff:g> för jobbet"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Om du vill lossa skärmen trycker du länge på Tillbaka."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Appen är fäst. Att lossa den är inte tillåtet på den här enheten."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skärmen är fäst"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Återställ nu"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> har inaktiverats"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferenssamtal"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Popup-fönster med beskrivning"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Beskrivning"</string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 1d3c7ac..0f6b875 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -375,6 +375,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Huruhusu programu kutumia huduma ya IMS kupiga simu bila udhibiti wako."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"kusoma hali na kitambulisho cha simu"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Huruhusu programu kufikia vipengele vya simu vilivyo kwenye kifaa. Idhini hii inaruhusu programu kutambua nambari ya simu na kifaa, kama kuna simu inayopigwa, na nambari ya mbali iliyounganishwa kwenye simu."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"kusoma nambari ya simu"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Inaruhusu programu kufikia nambari ya simu ya kifaa."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zuia kompyuta ndogo dhidi ya kulala"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"zuia runinga isiingie katika hali tuli"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"kuzuia simu isilale"</string>
@@ -1208,6 +1210,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Huruhusu programu kusoma vipindi vya kusanikisha. Hii huiruhusu kuona maelezo kuhusu usanikishaji wa programu unaoendelea."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"omba ruhusa ya kusakinisha vifurushi"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Huruhusu programu kuomba idhini ya kusakinisha vifurushi."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"omba kupuuza uimarishji wa betri"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Huruhusu programu kuomba ruhusa ya kupuuza uimarishaji wa betri katika programu yako."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Gonga mara mbili kwa udhibiti wa kuza"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Haikuweza kuongeza wijeti."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Nenda"</string>
@@ -1558,10 +1562,8 @@
<string name="select_year" msgid="7952052866994196170">"Chagua mwaka"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> kimefutwa"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Ya kazini <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> ya 2 ya Kazini"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> ya 3 ya Kazini"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Ili kubandua skrini hii, gusa na ushikilie Nyuma."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Programu imebanwa: Kubanuliwa hakuruhusiwi kwenye kifaa hiki."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skrini imebandikwa"</string>
@@ -1681,5 +1683,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Weka upya sasa"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> imezimwa"</string>
<string name="conference_call" msgid="3751093130790472426">"Simu ya Kongamano"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Kidirisha Ibukizi cha vidokezo"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Kidirisha cha vidokezo"</string>
</resources>
diff --git a/core/res/res/values-sw900dp/dimens.xml b/core/res/res/values-sw900dp/dimens.xml
new file mode 100644
index 0000000..11092b2
--- /dev/null
+++ b/core/res/res/values-sw900dp/dimens.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+*/
+-->
+<resources>
+
+ <!-- Height of the bottom navigation / system bar. -->
+ <dimen name="navigation_bar_height">56dp</dimen>
+
+ <!-- Height of the bottom navigation bar in landscape; often
+ the same as @dimen/navigation_bar_height -->
+ <dimen name="navigation_bar_height_landscape">56dp</dimen>
+
+</resources>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 46a4589..3f935c0 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"உங்கள் குறுக்கீடின்றி IMS சேவையைப் பயன்படுத்தி அழைப்பதற்கு, பயன்பாட்டை அனுமதிக்கும்."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"மொபைல் நிலை மற்றும் அடையாளத்தைப் படித்தல்"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"சாதனத்தின் மொபைல் அம்சங்களை அணுகப் பயன்பாட்டை அனுமதிக்கிறது. மொபைல் மற்றும் சாதன ஐடிகள், அழைப்பு செயலில் உள்ளதா மற்றும் அழைப்பு மூலம் இணைக்கப்பட்ட தொலைக் கட்டுப்பாட்டு எண் ஆகியவற்றைத் தீர்மானிக்க இந்த அனுமதி பயன்பாட்டை அனுமதிக்கிறது."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"மொபைல் எண்ணைப் படி"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"சாதனத்தின் மொபைல் எண்ணை அணுக, பயன்பாட்டை அனுமதிக்கும்."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"டேப்லெட் உறக்க நிலைக்குச் செல்வதைத் தடுத்தல்"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"டிவி உறக்கநிலைக்குச் செல்வதைத் தடுத்தல்"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"தொலைபேசி உறக்கநிலைக்குச் செல்வதைத் தடுத்தல்"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"மீடியாவின் ஒலியளவு"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"அறிவிப்பின் ஒலியளவு"</string>
<string name="ringtone_default" msgid="3789758980357696936">"இயல்புநிலை ரிங்டோன்"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"இயல்பு (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ஏதுமில்லை"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"ரிங்டோன்கள்"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"அலார ஒலிகள்"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"அறிவிப்பு ஒலிகள்"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"தெரியாதது"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">வைஃபை நெட்வொர்க்குகள் உள்ளன</item>
<item quantity="one">வைஃபை நெட்வொர்க் உள்ளது</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"நிறுவல் அமர்வுகளைப் படிக்க, பயன்பாட்டை அனுமதிக்கிறது. இது செயல்படும் தொகுப்பு நிறுவல்களைப் பற்றிய விவரங்களைப் பார்க்க அனுமதிக்கிறது."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"நிறுவல் தொகுப்புகளைக் கோருதல்"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"தொகுப்புகளின் நிறுவலைக் கோர, பயன்பாட்டை அனுமதிக்கும்."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"பேட்டரி மேம்படுத்தல்களைப் புறக்கணிப்பதற்கான அனுமதியைக் கோரு"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"பயன்பாட்டிற்கான பேட்டரி மேம்படுத்தல்களைப் புறக்கணிப்பதற்கான அனுமதியைக் கோர, பயன்பாட்டை அனுமதிக்கும்."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"அளவை மாற்றுவதற்கான கட்டுப்பாட்டிற்கு, இருமுறை தட்டவும்"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"விட்ஜெட்டைச் சேர்க்க முடியவில்லை."</string>
<string name="ime_action_go" msgid="8320845651737369027">"செல்"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"ஆண்டைத் தேர்ந்தெடுக்கவும்"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> நீக்கப்பட்டது"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"பணியிடம் <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2வது பணி <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3வது பணி <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"இந்தத் திரையை விலக்க, \"முந்தையது\" பொத்தானைத் தொட்டுப் பிடிக்கவும்."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"பயன்பாடு பொருத்தப்பட்டது: பொருத்தியதை நீக்குவதற்கு இந்தச் சாதனத்தில் அனுமதியில்லை."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"திரை பின் செய்யப்பட்டது"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"இப்போதே மீட்டமை"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"முடக்கப்பட்டது: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"குழு அழைப்பு"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"உதவிக்குறிப்பு"</string>
</resources>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index c6722ee..561492a 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"మీ ప్రమేయం లేకుండా కాల్లు చేయడం కోసం IMS సేవను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"ఫోన్ స్థితి మరియు గుర్తింపుని చదవడం"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"పరికరం యొక్క ఫోన్ లక్షణాలను ప్రాప్యత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ అనుమతి ఫోన్ నంబర్ మరియు పరికరం IDలను, కాల్ సక్రియంగా ఉందా లేదా అనే విషయాన్ని మరియు కాల్ ద్వారా కనెక్ట్ చేయబడిన రిమోట్ నంబర్ను కనుగొనడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"ఫోన్ నంబర్ను చదవడం"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"పరికరం యొక్క ఫోన్ నంబర్ను ప్రాప్యత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"టాబ్లెట్ను నిద్రావస్థకు వెళ్లనీయకుండా నిరోధించడం"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"టీవీ నిద్రావస్థకు వెళ్లకుండా నిరోధించడం"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ఫోన్ను నిద్రావస్థకు వెళ్లనీయకుండా నిరోధించడం"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"మీడియా వాల్యూమ్"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"నోటిఫికేషన్ వాల్యూమ్"</string>
<string name="ringtone_default" msgid="3789758980357696936">"డిఫాల్ట్ రింగ్టోన్"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"డిఫాల్ట్ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ఏదీ వద్దు"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"రింగ్టోన్లు"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"అలారం ధ్వనులు"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"నోటిఫికేషన్ ధ్వనులు"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"తెలియదు"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Wi-Fi నెట్వర్క్లు అందుబాటులో ఉన్నాయి</item>
<item quantity="one">Wi-Fi నెట్వర్క్ అందుబాటులో ఉంది</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ఇన్స్టాల్ సెషన్లను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది సక్రియ ప్యాకేజీ ఇన్స్టాలేషన్ల గురించి వివరాలను చూడటానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ఇన్స్టాల్ ప్యాకేజీలను అభ్యర్థించడం"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ప్యాకేజీల ఇన్స్టాలేషన్ అభ్యర్థించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"బ్యాటరీ అనుకూలీకరణలను విస్మరించడానికి అడగాలి"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"ఆ అనువర్తనం కోసం బ్యాటరీ అనుకూలీకరణలు విస్మరించేలా అనుమతి కోరడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"జూమ్ నియంత్రణ కోసం రెండుసార్లు నొక్కండి"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"విడ్జెట్ను జోడించడం సాధ్యపడలేదు."</string>
<string name="ime_action_go" msgid="8320845651737369027">"వెళ్లు"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"సంవత్సరాన్ని ఎంచుకోండి"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> తొలగించబడింది"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"కార్యాలయం <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2వ కార్యాలయం <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3వ కార్యాలయం <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"ఈ స్క్రీన్ని అన్పిన్ చేయడానికి, వెనుకకు తాకి & అలాగే పట్టుకోండి."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"అనువర్తనం పిన్ చేయబడింది: ఈ పరికరంలో అన్పిన్ చేయడానికి అనుమతి లేదు."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"స్క్రీన్ పిన్ చేయబడింది"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ఇప్పుడే రీసెట్ చేయి"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> నిలిపివేయబడింది"</string>
<string name="conference_call" msgid="3751093130790472426">"కాన్ఫరెన్స్ కాల్"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"సాధనం చిట్కా"</string>
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index ab04bec..200537f 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"อนุญาตให้แอปใช้บริการ IMS เพื่อโทรออกโดยคุณไม่ต้องดำเนินการใดๆ เลย"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"อ่านสถานะและข้อมูลระบุตัวตนของโทรศัพท์"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"อนุญาตให้แอปพลิเคชันเข้าถึงคุณลักษณะโทรศัพท์ของอุปกรณ์ การอนุญาตนี้ทำให้แอปพลิเคชันสามารถตรวจสอบหมายเลขโทรศัพท์และรหัสอุปกรณ์ ตรวจสอบว่ามีการโทรที่ทำงานอยู่หรือไม่ และตรวจสอบหมายเลขระยะไกลที่เชื่อมต่อด้วยการโทร"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"อ่านหมายเลขโทรศัพท์"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"อนุญาตให้แอปเข้าถึงหมายเลขโทรศัพท์ของอุปกรณ์"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ป้องกันไม่ให้แท็บเล็ตเข้าสู่โหมดสลีป"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ป้องกันไม่ให้ทีวีเข้าสู่โหมดสลีป"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ป้องกันไม่ให้โทรศัพท์เข้าโหมดสลีป"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"ระดับเสียงของสื่อ"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"ระดับเสียงของการแจ้งเตือน"</string>
<string name="ringtone_default" msgid="3789758980357696936">"เสียงเรียกเข้าเริ่มต้น"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ค่าเริ่มต้น (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"ไม่มี"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"เสียงเรียกเข้า"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"เสียงปลุก"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"เสียงการแจ้งเตือน"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"ไม่รู้จัก"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">มีหลายเครือข่าย Wi-Fi ที่ใช้งานได้</item>
<item quantity="one">มี 1 เครือข่าย Wi-Fi ที่ใช้งานได้</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"อนุญาตให้แอปพลิเคชันอ่านเซสชันการติดตั้ง ซึ่งจะอนุญาตให้อ่านรายละเอียดเกี่ยวกับการติดตั้งแพ็กเกจที่ใช้งาน"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ขอติดตั้งแพ็กเกจ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"อนุญาตให้แอปพลิเคชันขอการติดตั้งแพ็กเกจ"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ขอเพิกเฉยต่อการเพิ่มประสิทธิภาพแบตเตอรี่"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"อนุญาตให้แอปขอสิทธิ์เพิกเฉยต่อการเพิ่มประสิทธิภาพแบตเตอรี่สำหรับแอปนั้น"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"แตะสองครั้งเพื่อควบคุมการซูม"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ไม่สามารถเพิ่มวิดเจ็ต"</string>
<string name="ime_action_go" msgid="8320845651737369027">"ไป"</string>
@@ -1553,7 +1553,7 @@
</plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"ลองอีกครั้งในภายหลัง"</string>
<string name="immersive_cling_title" msgid="8394201622932303336">"กำลังดูแบบเต็มหน้าจอ"</string>
- <string name="immersive_cling_description" msgid="3482371193207536040">"หากต้องการออกไป ให้เลื่อนลงจากด้านบน"</string>
+ <string name="immersive_cling_description" msgid="3482371193207536040">"หากต้องการออก ให้เลื่อนลงจากด้านบน"</string>
<string name="immersive_cling_positive" msgid="5016839404568297683">"รับทราบ"</string>
<string name="done_label" msgid="2093726099505892398">"เสร็จสิ้น"</string>
<string name="hour_picker_description" msgid="6698199186859736512">"ตัวเลื่อนหมุนระบุชั่วโมง"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"เลือกปี"</string>
<string name="deleted_key" msgid="7659477886625566590">"ลบ <xliff:g id="KEY">%1$s</xliff:g> แล้ว"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g>ที่ทำงาน"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> งานที่ 2"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> งานที่ 3"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"หากต้องการเลิกตรึงหน้าจอนี้ แตะ \"กลับ\" ค้างไว้"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"มีการตรึงแอป: ไม่อนุญาตให้เลิกตรึงบนอุปกรณ์นี้"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ตรึงหน้าจอแล้ว"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"รีเซ็ตทันที"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"ปิดใช้ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"การประชุมสาย"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"เคล็ดลับเครื่องมือ"</string>
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index e7cec56..72c52b6 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Pinapahintulutan ang app na gamitin ang serbisyo ng IMS upang tumawag nang walang pahintulot mo."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"basahin ang katayuan at pagkakakilanlan ng telepono"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Pinapayagan ang app na i-access ang mga tampok ng telepono ng device. Pinapayagan ng pahintulot na ito ang app na tukuyin ang numero ng telepono at mga ID ng device, kung aktibo man ang isang tawag, at ang malayuang numerong ikinonekta ng isang tawag."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"basahin ang numero ng telepono"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Binibigyang-daan ang app na i-access ang numero ng telepono ng device."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"pigilan ang tablet mula sa pag-sleep"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"pigilan ang TV sa pag-sleep"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"pigilan ang telepono mula sa paghinto"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Volume ng media"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume ng notification"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Default na ringtone"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Default (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Wala"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Mga Ringtone"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Mga tunog ng alarm"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Mga tunog ng notification"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Hindi Alam"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="one">Available ang mga Wi-Fi network</item>
<item quantity="other">Available ang mga Wi-Fi network</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Pinapayagan ang isang application na magbasa ng mga session ng pag-install. Nagbibigay-daan ito upang makita ang mga detalye tungkol sa mga aktibong pag-install ng package."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"humiling ng mga package sa pag-install"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Pinapayagan ang isang application na hilingin ang pag-install ng mga package."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"hilingin na balewalain ang mga pag-optimize ng baterya"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Pinapayagang humingi ng pahintulot ang isang app na balewalain ang mga pag-optimize ng baterya para sa app na iyon."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tapikin ng dalawang beses para sa pagkontrol ng zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Hindi maidagdag ang widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Pumunta"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Pumili ng taon"</string>
<string name="deleted_key" msgid="7659477886625566590">"Tinanggal ang <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Pangalawang <xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Pangatlong <xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Upang i-unpin ang screen na ito, pindutin nang matagal ang Bumalik."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Naka-pin ang app: Hindi pinapayagan ang pag-a-unpin sa device na ito."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Naka-pin ang screen"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"I-reset ngayon"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Na-disable ang <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Conference Call"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Tooltip"</string>
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 59dc68e..dd7dffd 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Uygulamanın, sizin müdahaleniz olmadan telefon etmek için IMS hizmetini kullanmasına izin verir."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"telefonun durumunu ve kimliğini okuma"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Uygulamaya cihazdaki telefon özelliklerine erişme izni verir. Bu izin, uygulamanın telefon numarasını ve cihaz kimliğini, etkin bir çağrı olup olmadığını ve çağrıda bağlanılan karşı tarafın numarasını öğrenmesine olanak sağlar."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"telefon numarasını oku"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Uygulamanın cihazın telefon numarasına erişmesine izin verir."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"tabletin uykuya geçmesini önle"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV\'nin uyku moduna geçmesini önleme"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"telefonun uykuya geçmesini önleme"</string>
@@ -605,7 +607,7 @@
<string name="phoneTypeRadio" msgid="4093738079908667513">"Telsiz"</string>
<string name="phoneTypeTelex" msgid="3367879952476250512">"Teleks"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
- <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"İş Cep Telefonu"</string>
+ <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"İş Mobil"</string>
<string name="phoneTypeWorkPager" msgid="649938731231157056">"İş Çağrı Cihazı"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"Yardımcı"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
@@ -649,7 +651,7 @@
<string name="relationTypeManager" msgid="6365677861610137895">"Yönetici"</string>
<string name="relationTypeMother" msgid="4578571352962758304">"Anne"</string>
<string name="relationTypeParent" msgid="4755635567562925226">"Ebeveyn"</string>
- <string name="relationTypePartner" msgid="7266490285120262781">"Hayat Arkadaşı"</string>
+ <string name="relationTypePartner" msgid="7266490285120262781">"Ortak"</string>
<string name="relationTypeReferredBy" msgid="101573059844135524">"Öneren"</string>
<string name="relationTypeRelative" msgid="1799819930085610271">"Akraba"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"Kız Kardeş"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Medya ses düzeyi"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Bildirim ses düzeyi"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Varsayılan zil sesi"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Varsayılan (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Yok"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Zil sesleri"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Alarm sesleri"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Bildirim sesleri"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Bilinmiyor"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Kablosuz ağlar var</item>
<item quantity="one">Kablosuz ağ var</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Bir uygulamanın yükleme oturumlarını okumasına izin verir. Bu, etkin paket yüklemeleriyle ilgili ayrıntıların görülmesine olanak tanır."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"paket yükleme isteğinde bulunma"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Uygulamaya, paketleri yükleme isteğinde bulunma izni verir."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"pil optimizasyonlarını göz ardı etme izni iste"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Bir uygulamanın, kendisi için pil optimizasyonlarını göz ardı etme izni istemesine olanak sağlar."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Zum denetimi için iki kez dokun"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Widget eklenemedi."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Git"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Yılı seçin"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> silindi"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (İş)"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"İş için 2. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"İş için 3. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Bu ekranın sabitlemesini kaldırmak için Geri\'ye dokunup basılı tutun."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Uygulama sabitlendi. Bu cihazda sabitlemenin kaldırılmasına izin verilmiyor."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran sabitlendi"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Şimdi sıfırla"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> devre dışı"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferans Çağrısı"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"İpucu"</string>
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 0ac3b80..b153518 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -383,6 +383,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Додаток зможе телефонувати за допомогою служби IMS без вашого відома."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"читати статус та ідентифікаційну інформацію телефону"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Дозволяє програмі отримувати доступ до телефонних функцій пристрою. Такий дозвіл дає програмі змогу визначати номер телефону й ідентифікатори пристрою, активність виклику, а також віддалений номер, на який здійснюється виклик."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"переглядати номер телефону"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Дозволяє додатку отримувати доступ до номера телефону на пристрої."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"не доп.перехід пристр.в реж.сну"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"не допускати перехід телевізора в режим сну"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Вимкнення режиму сну"</string>
@@ -1260,6 +1262,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Дозволяє додатку читати дані сеансів встановлення. Додаток може бачити деталі про активні встановлення пакетів."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"запитувати дані про пакети встановлення"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Додаток зможе надсилати запити на встановлення пакетів."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"запитувати дозвіл ігнорувати оптимізацію використання заряду акумулятора"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Додаток зможе запитувати дозвіл ігнорувати оптимізацію використання заряду акумулятора."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Двічі натис. для кер. масшт."</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Не вдалося додати віджет."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Йти"</string>
@@ -1614,10 +1618,8 @@
<string name="select_year" msgid="7952052866994196170">"Виберіть рік"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> видалено"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Робоча <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-а робота: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-я робота: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Щоб відкріпити цей екран, натисніть і утримуйте кнопку \"Назад\"."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Додаток закріплено. Його не можна відкріпити на цьому пристрої."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Екран закріплено"</string>
@@ -1755,5 +1757,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Скинути"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> вимкнено"</string>
<string name="conference_call" msgid="3751093130790472426">"Конференц-виклик"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Спливаюча підказка"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Спливаюча підказка"</string>
</resources>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 715dbed..4f4706f 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -265,7 +265,7 @@
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"کسی ایسی ونڈو کے مواد کا معائنہ کریں جس کے ساتھ آپ تعامل کر رہے ہیں۔"</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"ٹچ کے ذریعے دریافت کریں کو آن کرنے کی"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"تھپتھپائے گئے آئٹمز کو باآواز بلند بولا جائے گا اور اشاروں کا استعمال کرکے اسکرین کو دریافت کیا جا سکتا ہے۔"</string>
- <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"بہتر ویب accessibility کو آن کرنے کی"</string>
+ <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"بہتر ویب ایکسیسبیلٹی کو آن کرنے کی"</string>
<string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"ایپ کا مواد مزید قابل رسائی بنانے کیلئے اسکرپٹس کو انسٹال کیا جا سکتا ہے۔"</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"آپکے ٹائپ کردہ متن کا مشاہدہ کرنے کی"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"اس میں ذاتی ڈیٹا جیسے کریڈٹ کارڈ نمبرز اور پاس ورڈز شامل ہیں۔"</string>
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"آپ کی مداخلت کے بغیر کالیں کرنے کیلئے ایپ کو IMS سروس استعمال کرنے کی اجازت دیتی ہے۔"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"فون کے اسٹیٹس اور شناخت کو پڑھیں"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ایپ کو آلے کی فون والی خصوصیات تک رسائی حاصل کرنے کی اجازت دیتا ہے۔ یہ اجازت ایپ کو فون نمبر اور آلے کے IDs کا تعین کرنے، آیا کوئی کال فعال ہے، اور کال کے ذریعہ مربوط ریموٹ نمبر کا تعین کرنے دیتی ہے۔"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"فون نمبر پڑھے"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"ایپ کو آلہ کے فون نمبر تک رسائی کرنے دیتا ہے۔"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ٹیبلیٹ کو سلیپ وضع میں جانے سے روکیں"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV کو سلیپ وضع میں جانے سے روکیں"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"فون کو سلیپ وضع میں جانے سے روکیں"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"میڈیا والیوم"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"اطلاع کا والیوم"</string>
<string name="ringtone_default" msgid="3789758980357696936">"ڈیفالٹ رنگ ٹون"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"ڈیفالٹ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"کوئی نہیں"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"رنگ ٹونز"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"الارم کی آوازیں"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"اطلاعات کی آوازیں"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"نامعلوم"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Wi-Fi نیٹ ورکس دستیاب ہیں</item>
<item quantity="one">Wi-Fi نیٹ ورک دستیاب ہے</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ایک ایپلیکیشن کو انسٹال سیشنز پڑھنے کی اجازت دیتا ہے۔ یہ اسے فعال پیکیج انسٹالیشنز کے بارے میں تفصیلات دیکھنے کی اجازت دیتا ہے۔"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"پیکجز انسٹال کرنے کی درخواست کریں"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ایک ایپلیکیشن کو پیکجز انسٹال کرنے کی اجازت دیتی ہے۔"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"بیٹری کی بہتریاں نظر انداز کرنے کا پوچھیں"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"اس ایپ کیلئے ایک ایپ کو بیٹری کی کارکردگی بہتر بنانے کو نظر انداز کرنے کی اجازت دیں۔"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"زوم کنٹرول کیلئے دوبار تھپتھپائیں"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ویجٹس کو شامل نہیں کرسکا۔"</string>
<string name="ime_action_go" msgid="8320845651737369027">"جائیں"</string>
@@ -1236,7 +1236,7 @@
<string name="forward_intent_to_work" msgid="621480743856004612">"آپ اس ایپ کو اپنے دفتری پروفائل میں استعمال کر رہے ہیں"</string>
<string name="input_method_binding_label" msgid="1283557179944992649">"اندراج کا طریقہ"</string>
<string name="sync_binding_label" msgid="3687969138375092423">"مطابقت پذیری کریں"</string>
- <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibility"</string>
+ <string name="accessibility_binding_label" msgid="4148120742096474641">"ایکسیسبیلٹی"</string>
<string name="wallpaper_binding_label" msgid="1240087844304687662">"وال پیپر"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"وال پیپر تبدیل کریں"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"اطلاع سننے والا"</string>
@@ -1438,9 +1438,9 @@
<string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"ہٹائیں"</string>
<string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"والیوم کو تجویز کردہ سطح سے زیادہ کریں؟\n\nزیادہ وقت تک اونچی آواز میں سننے سے آپ کی سماعت کو نقصان پہنچ سکتا ہے۔"</string>
- <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"accessibility فعال کرنے کیلئے دو انگلیاں نیچے دبائے رکھیں۔"</string>
- <string name="accessibility_enabled" msgid="1381972048564547685">"Accessibility فعال۔"</string>
- <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Accessibility منسوخ ہوگئی۔"</string>
+ <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"ایکسیسبیلٹی فعال کرنے کیلئے دو انگلیاں نیچے دبائے رکھیں۔"</string>
+ <string name="accessibility_enabled" msgid="1381972048564547685">"ایکسیسبیلٹی فعال۔"</string>
+ <string name="enable_accessibility_canceled" msgid="3833923257966635673">"ایکسیسبیلٹی منسوخ ہوگئی۔"</string>
<string name="user_switched" msgid="3768006783166984410">"موجودہ صارف <xliff:g id="NAME">%1$s</xliff:g>۔"</string>
<string name="user_switching_message" msgid="2871009331809089783">"<xliff:g id="NAME">%1$s</xliff:g> پر سوئچ کیا جا رہا ہے…"</string>
<string name="user_logging_out_message" msgid="8939524935808875155">"<xliff:g id="NAME">%1$s</xliff:g> لاگ آؤٹ ہو رہا ہے…"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"سال منتخب کریں"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> کو حذف کر دیا گیا"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"دفتر <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"دوسرا کام <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"تیسرا کام <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"اس اسکرین سے پن ہٹانے کیلئے، پیچھے کو تھپتھپائیں اور دبا کر رکھیں۔"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ایپ کو پن کر دیا گیا ہے: اس آلہ پر پن ہٹانے کی اجازت نہیں ہے۔"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"اسکرین کو پن کر دیا گیا"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ابھی ری سیٹ کریں"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"غیر فعال کردہ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"کانفرنس کال"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"ٹول ٹپ"</string>
</resources>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 255982c..321d795 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Ilovaga sizning ishtirokingizsiz qo‘ng‘iroqlarni amalga oshirish uchun IMS xizmatidan foydalanishga ruxsat beradi."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"telefon holati haqidagi ma’lumotlarni olish"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Ilovaga qurilmangizdagi telefon xususiyatlariga kirishga ruxsat beradi. Bu ruxsat ilovaga telefon raqami va qurilma nomlari, qo‘ng‘iroq faol yoki faolsizligi va masofadagi raqam qo‘ng‘rioq orqali bog‘langanligini aniqlashga imkon beradi."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"telefon raqamini o‘qish"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Ilovaga qurilmaning telefon raqamidan foydalanishiga ruxsat beradi."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"planshetni uyquga ketishiga yo‘l qo‘ymaslik"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"televizorning uyqu rejimiga o‘tishining oldini olish"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"telefonni uxlashiga yo‘l qo‘ymaslik"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Ilovaga o‘rnatilgan seanslarni o‘qish uchun ruxsat beradi. Bu unga faol paket o‘rnatmalari haqidagi ma’lumotlarni ko‘rish imkonini beradi."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"paketlarni o‘rnatish so‘rovini yuborish"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Ilovaga paketlarni o‘rnatish so‘rovini yuborish imkonini beradi."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"batareya quvvatidan xohlagancha foydalanishni so‘rash"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Ilovaga batareya quvvatidan xohlagancha foydalanish uchun ruxsat so‘rashga imkon beradi."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Ko‘lamini o‘zgartirish uchun ikki marta bosing"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Vidjet qo‘shilmadi."</string>
<string name="ime_action_go" msgid="8320845651737369027">"O‘tish"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Yilni tanlash"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> raqami o‘chirib tashlandi"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Ish <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-ishxona <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-ishxona <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Bu ekrandan chiqish uchun “Orqaga” tugmasini bosib turing."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Ilova qadab qo‘yilgan. Uni ekrandan yechish ushbu qurilmada ta’qiqlangan."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran qadab qo‘yildi"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Asl holatga qaytarish"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> vidjeti o‘chirilgan"</string>
<string name="conference_call" msgid="3751093130790472426">"Konferens-aloqa"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Qalqib chiquvchi maslahat oynasi"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Maslahat oynasi"</string>
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 1f6a1cd..f5ad6a4 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Cho phép ứng dụng sử dụng dịch vụ IMS để thực hiện cuộc gọi mà không có sự can thiệp của bạn."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"đọc trạng thái và nhận dạng của điện thoại"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Cho phép ứng dụng truy cập vào các tính năng điện thoại của thiết bị. Quyền này cho phép ứng dụng xác định số điện thoại và ID thiết bị, cho dù cuộc gọi có hiện hoạt hay không và số từ xa có được kết nối bằng một cuộc gọi hay không."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"đọc số điện thoại"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Cho phép ứng dụng truy cập số điện thoại của thiết bị."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ngăn máy tính bảng chuyển sang chế độ ngủ"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ngăn TV chuyển sang chế độ ngủ"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ngăn điện thoại chuyển sang chế độ ngủ"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"Âm lượng phương tiện"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Âm lượng thông báo"</string>
<string name="ringtone_default" msgid="3789758980357696936">"Nhạc chuông mặc định"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Mặc định (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Không"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Nhạc chuông"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Âm thanh báo thức"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Âm thanh thông báo"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"Không xác định"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">Các mạng Wi-Fi khả dụng</item>
<item quantity="one">Mạng Wi-Fi khả dụng</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Cho phép ứng dụng đọc phiên cài đặt. Thao tác này sẽ cho phép ứng dụng xem chi tiết về gói cài đặt đang hoạt động."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"yêu cầu gói cài đặt"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Cho phép ứng dụng yêu cầu cài đặt gói."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"hỏi để bỏ qua tối ưu hóa pin"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Cho phép ứng dụng hỏi quyền để bỏ qua tối ưu hóa pin cho ứng dụng đó."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Nhấn hai lần để kiểm soát thu phóng"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Không thể thêm tiện ích."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Đến"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Chọn năm"</string>
<string name="deleted_key" msgid="7659477886625566590">"Đã xóa <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> làm việc"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Công việc thứ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Công việc thứ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Để bỏ ghim màn hình này, nhấn và giữ Quay lại."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Ứng dụng được ghim: Không được phép bỏ ghim trên thiết bị này."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Đã ghim màn hình"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Đặt lại ngay bây giờ"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Đã tắt <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"Cuộc gọi nhiều bên"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Chú giải công cụ"</string>
</resources>
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index d13d154..ac7b236 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -65,4 +65,5 @@
<!-- The small screens of watch devices makes multi-window support undesireable. -->
<bool name="config_supportsMultiWindow">false</bool>
+ <bool name="config_supportsSplitScreenMultiWindow">false</bool>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 5991f54..ead9a66 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -278,7 +278,7 @@
<string name="permlab_statusBarService" msgid="4826835508226139688">"用作状态栏"</string>
<string name="permdesc_statusBarService" msgid="716113660795976060">"允许以状态栏形式显示应用。"</string>
<string name="permlab_expandStatusBar" msgid="1148198785937489264">"展开/收拢状态栏"</string>
- <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"允许应用展开或折叠状态栏。"</string>
+ <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"允许应用展开或收起状态栏。"</string>
<string name="permlab_install_shortcut" msgid="4279070216371564234">"安装快捷方式"</string>
<string name="permdesc_install_shortcut" msgid="8341295916286736996">"允许应用自行添加主屏幕快捷方式。"</string>
<string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"卸载快捷方式"</string>
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"允许应用自行使用即时通讯服务拨打电话。"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"读取手机状态和身份"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"允许该应用访问设备的电话功能。此权限可让该应用确定本机号码和设备 ID、是否正处于通话状态以及拨打的号码。"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"读取电话号码"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"允许该应用访问该设备的电话号码。"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"阻止平板电脑进入休眠状态"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"阻止电视进入休眠状态"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"防止手机休眠"</string>
@@ -738,7 +740,7 @@
<string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"添加小部件。"</string>
<string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"空白"</string>
<string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"已展开解锁区域。"</string>
- <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"已折叠解锁区域。"</string>
+ <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"已收起解锁区域。"</string>
<string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>小部件。"</string>
<string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"用户选择器"</string>
<string name="keyguard_accessibility_status" msgid="8008264603935930611">"状态"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"媒体音量"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
<string name="ringtone_default" msgid="3789758980357696936">"默认铃声"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"默认铃声(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"无"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"铃声"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"闹钟提示音"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"通知提示音"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"未知"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">有可用的 WLAN 网络</item>
<item quantity="one">有可用的 WLAN 网络</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"允许应用读取安装会话。这样,应用将可以查看有关当前软件包安装的详情。"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"请求安装文件包"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"允许应用请求安装文件包。"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"请求忽略电池优化"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"允许应用请求相应的权限,以便忽略针对该应用的电池优化。"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"双击可以进行缩放控制"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"无法添加小部件。"</string>
<string name="ime_action_go" msgid="8320845651737369027">"开始"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"选择年份"</string>
<string name="deleted_key" msgid="7659477886625566590">"已删除<xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"第二个工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"第三个工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"要取消固定此屏幕,请触摸并按住“返回”按钮。"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"应用处于固定状态:在此设备上不允许退出该模式。"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"已固定屏幕"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"立即重置"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"已停用的<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"电话会议"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"提示"</string>
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 7191a3d..ffad746a 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"允許應用程式自行使用 IMS 服務撥打電話。"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"讀取手機狀態和識別碼"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"允許應用程式使用裝置的電話功能。這項權限允許應用程式確定手機號碼和裝置編號、是否正在通話中,以及所撥打的對方號碼。"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"讀取電話號碼"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"允許應用程式存取裝置的電話號碼。"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"防止平板電腦進入休眠狀態"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"阻止電視進入休眠狀態"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"防止手機進入休眠狀態"</string>
@@ -646,7 +648,7 @@
<string name="relationTypeDomesticPartner" msgid="6904807112121122133">"同居伴侶"</string>
<string name="relationTypeFather" msgid="5228034687082050725">"父親"</string>
<string name="relationTypeFriend" msgid="7313106762483391262">"朋友"</string>
- <string name="relationTypeManager" msgid="6365677861610137895">"管理員"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"主管"</string>
<string name="relationTypeMother" msgid="4578571352962758304">"母親"</string>
<string name="relationTypeParent" msgid="4755635567562925226">"父母"</string>
<string name="relationTypePartner" msgid="7266490285120262781">"夥伴"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"媒體音量"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
<string name="ringtone_default" msgid="3789758980357696936">"預設鈴聲"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"預設 (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"無"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"鈴聲"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"鬧鐘音效"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"通知音效"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"不明"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">有可用的 Wi-Fi 網絡</item>
<item quantity="one">有可用的 Wi-Fi 網絡</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"允許應用程式讀取安裝工作階段。應用程式將可查看目前安裝套裝的詳細資料。"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"要求安裝套件"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"允許應用程式要求安裝套件"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"要求忽略電池優化"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"允許應用程式要求就該應用程式忽略電池優化。"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"輕觸兩下控制縮放"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"無法新增小工具。"</string>
<string name="ime_action_go" msgid="8320845651737369027">"開始"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"選取年份"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> 已刪除"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"公司<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"第二個工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"第三個工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"如要取消固定這個畫面,請按住 [返回]。"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"應用程式已固定:不允許在此裝置上取消固定。"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"螢幕已固定"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"立即重設"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"「<xliff:g id="LABEL">%1$s</xliff:g>」已停用"</string>
<string name="conference_call" msgid="3751093130790472426">"會議通話"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"提示"</string>
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 9e37672..1a49aaf 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"允許應用程式自動使用 IMS 服務撥打電話。"</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"讀取手機狀態和識別碼"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"允許應用程式使用裝置的電話功能。這項權限可讓應用程式判讀手機號碼和裝置 ID、是否正在通話中,以及所撥打的對方號碼。"</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"讀取電話號碼"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"允許應用程式存取裝置的電話號碼。"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"防止平板電腦進入休眠狀態"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"防止電視進入休眠狀態"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"防止手機進入待命狀態"</string>
@@ -605,7 +607,7 @@
<string name="phoneTypeRadio" msgid="4093738079908667513">"無線電"</string>
<string name="phoneTypeTelex" msgid="3367879952476250512">"電報"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY/TDD"</string>
- <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"公司行動電話"</string>
+ <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"公司手機"</string>
<string name="phoneTypeWorkPager" msgid="649938731231157056">"公司呼叫器"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"助理"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"多媒體簡訊"</string>
@@ -1059,16 +1061,12 @@
<string name="volume_icon_description_media" msgid="4217311719665194215">"媒體音量"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
<string name="ringtone_default" msgid="3789758980357696936">"預設鈴聲"</string>
- <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
- <skip />
+ <string name="ringtone_default_with_actual" msgid="1767304850491060581">"預設 (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"無"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"鈴聲"</string>
- <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
- <skip />
- <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
- <skip />
- <!-- no translation found for ringtone_unknown (3914515995813061520) -->
- <skip />
+ <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"鬧鐘音效"</string>
+ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"通知音效"</string>
+ <string name="ringtone_unknown" msgid="3914515995813061520">"不明"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
<item quantity="other">有多個可用的 Wi-Fi 網路</item>
<item quantity="one">有一個可用的 Wi-Fi 網路</item>
@@ -1214,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"允許應用程式讀取安裝工作階段。應用程式將可查看目前的套件安裝詳細資料。"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"要求安裝套件"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"允許應用程式要求安裝套件。"</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"要求忽略電池效能最佳化設定"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"允許應用程式要求權限,以便忽略針對該應用程式的電池效能最佳化設定。"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"點兩下以進行縮放控制"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"無法新增小工具。"</string>
<string name="ime_action_go" msgid="8320845651737369027">"開始"</string>
@@ -1564,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"選取年份"</string>
<string name="deleted_key" msgid="7659477886625566590">"已刪除 <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"公司<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"第 2 項工作:<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"第 3 項工作:<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"如要取消固定這個畫面,請按住「返回」按鈕。"</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"應用程式已固定:無法在這部裝置取消固定。"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"已固定螢幕"</string>
@@ -1687,6 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"立即重設"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"已停用的<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="conference_call" msgid="3751093130790472426">"電話會議"</string>
- <!-- no translation found for tooltip_popup_title (8101791425834697618) -->
- <skip />
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"工具提示"</string>
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 66d1010..3cde2a1 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -377,6 +377,8 @@
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Ivumela uhlelo lokusebenza ukuthi lusebenzise isevisi ye-IMS ukuze yenze amakholi ngaphandle kokungenelela kwakho."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"funda isimo sefoni kanye nesazisi"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Ivumela uhlelo lokusebenza ukufinyelela izici zefoni zedivayisi. Le mvume ivumela uhlelo lokusebenza ukucacisa inombolo yefoni nobunikazi bedivayisi, ukuthi noma ikholi iyasebenza, futhi nenombolo yesilawuli kude zixhunywe ngekholi."</string>
+ <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"funda inombolo yefoni"</string>
+ <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Ivumela uhlelo lokusebenza ukuthi lifinyelele kunombolo yefoni yedivayisi."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"gwema ithebhulethi ukuba ingalali"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"vimbela i-TV kusukela ekulaleni"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"gwema ifoni ukuba ingalali"</string>
@@ -1210,6 +1212,8 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Ivumela uhlelo lokusebenza ukufunda izikhathi. Lokhu kuzolivumela ukubona imininingwane mayelana nokufaka kwephakethi esebenzayo."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"cela amaphakheji wokufaka"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Ivumela uhlelo lokusebenza ukucela ukufakwa kwamaphakheji."</string>
+ <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"cela ukuziba ukulungiselelwa kwebhethri"</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Ivumela uhlelo lokusebenza ukuthi licele imvume yokuziba ukulungiselela ibhethri yalolo hlelo lokusebenza."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Thepha kabili ukuthola ukulawula ukusondeza"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Yehlulekile ukwengeza i-widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Iya"</string>
@@ -1560,10 +1564,8 @@
<string name="select_year" msgid="7952052866994196170">"Khetha unyaka"</string>
<string name="deleted_key" msgid="7659477886625566590">"I-<xliff:g id="KEY">%1$s</xliff:g> isusiwe"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Umsebenzi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <!-- no translation found for managed_profile_label_badge_2 (5048136430082124036) -->
- <skip />
- <!-- no translation found for managed_profile_label_badge_3 (2808305070321719040) -->
- <skip />
+ <string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Umsebenzi wesibili <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Umsebenzi wesithathu <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="lock_to_app_toast" msgid="1420543809500606964">"Ukuze ususe ukuphina lesi sikrini, thinta futhi ubambe okuthi Emuva."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Uhlelo lokusebenza luphiniwe: Ukususa ukuphina akuvunyelwe kule divayisi."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Isikrini siphiniwe"</string>
@@ -1683,5 +1685,5 @@
<string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Setha kabusha manje"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"I-<xliff:g id="LABEL">%1$s</xliff:g> ekhutshaziwe"</string>
<string name="conference_call" msgid="3751093130790472426">"Ikholi yengqungquthela"</string>
- <string name="tooltip_popup_title" msgid="8101791425834697618">"Okuzivelelayo kwe-tooltip"</string>
+ <string name="tooltip_popup_title" msgid="5253721848739260181">"Ithulithiphu"</string>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 7045eaf..aa050de 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2887,6 +2887,28 @@
<!-- Defines text displayed in a small popup window on hover or long press. -->
<attr name="tooltip" format="string" localization="suggested" />
+ <!-- Whether this view is a root of a keyboard navigation cluster.
+ See {@link android.view.View#setKeyboardNavigationCluster(boolean)}. -->
+ <attr name="keyboardNavigationCluster" format="boolean" />
+
+ <!-- Whether this view is a root of a keyboard navigation section.
+ See {@link android.view.View#setKeyboardNavigationSection(boolean)}. -->
+ <attr name="keyboardNavigationSection" format="boolean" />
+
+ <!-- Defines the next keyboard navigation cluster.
+
+ If the reference refers to a view that does not exist or is part
+ of a hierarchy that is invisible, a {@link java.lang.RuntimeException}
+ will result when the reference is accessed.-->
+ <attr name="nextClusterForward" format="reference"/>
+
+ <!-- Defines the next keyboard navigation section.
+
+ If the reference refers to a view that does not exist or is part
+ of a hierarchy that is invisible, a {@link java.lang.RuntimeException}
+ will result when the reference is accessed.-->
+ <attr name="nextSectionForward" format="reference"/>
+
</declare-styleable>
<!-- Attributes that can be assigned to a tag for a particular View. -->
@@ -7508,6 +7530,8 @@
<attr name="title" />
<!-- @SystemApi Summary for the same preference as the title. @hide -->
<attr name="summary" />
+ <!-- @SystemApi Whether trust agent can unlock a user profile @hide -->
+ <attr name="unlockProfile" format="boolean"/>
</declare-styleable>
<!-- =============================== -->
@@ -8378,13 +8402,13 @@
<attr name="color" />
</declare-styleable>
- <!-- @hide Attributes which will be read by the Activity to intialize the
+ <!-- @hide Attributes which will be read by the Activity to intialize the
base activity TaskDescription. -->
<declare-styleable name="ActivityTaskDescription">
<!-- @hide From Theme.colorPrimary, used for the TaskDescription primary
color. -->
<attr name="colorPrimary" />
- <!-- @hide From Theme.colorBackground, used for the TaskDescription background
+ <!-- @hide From Theme.colorBackground, used for the TaskDescription background
color. -->
<attr name="colorBackground" />
</declare-styleable>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 967c4ad..c91f0a5 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1209,6 +1209,10 @@
-->
<attr name="autoVerify" format="boolean" />
+ <!-- Specify whether a component should be visible to ephemeral apps.
+ -->
+ <attr name="visibleToEphemeral" format="boolean" />
+
<!-- An XML resource with the application's Network Security Config. -->
<attr name="networkSecurityConfig" format="reference" />
@@ -1731,6 +1735,7 @@
<attr name="exported" />
<attr name="singleUser" />
<attr name="directBootAware" />
+ <attr name="visibleToEphemeral" />
</declare-styleable>
<!-- Attributes that can be supplied in an AndroidManifest.xml
@@ -1820,6 +1825,7 @@
client to bind to the service as if it were running it its own package. The service
must also be {@link android.R.attr#exported} if this flag is set. -->
<attr name="externalService" format="boolean" />
+ <attr name="visibleToEphemeral" />
</declare-styleable>
<!-- The <code>receiver</code> tag declares an
@@ -1940,7 +1946,8 @@
<!-- @hide This activity is a launcher which should always show up on the top of others.
This attribute is ignored if the activity isn't a launcher. -->
<attr name="onTopLauncher" format="boolean" />
- <attr name="rotationAnimation"/>
+ <attr name="rotationAnimation" />
+ <attr name="visibleToEphemeral" />
</declare-styleable>
<!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a7c5b2a..69c7b60 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -422,6 +422,9 @@
<!-- Boolean indicating whether Hotspot 2.0/Passpoint and ANQP queries is enabled -->
<bool translatable="false" name="config_wifi_hotspot2_enabled">false</bool>
+ <!-- Boolean indicating whether 802.11r Fast BSS Transition is enabled on this platform -->
+ <bool translatable="false" name="config_wifi_fast_bss_transition_enabled">false</bool>
+
<!-- Device type information conforming to Annex B format in WiFi Direct specification.
The default represents a dual-mode smartphone -->
<string translatable="false" name="config_wifi_p2p_device_type">10-0050F204-5</string>
@@ -1254,6 +1257,19 @@
config_enableFusedLocationOverlay is false. -->
<string name="config_fusedLocationProviderPackageName" translatable="false">com.android.location.fused</string>
+ <!-- A list of potential packages, in priority order, that may contain a
+ network recommendation provider. A network recommendation provider must:
+ * Be granted the SCORE_NETWORKS permission.
+ * Include a Receiver for the android.net.scoring.SCORE_NETWORKS action guarded by the
+ BROADCAST_NETWORK_PRIVILEGED permission.
+ * Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action.
+
+ This may be empty if network scoring and recommending isn't supported.
+ -->
+ <string-array name="config_networkRecommendationPackageNames" translatable="false">
+ <!-- Add packages here -->
+ </string-array>
+
<!-- Whether to enable Hardware FLP overlay which allows Hardware FLP to be
replaced by an app at run-time. When disabled, only the
config_hardwareFlpPackageName package will be searched for Hardware Flp,
@@ -1650,7 +1666,7 @@
<bool name="config_actionMenuItemAllCaps">true</bool>
<!-- Remote server that can provide NTP responses. -->
- <string translatable="false" name="config_ntpServer">2.android.pool.ntp.org</string>
+ <string translatable="false" name="config_ntpServer">time.android.com</string>
<!-- Normal polling frequency in milliseconds -->
<integer name="config_ntpPollingInterval">86400000</integer>
<!-- Try-again polling interval in milliseconds, in case the network request failed -->
@@ -2552,6 +2568,9 @@
E.g. freeform, split-screen, picture-in-picture. -->
<bool name="config_supportsMultiWindow">true</bool>
+ <!-- True if the device supports split screen as a form of multi-window. -->
+ <bool name="config_supportsSplitScreenMultiWindow">true</bool>
+
<!-- True if the device requires AppWidgetService even if it does not have
the PackageManager.FEATURE_APP_WIDGETS feature -->
<bool name="config_enableAppWidgetService">false</bool>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index deeaf35..4604f3f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2775,6 +2775,11 @@
<public name="layout_marginVertical" />
<public name="paddingHorizontal" />
<public name="paddingVertical" />
+ <public name="visibleToEphemeral" />
+ <public name="keyboardNavigationCluster" />
+ <public name="keyboardNavigationSection" />
+ <public name="nextClusterForward" />
+ <public name="nextSectionForward" />
</public-group>
<public-group type="style" first-id="0x010302e0">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index af77b1f..6c08473 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3248,6 +3248,11 @@
<!-- Description of an application permission that lets it read install sessions. -->
<string name="permdesc_requestInstallPackages">Allows an application to request installation of packages.</string>
+ <!-- Title of an application permission that lets it ask user to ignore battery optimizations for that app. -->
+ <string name="permlab_requestIgnoreBatteryOptimizations">ask to ignore battery optimizations</string>
+ <!-- Description of an application permission that lets it ask user to ignore battery optimizations for that app-->
+ <string name="permdesc_requestIgnoreBatteryOptimizations">Allows an app to ask for permission to ignore battery optimizations for that app.</string>
+
<!-- Shown in the tutorial for tap twice for zoom control. -->
<string name="tutorial_double_tap_to_zoom_message_short">Tap twice for zoom control</string>
@@ -4272,7 +4277,7 @@
<string name="zen_mode_alarm">Until <xliff:g id="formattedTime" example="10:00 PM">%1$s</xliff:g> (next alarm)</string>
<!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
- <string name="zen_mode_forever">Until you turn this off</string>
+ <string name="zen_mode_forever">Until you turn off Do Not Disturb</string>
<!-- Zen mode condition: no exit criteria, includes the name of the feature for emphasis. [CHAR LIMIT=NONE] -->
<string name="zen_mode_forever_dnd">Until you turn off Do Not Disturb</string>
@@ -4453,6 +4458,6 @@
<!-- Label used by Telephony code, assigned as the display name for conference calls [CHAR LIMIT=60] -->
<string name="conference_call">Conference Call</string>
- <!-- Title for a tooltip popup window [CHAR LIMIT=NONE] -->
- <string name="tooltip_popup_title">Tooltip Popup</string>
+ <!-- Window title for a tooltip [CHAR LIMIT=NONE] -->
+ <string name="tooltip_popup_title">Tooltip</string>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f6fd64b..dcb44d3 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -307,6 +307,7 @@
<java-symbol type="bool" name="config_supportAudioSourceUnprocessed" />
<java-symbol type="bool" name="config_freeformWindowManagement" />
<java-symbol type="bool" name="config_supportsMultiWindow" />
+ <java-symbol type="bool" name="config_supportsSplitScreenMultiWindow" />
<java-symbol type="bool" name="config_guestUserEphemeral" />
<java-symbol type="bool" name="config_localDisplaysMirrorContent" />
<java-symbol type="integer" name="config_defaultDisplayDefaultColorMode" />
@@ -1716,6 +1717,7 @@
<java-symbol type="bool" name="config_wifi_background_scan_support" />
<java-symbol type="bool" name="config_wifi_dual_band_support" />
<java-symbol type="bool" name="config_wifi_hotspot2_enabled" />
+ <java-symbol type="bool" name="config_wifi_fast_bss_transition_enabled" />
<java-symbol type="bool" name="config_wimaxEnabled" />
<java-symbol type="bool" name="show_ongoing_ime_switcher" />
<java-symbol type="color" name="config_defaultNotificationColor" />
@@ -2751,4 +2753,7 @@
<java-symbol type="integer" name="date_picker_mode" />
<java-symbol type="dimen" name="config_appTransitionAnimationDurationScaleDefault" />
+
+<!-- Network Recommendation -->
+ <java-symbol type="array" name="config_networkRecommendationPackageNames" />
</resources>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index b19858e..a711088 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -742,15 +742,15 @@
<item name="colorAccent">@color/accent_device_default_light</item>
</style>
- <!-- DeviceDefault theme for a window that should use Settings theme colors but has
- a full dark palette (instead of Light with dark action bar like
- Theme.DeviceDefault.Settings. -->
- <style name="Theme.DeviceDefault.Settings.Dark" parent="Theme.Material">
+ <!-- @hide DeviceDefault theme for a window that should use Settings theme colors
+ but has a full dark palette. ONLY USED FOR QUICK SETTINGS THEME -->
+ <style name="Theme.DeviceDefault.QuickSettings" parent="Theme.Material">
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
<item name="colorSecondary">@color/secondary_device_default_settings</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorControlNormal">?attr/textColorPrimary</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Settings_Dark} with no action bar -->
diff --git a/core/tests/coretests/res/layout/messaging_linear_layout_test.xml b/core/tests/coretests/res/layout/messaging_linear_layout_test.xml
new file mode 100644
index 0000000..8ba3e07
--- /dev/null
+++ b/core/tests/coretests/res/layout/messaging_linear_layout_test.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<com.android.internal.widget.MessagingLinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:maxHeight="300px"
+ android:spacing="5px">
+
+</com.android.internal.widget.MessagingLinearLayout>
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationTest.java b/core/tests/coretests/src/android/content/res/ConfigurationTest.java
new file mode 100644
index 0000000..72b9197
--- /dev/null
+++ b/core/tests/coretests/src/android/content/res/ConfigurationTest.java
@@ -0,0 +1,58 @@
+/*
+1;3409;0c * 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.content.res;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import org.junit.runners.JUnit4;
+
+import android.content.res.Configuration;
+import android.support.test.filters.SmallTest;
+import android.platform.test.annotations.Presubmit;
+
+import junit.framework.TestCase;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Build/install/run: bit FrameworksCoreTests:android.content.res.ConfigurationTest
+ */
+@RunWith(JUnit4.class)
+@SmallTest
+@Presubmit
+public class ConfigurationTest extends TestCase {
+ @Test
+ public void testUpdateFromPreservesRoundBit() {
+ Configuration config = new Configuration();
+ config.screenLayout = Configuration.SCREENLAYOUT_ROUND_YES;
+ Configuration config2 = new Configuration();
+
+ config.updateFrom(config2);
+ assertEquals(config.screenLayout, Configuration.SCREENLAYOUT_ROUND_YES);
+ }
+
+ @Test
+ public void testUpdateFromPreservesCompatNeededBit() {
+ Configuration config = new Configuration();
+ config.screenLayout = Configuration.SCREENLAYOUT_COMPAT_NEEDED;
+ Configuration config2 = new Configuration();
+ config.updateFrom(config2);
+ assertEquals(config.screenLayout, Configuration.SCREENLAYOUT_COMPAT_NEEDED);
+
+ config2.updateFrom(config);
+ assertEquals(config2.screenLayout, Configuration.SCREENLAYOUT_COMPAT_NEEDED);
+ }
+}
diff --git a/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java b/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java
new file mode 100644
index 0000000..9a81401
--- /dev/null
+++ b/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java
@@ -0,0 +1,161 @@
+package android.net;
+
+import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT;
+import static android.net.NetworkRecommendationProvider.EXTRA_SEQUENCE;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IRemoteCallback;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Unit test for the {@link NetworkRecommendationProvider}.
+ */
+public class NetworkRecommendationProviderTest extends InstrumentationTestCase {
+ @Mock private IRemoteCallback mMockRemoteCallback;
+ private NetworkRecProvider mRecProvider;
+ private Handler mHandler;
+ private INetworkRecommendationProvider mStub;
+ private CountDownLatch mRecRequestLatch;
+ private CountDownLatch mScoreRequestLatch;
+ private NetworkKey[] mTestNetworkKeys;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ // Configuration needed to make mockito/dexcache work.
+ final Context context = getInstrumentation().getTargetContext();
+ System.setProperty("dexmaker.dexcache",
+ context.getCacheDir().getPath());
+ ClassLoader newClassLoader = getInstrumentation().getClass().getClassLoader();
+ Thread.currentThread().setContextClassLoader(newClassLoader);
+
+ MockitoAnnotations.initMocks(this);
+
+ HandlerThread thread = new HandlerThread("NetworkRecommendationProviderTest");
+ thread.start();
+ mRecRequestLatch = new CountDownLatch(1);
+ mScoreRequestLatch = new CountDownLatch(1);
+ mHandler = new Handler(thread.getLooper());
+ mRecProvider = new NetworkRecProvider(mHandler, mRecRequestLatch, mScoreRequestLatch);
+ mStub = INetworkRecommendationProvider.Stub.asInterface(mRecProvider.getBinder());
+ mTestNetworkKeys = new NetworkKey[2];
+ mTestNetworkKeys[0] = new NetworkKey(new WifiKey("\"ssid_01\"", "00:00:00:00:00:11"));
+ mTestNetworkKeys[1] = new NetworkKey(new WifiKey("\"ssid_02\"", "00:00:00:00:00:22"));
+ }
+
+ @MediumTest
+ public void testRecommendationRequestReceived() throws Exception {
+ final RecommendationRequest request = new RecommendationRequest.Builder().build();
+ final int sequence = 100;
+ mStub.requestRecommendation(request, mMockRemoteCallback, sequence);
+
+ // wait for onRequestRecommendation() to be called in our impl below.
+ mRecRequestLatch.await(200, TimeUnit.MILLISECONDS);
+ NetworkRecommendationProvider.ResultCallback expectedResultCallback =
+ new NetworkRecommendationProvider.ResultCallback(mMockRemoteCallback, sequence);
+ assertEquals(request, mRecProvider.mCapturedRequest);
+ assertEquals(expectedResultCallback, mRecProvider.mCapturedCallback);
+ }
+
+ @SmallTest
+ public void testResultCallbackOnResult() throws Exception {
+ final int sequence = 100;
+ final NetworkRecommendationProvider.ResultCallback callback =
+ new NetworkRecommendationProvider.ResultCallback(mMockRemoteCallback, sequence);
+
+ final RecommendationResult result = new RecommendationResult(null);
+ callback.onResult(result);
+
+ final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ Mockito.verify(mMockRemoteCallback).sendResult(bundleCaptor.capture());
+ Bundle capturedBundle = bundleCaptor.getValue();
+ assertEquals(sequence, capturedBundle.getInt(EXTRA_SEQUENCE));
+ assertSame(result, capturedBundle.getParcelable(EXTRA_RECOMMENDATION_RESULT));
+ }
+
+ @SmallTest
+ public void testResultCallbackOnResult_runTwice_throwsException() throws Exception {
+ final int sequence = 100;
+ final NetworkRecommendationProvider.ResultCallback callback =
+ new NetworkRecommendationProvider.ResultCallback(mMockRemoteCallback, sequence);
+
+ final RecommendationResult result = new RecommendationResult(null);
+ callback.onResult(result);
+
+ try {
+ callback.onResult(result);
+ fail("Callback ran more than once.");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+
+ @MediumTest
+ public void testScoreRequestReceived() throws Exception {
+ mStub.requestScores(mTestNetworkKeys);
+
+ // wait for onRequestScores() to be called in our impl below.
+ mScoreRequestLatch.await(200, TimeUnit.MILLISECONDS);
+
+ assertSame(mTestNetworkKeys, mRecProvider.mCapturedNetworks);
+ }
+
+ @MediumTest
+ public void testScoreRequest_nullInput() throws Exception {
+ mStub.requestScores(null);
+
+ // onRequestScores() should never be called
+ assertFalse(mScoreRequestLatch.await(200, TimeUnit.MILLISECONDS));
+ }
+
+ @MediumTest
+ public void testScoreRequest_emptyInput() throws Exception {
+ mStub.requestScores(new NetworkKey[0]);
+
+ // onRequestScores() should never be called
+ assertFalse(mScoreRequestLatch.await(200, TimeUnit.MILLISECONDS));
+ }
+
+ private static class NetworkRecProvider extends NetworkRecommendationProvider {
+ private final CountDownLatch mRecRequestLatch;
+ private final CountDownLatch mScoreRequestLatch;
+ RecommendationRequest mCapturedRequest;
+ ResultCallback mCapturedCallback;
+ NetworkKey[] mCapturedNetworks;
+
+ NetworkRecProvider(Handler handler, CountDownLatch recRequestLatch,
+ CountDownLatch networkRequestLatch) {
+ super(handler);
+ mRecRequestLatch = recRequestLatch;
+ mScoreRequestLatch = networkRequestLatch;
+ }
+
+ @Override
+ public void onRequestRecommendation(RecommendationRequest request,
+ ResultCallback callback) {
+ mCapturedRequest = request;
+ mCapturedCallback = callback;
+ mRecRequestLatch.countDown();
+ }
+
+ @Override
+ public void onRequestScores(NetworkKey[] networks) {
+ mCapturedNetworks = networks;
+ mScoreRequestLatch.countDown();
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/provider/SettingsProviderTest.java b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
index 0a32e43..b0ce2c8 100644
--- a/core/tests/coretests/src/android/provider/SettingsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
@@ -351,6 +351,10 @@
assertCanBeHandled(new Intent(Settings.ACTION_WIFI_SETTINGS));
assertCanBeHandled(new Intent(Settings.ACTION_WIFI_SAVED_NETWORK_SETTINGS));
assertCanBeHandled(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
+
+ if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)) {
+ assertCanBeHandled(new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS));
+ }
}
private void assertCanBeHandled(final Intent intent) {
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index b6b0e68..bf994a9 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -179,13 +179,8 @@
ViewAppliedListener listener = new ViewAppliedListener();
views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener);
- boolean exceptionThrown = false;
- try {
- listener.waitAndGetView();
- } catch (Exception e) {
- exceptionThrown = true;
- }
- assertTrue(exceptionThrown);
+ exception.expect(Exception.class);
+ listener.waitAndGetView();
}
@Test
@@ -332,4 +327,43 @@
return mView;
}
}
+
+ @Test
+ public void nestedAddViews() {
+ RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test);
+ for (int i = 0; i < 10; i++) {
+ RemoteViews parent = new RemoteViews(mPackage, R.layout.remote_views_test);
+ parent.addView(R.id.layout, views);
+ views = parent;
+ }
+ views.clone();
+
+ views = new RemoteViews(mPackage, R.layout.remote_views_test);
+ for (int i = 0; i < 11; i++) {
+ RemoteViews parent = new RemoteViews(mPackage, R.layout.remote_views_test);
+ parent.addView(R.id.layout, views);
+ views = parent;
+ }
+ exception.expect(IllegalArgumentException.class);
+ views.clone();
+ }
+
+ @Test
+ public void nestedLandscapeViews() {
+ RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test);
+ for (int i = 0; i < 10; i++) {
+ views = new RemoteViews(views,
+ new RemoteViews(mPackage, R.layout.remote_views_test));
+ }
+ views.clone();
+
+ views = new RemoteViews(mPackage, R.layout.remote_views_test);
+ for (int i = 0; i < 11; i++) {
+ RemoteViews parent = new RemoteViews(mPackage, R.layout.remote_views_test);
+ parent.addView(R.id.layout, views);
+ views = parent;
+ }
+ exception.expect(IllegalArgumentException.class);
+ views.clone();
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java
index a15e367..f1aeecc 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java
@@ -18,12 +18,9 @@
import android.os.BatteryStats;
import android.os.Parcel;
import android.support.test.filters.SmallTest;
-import android.util.Log;
import junit.framework.TestCase;
-import org.mockito.Mockito;
-
/**
* Test BatteryStatsImpl.DurationTimer.
*
@@ -39,7 +36,7 @@
final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase();
timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime());
- final BatteryStatsImpl.DurationTimer timer = new BatteryStatsImpl.DurationTimer(clocks,
+ final BatteryStatsImpl.DurationTimer timer = new BatteryStatsImpl.DurationTimer(clocks,
null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase);
// TimeBase running, timer not running: current and max are 0
@@ -82,15 +79,15 @@
// Stop the TimeBase. The values should be frozen.
timeBase.setRunning(false, /* uptimeUs */ 10, /* realtimeUs */ 55000*1000);
assertTrue(timer.isRunningLocked());
- assertEquals(28100, timer.getCurrentDurationMsLocked(110100)); // Why 28100 and not 28000?
- assertEquals(28100, timer.getMaxDurationMsLocked(110101));
+ assertEquals(28000, timer.getCurrentDurationMsLocked(110100));
+ assertEquals(28000, timer.getMaxDurationMsLocked(110101));
// Start the TimeBase. The values should be the old value plus the delta
// between when the timer restarted and the current time
timeBase.setRunning(true, /* uptimeUs */ 10, /* realtimeUs */ 220100*1000);
assertTrue(timer.isRunningLocked());
- assertEquals(28300, timer.getCurrentDurationMsLocked(220300)); // extra 100 from above??
- assertEquals(28301, timer.getMaxDurationMsLocked(220301));
+ assertEquals(28200, timer.getCurrentDurationMsLocked(220300));
+ assertEquals(28201, timer.getMaxDurationMsLocked(220301));
}
@SmallTest
@@ -104,7 +101,7 @@
final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase();
timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime());
- final BatteryStatsImpl.DurationTimer timer = new BatteryStatsImpl.DurationTimer(clocks,
+ final BatteryStatsImpl.DurationTimer timer = new BatteryStatsImpl.DurationTimer(clocks,
null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase);
// Start running on battery.
@@ -124,7 +121,7 @@
summaryParcel.setDataPosition(0);
// Read summary
- final BatteryStatsImpl.DurationTimer summary = new BatteryStatsImpl.DurationTimer(clocks,
+ final BatteryStatsImpl.DurationTimer summary = new BatteryStatsImpl.DurationTimer(clocks,
null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase);
summary.startRunningLocked(3100);
summary.readSummaryFromParcelLocked(summaryParcel);
@@ -138,9 +135,9 @@
final Parcel fullParcel = Parcel.obtain();
timer.writeToParcel(fullParcel, 1500*1000);
fullParcel.setDataPosition(0);
-
+
// Read full - Should be the same as the summary as far as DurationTimer is concerned.
- final BatteryStatsImpl.DurationTimer full = new BatteryStatsImpl.DurationTimer(clocks,
+ final BatteryStatsImpl.DurationTimer full = new BatteryStatsImpl.DurationTimer(clocks,
null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase, fullParcel);
// The new one shouldn't be running, and therefore 0 for current time
assertFalse(full.isRunningLocked());
diff --git a/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java b/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
new file mode 100644
index 0000000..5dc07c2
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.view.View.MeasureSpec;
+import android.widget.TextView;
+
+import org.junit.Before;
+import org.junit.Test;
+
+@SmallTest
+public class ImageFloatingTextViewTest {
+
+ private Context mContext;
+ private ImageFloatingTextView mView;
+ private TextView mTextView;
+
+ @Before
+ public void setup() {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mView = new ImageFloatingTextView(mContext, null, 0, 0);
+ mTextView = new TextView(mContext, null, 0, 0);
+ mTextView.setMaxLines(9);
+ }
+
+ @Test
+ public void testEmpty() {
+ parametrizedTest("");
+ }
+
+ @Test
+ public void testSingleLine() {
+ parametrizedTest("Hello, World!");
+ }
+
+ @Test
+ public void testTwoLine() {
+ parametrizedTest("Hello, World!\nWhat a nice day!");
+ }
+
+ @Test
+ public void testShort() {
+ parametrizedTest("Hello, World! What a nice day! Let's try some more text. "
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet.");
+ }
+
+ @Test
+ public void testLong() {
+ parametrizedTest("Hello, World! What a nice day! Let's try some more text. "
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet."
+ + "Yada yada, yada yada. Lorem ipsum dolor sit amet.");
+ }
+
+ private void parametrizedTest(CharSequence text) {
+ int heightMeasureSpec = MeasureSpec.makeMeasureSpec(500, MeasureSpec.AT_MOST);
+ int widthMeasureSpec = MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY);
+
+ mTextView.setText(text);
+ mView.setText(text);
+
+ mTextView.measure(widthMeasureSpec, heightMeasureSpec);
+ mView.measure(widthMeasureSpec, heightMeasureSpec);
+
+ assertEquals(mTextView.getMeasuredHeight(), mView.getMeasuredHeight());
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
new file mode 100644
index 0000000..75b2c1d
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.os.Debug;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.espresso.core.deps.guava.base.Function;
+import android.support.test.filters.SmallTest;
+import android.view.LayoutInflater;
+import android.view.View.MeasureSpec;
+
+import com.android.frameworks.coretests.R;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+
+@SmallTest
+public class MessagingLinearLayoutTest {
+
+ public static final int WIDTH_SPEC = MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY);
+ public static final int HEIGHT_SPEC = MeasureSpec.makeMeasureSpec(400, MeasureSpec.AT_MOST);
+ private Context mContext;
+ private MessagingLinearLayout mView;
+
+ @Before
+ public void setup() {
+ mContext = InstrumentationRegistry.getTargetContext();
+ // maxHeight: 300px
+ // spacing: 50px
+ mView = (MessagingLinearLayout) LayoutInflater.from(mContext).inflate(
+ R.layout.messaging_linear_layout_test, null);
+ }
+
+ @Test
+ public void testSingleChild() {
+ FakeImageFloatingTextView child = fakeChild((i) -> 3);
+
+ mView.setNumIndentLines(2);
+ mView.addView(child);
+
+ mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
+ mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
+
+ assertEquals(3, child.getNumIndentLines());
+ assertFalse(child.isHidden());
+ assertEquals(150, mView.getMeasuredHeight());
+ }
+
+ @Test
+ public void testLargeSmall() {
+ FakeImageFloatingTextView child1 = fakeChild((i) -> 3);
+ FakeImageFloatingTextView child2 = fakeChild((i) -> 1);
+
+ mView.setNumIndentLines(2);
+ mView.addView(child1);
+ mView.addView(child2);
+
+ mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
+ mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
+
+ assertEquals(3, child1.getNumIndentLines());
+ assertEquals(0, child2.getNumIndentLines());
+ assertFalse(child1.isHidden());
+ assertFalse(child2.isHidden());
+ assertEquals(205, mView.getMeasuredHeight());
+ }
+
+ @Test
+ public void testSmallSmall() {
+ FakeImageFloatingTextView child1 = fakeChild((i) -> 1);
+ FakeImageFloatingTextView child2 = fakeChild((i) -> 1);
+
+ mView.setNumIndentLines(2);
+ mView.addView(child1);
+ mView.addView(child2);
+
+ mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
+ mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
+
+ assertEquals(2, child1.getNumIndentLines());
+ assertEquals(1, child2.getNumIndentLines());
+ assertFalse(child1.isHidden());
+ assertFalse(child2.isHidden());
+ assertEquals(105, mView.getMeasuredHeight());
+ }
+
+ @Test
+ public void testLargeLarge() {
+ FakeImageFloatingTextView child1 = fakeChild((i) -> 7);
+ FakeImageFloatingTextView child2 = fakeChild((i) -> 7);
+
+ mView.setNumIndentLines(2);
+ mView.addView(child1);
+ mView.addView(child2);
+
+ mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
+ mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
+
+ assertEquals(3, child2.getNumIndentLines());
+ assertTrue(child1.isHidden());
+ assertFalse(child2.isHidden());
+ assertEquals(300, mView.getMeasuredHeight());
+ }
+
+ @Test
+ public void testLargeSmall_largeWrapsWith3indentbutnot3_andHitsMax() {
+ FakeImageFloatingTextView child1 = fakeChild((i) -> i > 2 ? 5 : 4);
+ FakeImageFloatingTextView child2 = fakeChild((i) -> 1);
+
+ mView.setNumIndentLines(2);
+ mView.addView(child1);
+ mView.addView(child2);
+
+ mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
+ mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
+
+ assertTrue(child1.isHidden());
+ assertFalse(child2.isHidden());
+ assertEquals(50, mView.getMeasuredHeight());
+ assertEquals(2, child2.getNumIndentLines());
+ }
+
+ @Test
+ public void testLargeSmall_largeWrapsWith3indentbutnot3() {
+ FakeImageFloatingTextView child1 = fakeChild((i) -> i > 2 ? 4 : 3);
+ FakeImageFloatingTextView child2 = fakeChild((i) -> 1);
+
+ mView.setNumIndentLines(2);
+ mView.addView(child1);
+ mView.addView(child2);
+
+ mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
+ mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
+
+ assertFalse(child1.isHidden());
+ assertFalse(child2.isHidden());
+ assertEquals(255, mView.getMeasuredHeight());
+ assertEquals(3, child1.getNumIndentLines());
+ assertEquals(0, child2.getNumIndentLines());
+ }
+
+ private class FakeImageFloatingTextView extends ImageFloatingTextView {
+
+ public static final int LINE_HEIGHT = 50;
+ private final Function<Integer, Integer> mLinesForIndent;
+ private int mNumIndentLines;
+
+ public FakeImageFloatingTextView(Context context,
+ Function<Integer, Integer> linesForIndent) {
+ super(context, null, 0, 0);
+ mLinesForIndent = linesForIndent;
+ }
+
+ @Override
+ public boolean setNumIndentLines(int lines) {
+ boolean changed = (mNumIndentLines != lines);
+ mNumIndentLines = lines;
+ return changed;
+ }
+
+ public int getNumIndentLines() {
+ return mNumIndentLines;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(
+ getDefaultSize(500, widthMeasureSpec),
+ resolveSize(getDesiredHeight(), heightMeasureSpec));
+ }
+
+ @Override
+ public int getLineCount() {
+ return mLinesForIndent.apply(mNumIndentLines);
+ }
+
+ public int getDesiredHeight() {
+ return LINE_HEIGHT * getLineCount();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ // swallow
+ }
+
+ public boolean isHidden() {
+ MessagingLinearLayout.LayoutParams lp =
+ (MessagingLinearLayout.LayoutParams) getLayoutParams();
+ try {
+ Field hide = MessagingLinearLayout.LayoutParams.class.getDeclaredField("hide");
+ hide.setAccessible(true);
+ return hide.getBoolean(lp);
+ } catch (ReflectiveOperationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private FakeImageFloatingTextView fakeChild(Function<Integer,Integer> linesForIndent) {
+ return new FakeImageFloatingTextView(mContext, linesForIndent);
+ }
+}
diff --git a/core/tests/utiltests/Android.mk b/core/tests/utiltests/Android.mk
index 6e415f4..46a0d9b 100644
--- a/core/tests/utiltests/Android.mk
+++ b/core/tests/utiltests/Android.mk
@@ -12,6 +12,8 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SRC_FILES += src/android/util/IRemoteMemoryIntArray.aidl
+LOCAL_JNI_SHARED_LIBRARIES := libmemoryintarraytest libcutils libc++
+
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
frameworks-base-testutils \
diff --git a/core/tests/utiltests/jni/Android.bp b/core/tests/utiltests/jni/Android.bp
new file mode 100644
index 0000000..e9a4144
--- /dev/null
+++ b/core/tests/utiltests/jni/Android.bp
@@ -0,0 +1,27 @@
+// 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.
+
+cc_library_shared {
+ name: "libmemoryintarraytest",
+ shared_libs: [
+ "libcutils",
+ ],
+ clang: true,
+ stl: "libc++",
+ srcs: [
+ "registration.cpp",
+ "android_util_MemoryIntArrayTest.cpp",
+ ],
+ cflags: ["-Werror"],
+}
\ No newline at end of file
diff --git a/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp b/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
new file mode 100644
index 0000000..57ee2d5
--- /dev/null
+++ b/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#include <atomic>
+#include <jni.h>
+#include <cutils/ashmem.h>
+#include <linux/ashmem.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+jint android_util_MemoryIntArrayTest_createAshmem(__attribute__((unused)) JNIEnv* env,
+ __attribute__((unused)) jobject clazz,
+ jstring name, jint size)
+{
+
+ if (name == NULL) {
+ return -1;
+ }
+
+ if (size < 0) {
+ return -1;
+ }
+
+ const char* nameStr = env->GetStringUTFChars(name, NULL);
+ const int ashmemSize = sizeof(std::atomic_int) * size;
+ int fd = ashmem_create_region(nameStr, ashmemSize);
+ env->ReleaseStringUTFChars(name, nameStr);
+
+ if (fd < 0) {
+ return -1;
+ }
+
+ int setProtResult = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
+ if (setProtResult < 0) {
+ return -1;
+ }
+
+ return fd;
+}
+
+void android_util_MemoryIntArrayTest_setAshmemSize(__attribute__((unused)) JNIEnv* env,
+ __attribute__((unused)) jobject clazz, jint fd, jint size)
+{
+ if (fd < 0) {
+ return;
+ }
+
+ if (size < 0) {
+ return;
+ }
+
+ ioctl(fd, ASHMEM_SET_SIZE, size);
+}
diff --git a/core/tests/utiltests/jni/registration.cpp b/core/tests/utiltests/jni/registration.cpp
new file mode 100644
index 0000000..0c84d98
--- /dev/null
+++ b/core/tests/utiltests/jni/registration.cpp
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#include <jni.h>
+
+extern jint android_util_MemoryIntArrayTest_createAshmem(JNIEnv* env,
+ jobject clazz, jstring name, jint size);
+extern void android_util_MemoryIntArrayTest_setAshmemSize(JNIEnv* env,
+ jobject clazz, jint fd, jint size);
+
+extern "C" {
+ JNIEXPORT jint JNICALL Java_android_util_MemoryIntArrayTest_nativeCreateAshmem(
+ JNIEnv * env, jobject obj, jstring name, jint size);
+ JNIEXPORT void JNICALL Java_android_util_MemoryIntArrayTest_nativeSetAshmemSize(
+ JNIEnv * env, jobject obj, jint fd, jint size);
+};
+
+JNIEXPORT jint JNICALL Java_android_util_MemoryIntArrayTest_nativeCreateAshmem(
+ __attribute__((unused)) JNIEnv * env,__attribute__((unused)) jobject obj,
+ jstring name, jint size)
+{
+ return android_util_MemoryIntArrayTest_createAshmem(env, obj, name, size);
+}
+
+JNIEXPORT void JNICALL Java_android_util_MemoryIntArrayTest_nativeSetAshmemSize(
+ __attribute__((unused)) JNIEnv * env,__attribute__((unused)) jobject obj,
+ jint fd, jint size)
+{
+ android_util_MemoryIntArrayTest_setAshmemSize(env, obj, fd, size);
+}
diff --git a/core/tests/utiltests/src/android/util/IRemoteMemoryIntArray.aidl b/core/tests/utiltests/src/android/util/IRemoteMemoryIntArray.aidl
index 0a65fff2..10d14f1 100644
--- a/core/tests/utiltests/src/android/util/IRemoteMemoryIntArray.aidl
+++ b/core/tests/utiltests/src/android/util/IRemoteMemoryIntArray.aidl
@@ -20,11 +20,12 @@
interface IRemoteMemoryIntArray {
MemoryIntArray peekInstance();
- void create(int size, boolean clientWritable);
+ void create(int size);
boolean isWritable();
int get(int index);
void set(int index, int value);
int size();
void close();
boolean isClosed();
+ void accessLastElementInRemoteProcess(in MemoryIntArray array);
}
diff --git a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
index 129e6b7..85817bb 100644
--- a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
+++ b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
@@ -28,14 +28,22 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.lang.reflect.Field;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
@RunWith(AndroidJUnit4.class)
public class MemoryIntArrayTest {
+ static {
+ System.loadLibrary("cutils");
+ System.loadLibrary("memoryintarraytest");
+ }
@Test
public void testSize() throws Exception {
MemoryIntArray array = null;
try {
- array = new MemoryIntArray(3, false);
+ array = new MemoryIntArray(3);
assertEquals("size must be three", 3, array.size());
} finally {
IoUtils.closeQuietly(array);
@@ -46,7 +54,7 @@
public void testGetSet() throws Exception {
MemoryIntArray array = null;
try {
- array = new MemoryIntArray(3, false);
+ array = new MemoryIntArray(3);
array.set(0, 1);
array.set(1, 2);
@@ -64,7 +72,7 @@
public void testWritable() throws Exception {
MemoryIntArray array = null;
try {
- array = new MemoryIntArray(3, true);
+ array = new MemoryIntArray(3);
assertTrue("Must be mutable", array.isWritable());
} finally {
IoUtils.closeQuietly(array);
@@ -75,7 +83,7 @@
public void testClose() throws Exception {
MemoryIntArray array = null;
try {
- array = new MemoryIntArray(3, false);
+ array = new MemoryIntArray(3);
array.close();
assertTrue("Must be closed", array.isClosed());
} finally {
@@ -90,7 +98,7 @@
MemoryIntArray firstArray = null;
MemoryIntArray secondArray = null;
try {
- firstArray = new MemoryIntArray(3, false);
+ firstArray = new MemoryIntArray(3);
firstArray.set(0, 1);
firstArray.set(1, 2);
@@ -117,7 +125,7 @@
public void testInteractOnceClosed() throws Exception {
MemoryIntArray array = null;
try {
- array = new MemoryIntArray(3, false);
+ array = new MemoryIntArray(3);
array.close();
array.close();
@@ -160,7 +168,7 @@
public void testInteractPutOfBounds() throws Exception {
MemoryIntArray array = null;
try {
- array = new MemoryIntArray(3, false);
+ array = new MemoryIntArray(3);
try {
array.get(-1);
@@ -198,7 +206,7 @@
public void testOverMaxSize() throws Exception {
MemoryIntArray array = null;
try {
- array = new MemoryIntArray(MemoryIntArray.getMaxSize() + 1, false);
+ array = new MemoryIntArray(MemoryIntArray.getMaxSize() + 1);
fail("Cannot use over max size");
} catch (IllegalArgumentException e) {
/* expected */
@@ -209,7 +217,7 @@
@Test
public void testNotMutableByUnprivilegedClients() throws Exception {
- RemoteIntArray remoteIntArray = new RemoteIntArray(1, false);
+ RemoteIntArray remoteIntArray = new RemoteIntArray(1);
try {
assertNotNull("Couldn't get remote instance", remoteIntArray);
MemoryIntArray localIntArray = remoteIntArray.peekInstance();
@@ -230,4 +238,64 @@
remoteIntArray.destroy();
}
}
+
+ @Test
+ public void testAshmemSizeMatchesMemoryIntArraySize() throws Exception {
+ boolean success = false;
+
+ // Get a handle to a remote process to send the fd
+ RemoteIntArray remoteIntArray = new RemoteIntArray(1);
+ try {
+ // Let us try 100 times
+ for (int i = 0; i < 100; i++) {
+ // Create a MemoryIntArray to muck with
+ MemoryIntArray array = new MemoryIntArray(1);
+
+ // Create the fd to stuff in the MemoryIntArray
+ final int fd = nativeCreateAshmem("foo", 1);
+
+ // Replace the fd with our ahsmem region
+ Field fdFiled = MemoryIntArray.class.getDeclaredField("mFd");
+ fdFiled.setAccessible(true);
+ fdFiled.set(array, fd);
+
+ CountDownLatch countDownLatch = new CountDownLatch(2);
+
+ new Thread() {
+ @Override
+ public void run() {
+ for (int i = 2; i < Integer.MAX_VALUE; i++) {
+ if (countDownLatch.getCount() == 1) {
+ countDownLatch.countDown();
+ return;
+ }
+ nativeSetAshmemSize(fd, i);
+ }
+ }
+ }.start();
+
+ try {
+ remoteIntArray.accessLastElementInRemoteProcess(array);
+ } catch (IllegalArgumentException e) {
+ success = true;
+ }
+
+ countDownLatch.countDown();
+ countDownLatch.await(1000, TimeUnit.MILLISECONDS);
+
+ if (success) {
+ break;
+ }
+ }
+ } finally {
+ remoteIntArray.destroy();
+ }
+
+ if (!success) {
+ fail("MemoryIntArray should catch ahshmem size changing under it");
+ }
+ }
+
+ private native int nativeCreateAshmem(String name, int size);
+ private native void nativeSetAshmemSize(int fd, int size);
}
diff --git a/core/tests/utiltests/src/android/util/RemoteIntArray.java b/core/tests/utiltests/src/android/util/RemoteIntArray.java
index 10c325f..7dc3400 100644
--- a/core/tests/utiltests/src/android/util/RemoteIntArray.java
+++ b/core/tests/utiltests/src/android/util/RemoteIntArray.java
@@ -40,7 +40,7 @@
private android.util.IRemoteMemoryIntArray mRemoteInstance;
- public RemoteIntArray(int size, boolean clientWritable) throws IOException, TimeoutException {
+ public RemoteIntArray(int size) throws IOException, TimeoutException {
mIntent.setComponent(new ComponentName(InstrumentationRegistry.getContext(),
RemoteMemoryIntArrayService.class));
synchronized (mLock) {
@@ -48,7 +48,7 @@
bindLocked();
}
try {
- mRemoteInstance.create(size, clientWritable);
+ mRemoteInstance.create(size);
} catch (RemoteException e) {
throw new IOException(e);
}
@@ -148,6 +148,14 @@
}
}
+ public void accessLastElementInRemoteProcess(MemoryIntArray array) {
+ try {
+ mRemoteInstance.accessLastElementInRemoteProcess(array);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mLock) {
diff --git a/core/tests/utiltests/src/android/util/RemoteMemoryIntArrayService.java b/core/tests/utiltests/src/android/util/RemoteMemoryIntArrayService.java
index 35ae9a7..9264c6c 100644
--- a/core/tests/utiltests/src/android/util/RemoteMemoryIntArrayService.java
+++ b/core/tests/utiltests/src/android/util/RemoteMemoryIntArrayService.java
@@ -35,10 +35,10 @@
return new android.util.IRemoteMemoryIntArray.Stub() {
@Override
- public void create(int size, boolean clientWritable) {
+ public void create(int size) {
synchronized (mLock) {
try {
- mArray = new MemoryIntArray(size, clientWritable);
+ mArray = new MemoryIntArray(size);
} catch (IOException e) {
throw new IllegalStateException(e);
}
@@ -109,6 +109,15 @@
return mArray.isClosed();
}
}
+
+ @Override
+ public void accessLastElementInRemoteProcess(MemoryIntArray array) {
+ try {
+ array.get(array.size() - 1);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
};
}
}
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index f4c5b53..5baa75b 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -13,7 +13,7 @@
# limitations under the License.
# We have to use BUILD_PREBUILT instead of PRODUCT_COPY_FIES,
-# because SMALLER_FONT_FOOTPRINT is only available in Android.mks.
+# because MINIMAL_FONT_FOOTPRINT is only available in Android.mks.
LOCAL_PATH := $(call my-dir)
@@ -59,21 +59,6 @@
extra_font_files :=
################################
-# Include the DroidSansFallback subset on SMALLER_FONT_FOOTPRINT build
-ifeq ($(SMALLER_FONT_FOOTPRINT),true)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := DroidSansFallback.ttf
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts
-include $(BUILD_PREBUILT)
-droidsans_fallback_src :=
-
-endif # SMALLER_FONT_FOOTPRINT
-
-################################
# Build the rest of font files as prebuilt.
# $(1): The source file name in LOCAL_PATH.
@@ -101,7 +86,7 @@
checkbuild: fontchain_lint
FONTCHAIN_LINTER := frameworks/base/tools/fonts/fontchain_lint.py
-ifeq ($(SMALLER_FONT_FOOTPRINT),true)
+ifeq ($(MINIMAL_FONT_FOOTPRINT),true)
CHECK_EMOJI := false
else
CHECK_EMOJI := true
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index acd785e..23c54ae 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -18,6 +18,5 @@
frameworks/base/data/fonts/fonts.xml:$(TARGET_COPY_OUT_SYSTEM)/etc/fonts.xml
PRODUCT_PACKAGES := \
- DroidSansFallback.ttf \
DroidSansMono.ttf \
- AndroidClock.ttf \
+ AndroidClock.ttf
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 345ec37..465e207 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -353,9 +353,6 @@
<family lang="und-Zsym">
<font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted2.ttf</font>
</family>
- <family>
- <font weight="400" style="normal">DroidSansFallback.ttf</font>
- </family>
<!--
Tai Le and Mongolian are intentionally kept last, to make sure they don't override
the East Asian punctuation for Chinese.
diff --git a/docs/html/reference/packages-wearable-support.html b/docs/html/reference/packages-wearable-support.html
index aff2e34..a8d9446 100644
--- a/docs/html/reference/packages-wearable-support.html
+++ b/docs/html/reference/packages-wearable-support.html
@@ -113,7 +113,7 @@
<!-- JAVASCRIPT -->
-<script src="http://www.google.com/jsapi" type="text/javascript"></script>
+<script src="//www.google.com/jsapi" type="text/javascript"></script>
<script src="../assets/js/android_3p-bundle.js" type="text/javascript"></script>
<script type="text/javascript">
var toRoot = "../";
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes.html b/docs/html/sdk/support_api_diff/25.0.0/changes.html
new file mode 100644
index 0000000..cd9b0a5
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<!-- on Fri Nov 11 17:08:02 EST 2016 -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Support Library API Differences Report
+</TITLE>
+<link href="../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</head>
+<frameset cols="242,**" framespacing="1" frameborder="yes" border="1" bordercolor="#e9e9e9">
+<frameset rows="174,**" framespacing="1" frameborder="yes" border="1" bordercolor="#e9e9e9">
+ <frame src="changes/jdiff_topleftframe.html" scrolling="no" name="topleftframe" frameborder="1">
+ <frame src="changes/alldiffs_index_all.html" scrolling="auto" name="bottomleftframe" frameborder="1">
+ </frameset>
+ <frame src="changes/changes-summary.html" scrolling="auto" name="rightframe" frameborder="1">
+</frameset>
+<noframes>
+<h2>
+Frame Alert
+</h2>
+
+<p>
+This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+<br>
+Link to <a href="changes/changes-summary.html" target="_top">Non-frame version.</A>
+</noframes>
+</html>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_additions.html b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_additions.html
new file mode 100644
index 0000000..369d9b1
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_additions.html
@@ -0,0 +1,252 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a>
+ <br>
+<A HREF="alldiffs_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<b>Additions</b>
+ <br>
+<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<!-- Constructor ActivityCompat -->
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v13.app.ActivityCompat.html#android.support.v13.app.ActivityCompat.ctor_added()" class="hiddenlink" target="rightframe"><b>ActivityCompat</b>
+()</A></nobr> constructor<br>
+<!-- Package android.support.v13.view.inputmethod -->
+<A HREF="changes-summary.html#android.support.v13.view.inputmethod" class="hiddenlink" target="rightframe"><b>android.support.v13.view.inputmethod</b></A><br>
+<!-- Class BottomNavigationView -->
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView" class="hiddenlink" target="rightframe"><b>BottomNavigationView</b></A><br>
+<!-- Class BottomNavigationView.OnNavigationItemSelectedListener -->
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView.OnNavigationItemSelectedListener" class="hiddenlink" target="rightframe"><b><i>BottomNavigationView.OnNavigationItemSelectedListener</i></b></A><br>
+<!-- Class DividerItemDecoration -->
+<A NAME="D"></A>
+<br><font size="+2">D</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#DividerItemDecoration" class="hiddenlink" target="rightframe"><b>DividerItemDecoration</b></A><br>
+<!-- Method getBridgeTag -->
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.getBridgeTag_added()" class="hiddenlink" target="rightframe"><b>getBridgeTag</b>
+()</A></nobr><br>
+<!-- Method getDecoratedBoundsWithMargins -->
+<nobr><A HREF="android.support.v7.widget.RecyclerView.html#android.support.v7.widget.RecyclerView.getDecoratedBoundsWithMargins_added(android.view.View, android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getDecoratedBoundsWithMargins</b>
+(<code>View, Rect</code>)</A></nobr><br>
+<!-- Method getDisplay -->
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.getDisplay_added(android.view.View)" class="hiddenlink" target="rightframe"><b>getDisplay</b>
+(<code>View</code>)</A></nobr><br>
+<!-- Method getProgressViewEndOffset -->
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewEndOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewEndOffset</b>
+()</A></nobr><br>
+<!-- Method getProgressViewStartOffset -->
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewStartOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewStartOffset</b>
+()</A></nobr><br>
+<!-- Method getRestrictBackgroundStatus -->
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.getRestrictBackgroundStatus_added(android.net.ConnectivityManager)" class="hiddenlink" target="rightframe"><b>getRestrictBackgroundStatus</b>
+(<code>ConnectivityManager</code>)</A></nobr><br>
+<!-- Method getRippleColor -->
+<nobr><A HREF="android.support.design.widget.FloatingActionButton.html#android.support.design.widget.FloatingActionButton.getRippleColor_added()" class="hiddenlink" target="rightframe"><b>getRippleColor</b>
+()</A></nobr><br>
+<!-- Method isItemPrefetchEnabled -->
+<A NAME="I"></A>
+<br><font size="+2">I</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.isItemPrefetchEnabled_added()" class="hiddenlink" target="rightframe"><b>isItemPrefetchEnabled</b>
+()</A></nobr><br>
+<!-- Method isRtl -->
+<nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.isRtl_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>isRtl</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<!-- Class NotificationCompat.DecoratedCustomViewStyle -->
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedCustomViewStyle</b></A><br>
+<!-- Class NotificationCompat.DecoratedMediaCustomViewStyle -->
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedMediaCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedMediaCustomViewStyle</b></A><br>
+<!-- Field RESTRICT_BACKGROUND_STATUS_DISABLED -->
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_DISABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_DISABLED</A>
+</nobr><br>
+<!-- Field RESTRICT_BACKGROUND_STATUS_ENABLED -->
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_ENABLED</A>
+</nobr><br>
+<!-- Field RESTRICT_BACKGROUND_STATUS_WHITELISTED -->
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_WHITELISTED</A>
+</nobr><br>
+<!-- Method setBackground -->
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.setBackground_added(android.view.View, android.graphics.drawable.Drawable)" class="hiddenlink" target="rightframe"><b>setBackground</b>
+(<code>View, Drawable</code>)</A></nobr><br>
+<!-- Method setBridgeTag -->
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.setBridgeTag_added(java.lang.String)" class="hiddenlink" target="rightframe"><b>setBridgeTag</b>
+(<code>String</code>)</A></nobr><br>
+<!-- Method setItemPrefetchEnabled -->
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.setItemPrefetchEnabled_added(boolean)" class="hiddenlink" target="rightframe"><b>setItemPrefetchEnabled</b>
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method setPageTransformer -->
+<nobr><A HREF="android.support.v4.view.ViewPager.html#android.support.v4.view.ViewPager.setPageTransformer_added(boolean, android.support.v4.view.ViewPager.PageTransformer, int)" class="hiddenlink" target="rightframe"><b>setPageTransformer</b>
+(<code>boolean, PageTransformer, int</code>)</A></nobr><br>
+<!-- Method startActivity -->
+<nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.startActivity_added(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe"><b>startActivity</b>
+(<code>Context, Intent, Bundle</code>)</A></nobr><br>
+<!-- Method unicodeWrap -->
+<A NAME="U"></A>
+<br><font size="+2">U</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>unicodeWrap</i><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<!-- Method unicodeWrap -->
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<!-- Method unicodeWrap -->
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<!-- Method unicodeWrap -->
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_all.html b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_all.html
new file mode 100644
index 0000000..9396e52
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_all.html
@@ -0,0 +1,422 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>All Differences</b>
+ <br>
+<A HREF="alldiffs_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<!-- Class ActivityCompat -->
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>ActivityCompat</i><br>
+ <A HREF="android.support.v13.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+<!-- Class ActivityCompat -->
+ <A HREF="android.support.v4.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<!-- Constructor ActivityCompat -->
+ <nobr><A HREF="android.support.v13.app.ActivityCompat.html#android.support.v13.app.ActivityCompat.ctor_added()" class="hiddenlink" target="rightframe"><b>ActivityCompat</b>
+()</A></nobr> constructor<br>
+<!-- Constructor ActivityCompat -->
+ <nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.ctor_changed()" class="hiddenlink" target="rightframe">ActivityCompat
+()</A></nobr> constructor<br>
+<!-- Package android.support.customtabs -->
+<A HREF="pkg_android.support.customtabs.html" class="hiddenlink" target="rightframe">android.support.customtabs</A><br>
+<!-- Package android.support.design.widget -->
+<A HREF="pkg_android.support.design.widget.html" class="hiddenlink" target="rightframe">android.support.design.widget</A><br>
+<!-- Package android.support.v13.app -->
+<A HREF="pkg_android.support.v13.app.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+<!-- Package android.support.v13.view.inputmethod -->
+<A HREF="changes-summary.html#android.support.v13.view.inputmethod" class="hiddenlink" target="rightframe"><b>android.support.v13.view.inputmethod</b></A><br>
+<!-- Package android.support.v4.app -->
+<A HREF="pkg_android.support.v4.app.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<!-- Package android.support.v4.content -->
+<A HREF="pkg_android.support.v4.content.html" class="hiddenlink" target="rightframe">android.support.v4.content</A><br>
+<!-- Package android.support.v4.net -->
+<A HREF="pkg_android.support.v4.net.html" class="hiddenlink" target="rightframe">android.support.v4.net</A><br>
+<!-- Package android.support.v4.text -->
+<A HREF="pkg_android.support.v4.text.html" class="hiddenlink" target="rightframe">android.support.v4.text</A><br>
+<!-- Package android.support.v4.view -->
+<A HREF="pkg_android.support.v4.view.html" class="hiddenlink" target="rightframe">android.support.v4.view</A><br>
+<!-- Package android.support.v4.widget -->
+<A HREF="pkg_android.support.v4.widget.html" class="hiddenlink" target="rightframe">android.support.v4.widget</A><br>
+<!-- Package android.support.v7.app -->
+<A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
+<!-- Package android.support.v7.widget -->
+<A HREF="pkg_android.support.v7.widget.html" class="hiddenlink" target="rightframe">android.support.v7.widget</A><br>
+<!-- Class BidiFormatter -->
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.text.BidiFormatter.html" class="hiddenlink" target="rightframe">BidiFormatter</A><br>
+<!-- Class BottomNavigationView -->
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView" class="hiddenlink" target="rightframe"><b>BottomNavigationView</b></A><br>
+<!-- Class BottomNavigationView.OnNavigationItemSelectedListener -->
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView.OnNavigationItemSelectedListener" class="hiddenlink" target="rightframe"><b><i>BottomNavigationView.OnNavigationItemSelectedListener</i></b></A><br>
+<!-- Class ConnectivityManagerCompat -->
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.net.ConnectivityManagerCompat.html" class="hiddenlink" target="rightframe">ConnectivityManagerCompat</A><br>
+<!-- Class ContextCompat -->
+<i>ContextCompat</i><br>
+ <A HREF="android.support.v4.content.ContextCompat.html" class="hiddenlink" target="rightframe">android.support.v4.content</A><br>
+<!-- Constructor ContextCompat -->
+ <nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.ctor_changed()" class="hiddenlink" target="rightframe">ContextCompat
+()</A></nobr> constructor<br>
+<!-- Class CustomTabsIntent -->
+<A HREF="android.support.customtabs.CustomTabsIntent.html" class="hiddenlink" target="rightframe">CustomTabsIntent</A><br>
+<!-- Class DividerItemDecoration -->
+<A NAME="D"></A>
+<br><font size="+2">D</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#DividerItemDecoration" class="hiddenlink" target="rightframe"><b>DividerItemDecoration</b></A><br>
+<!-- Class FloatingActionButton -->
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.design.widget.FloatingActionButton.html" class="hiddenlink" target="rightframe">FloatingActionButton</A><br>
+<!-- Method getBridgeTag -->
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.getBridgeTag_added()" class="hiddenlink" target="rightframe"><b>getBridgeTag</b>
+()</A></nobr><br>
+<!-- Method getDecoratedBoundsWithMargins -->
+<nobr><A HREF="android.support.v7.widget.RecyclerView.html#android.support.v7.widget.RecyclerView.getDecoratedBoundsWithMargins_added(android.view.View, android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getDecoratedBoundsWithMargins</b>
+(<code>View, Rect</code>)</A></nobr><br>
+<!-- Method getDisplay -->
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.getDisplay_added(android.view.View)" class="hiddenlink" target="rightframe"><b>getDisplay</b>
+(<code>View</code>)</A></nobr><br>
+<!-- Method getProgressViewEndOffset -->
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewEndOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewEndOffset</b>
+()</A></nobr><br>
+<!-- Method getProgressViewStartOffset -->
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewStartOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewStartOffset</b>
+()</A></nobr><br>
+<!-- Method getReferrer -->
+<nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.getReferrer_changed(android.app.Activity)" class="hiddenlink" target="rightframe">getReferrer
+(<code>Activity</code>)</A></nobr><br>
+<!-- Method getRestrictBackgroundStatus -->
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.getRestrictBackgroundStatus_added(android.net.ConnectivityManager)" class="hiddenlink" target="rightframe"><b>getRestrictBackgroundStatus</b>
+(<code>ConnectivityManager</code>)</A></nobr><br>
+<!-- Method getRippleColor -->
+<nobr><A HREF="android.support.design.widget.FloatingActionButton.html#android.support.design.widget.FloatingActionButton.getRippleColor_added()" class="hiddenlink" target="rightframe"><b>getRippleColor</b>
+()</A></nobr><br>
+<!-- Method isItemPrefetchEnabled -->
+<A NAME="I"></A>
+<br><font size="+2">I</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.isItemPrefetchEnabled_added()" class="hiddenlink" target="rightframe"><b>isItemPrefetchEnabled</b>
+()</A></nobr><br>
+<!-- Method isRtl -->
+<nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.isRtl_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>isRtl</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<!-- Method launchUrl -->
+<A NAME="L"></A>
+<br><font size="+2">L</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.customtabs.CustomTabsIntent.html#android.support.customtabs.CustomTabsIntent.launchUrl_changed(android.content.Context, android.net.Uri)" class="hiddenlink" target="rightframe">launchUrl
+(<code>Context, Uri</code>)</A></nobr><br>
+<!-- Class NotificationCompat.DecoratedCustomViewStyle -->
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedCustomViewStyle</b></A><br>
+<!-- Class NotificationCompat.DecoratedMediaCustomViewStyle -->
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedMediaCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedMediaCustomViewStyle</b></A><br>
+<!-- Class NotificationCompat.WearableExtender -->
+<A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html" class="hiddenlink" target="rightframe">NotificationCompat.WearableExtender</A><br>
+<!-- Class RecyclerView -->
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v7.widget.RecyclerView.html" class="hiddenlink" target="rightframe">RecyclerView</A><br>
+<!-- Class RecyclerView.LayoutManager -->
+<A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html" class="hiddenlink" target="rightframe">RecyclerView.LayoutManager</A><br>
+<!-- Field RESTRICT_BACKGROUND_STATUS_DISABLED -->
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_DISABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_DISABLED</A>
+</nobr><br>
+<!-- Field RESTRICT_BACKGROUND_STATUS_ENABLED -->
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_ENABLED</A>
+</nobr><br>
+<!-- Field RESTRICT_BACKGROUND_STATUS_WHITELISTED -->
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_WHITELISTED</A>
+</nobr><br>
+<!-- Method setBackground -->
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#U"><font size="-2">U</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.setBackground_added(android.view.View, android.graphics.drawable.Drawable)" class="hiddenlink" target="rightframe"><b>setBackground</b>
+(<code>View, Drawable</code>)</A></nobr><br>
+<!-- Method setBridgeTag -->
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.setBridgeTag_added(java.lang.String)" class="hiddenlink" target="rightframe"><b>setBridgeTag</b>
+(<code>String</code>)</A></nobr><br>
+<!-- Method setItemPrefetchEnabled -->
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.setItemPrefetchEnabled_added(boolean)" class="hiddenlink" target="rightframe"><b>setItemPrefetchEnabled</b>
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method setPageTransformer -->
+<nobr><A HREF="android.support.v4.view.ViewPager.html#android.support.v4.view.ViewPager.setPageTransformer_added(boolean, android.support.v4.view.ViewPager.PageTransformer, int)" class="hiddenlink" target="rightframe"><b>setPageTransformer</b>
+(<code>boolean, PageTransformer, int</code>)</A></nobr><br>
+<!-- Class Space -->
+<A HREF="pkg_android.support.v7.widget.html#Space" class="hiddenlink" target="rightframe"><strike>Space</strike></A><br>
+<!-- Method startActivity -->
+<i>startActivity</i><br>
+ <nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.startActivity_changed(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe">type
+(<code>Context, Intent, Bundle</code>) in android.support.v4.app.ActivityCompat
+</A></nobr><br>
+<!-- Method startActivity -->
+ <nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.startActivity_added(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe">type <b>
+(<code>Context, Intent, Bundle</code>)</b> in android.support.v4.content.ContextCompat
+</A></nobr><br>
+<!-- Class SwipeRefreshLayout -->
+<A HREF="android.support.v4.widget.SwipeRefreshLayout.html" class="hiddenlink" target="rightframe">SwipeRefreshLayout</A><br>
+<!-- Method unicodeWrap -->
+<A NAME="U"></A>
+<br><font size="+2">U</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>unicodeWrap</i><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<!-- Method unicodeWrap -->
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<!-- Method unicodeWrap -->
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<!-- Method unicodeWrap -->
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<!-- Class ViewCompat -->
+<A NAME="V"></A>
+<br><font size="+2">V</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.view.ViewCompat.html" class="hiddenlink" target="rightframe">ViewCompat</A><br>
+<!-- Class ViewPager -->
+<A HREF="android.support.v4.view.ViewPager.html" class="hiddenlink" target="rightframe">ViewPager</A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_changes.html b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_changes.html
new file mode 100644
index 0000000..e0c9f1e
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_changes.html
@@ -0,0 +1,256 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a>
+ <br>
+<A HREF="alldiffs_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<!-- Class ActivityCompat -->
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>ActivityCompat</i><br>
+ <A HREF="android.support.v13.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+<!-- Class ActivityCompat -->
+ <A HREF="android.support.v4.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<!-- Constructor ActivityCompat -->
+ <nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.ctor_changed()" class="hiddenlink" target="rightframe">ActivityCompat
+()</A></nobr> constructor<br>
+<!-- Package android.support.customtabs -->
+<A HREF="pkg_android.support.customtabs.html" class="hiddenlink" target="rightframe">android.support.customtabs</A><br>
+<!-- Package android.support.design.widget -->
+<A HREF="pkg_android.support.design.widget.html" class="hiddenlink" target="rightframe">android.support.design.widget</A><br>
+<!-- Package android.support.v13.app -->
+<A HREF="pkg_android.support.v13.app.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+<!-- Package android.support.v4.app -->
+<A HREF="pkg_android.support.v4.app.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<!-- Package android.support.v4.content -->
+<A HREF="pkg_android.support.v4.content.html" class="hiddenlink" target="rightframe">android.support.v4.content</A><br>
+<!-- Package android.support.v4.net -->
+<A HREF="pkg_android.support.v4.net.html" class="hiddenlink" target="rightframe">android.support.v4.net</A><br>
+<!-- Package android.support.v4.text -->
+<A HREF="pkg_android.support.v4.text.html" class="hiddenlink" target="rightframe">android.support.v4.text</A><br>
+<!-- Package android.support.v4.view -->
+<A HREF="pkg_android.support.v4.view.html" class="hiddenlink" target="rightframe">android.support.v4.view</A><br>
+<!-- Package android.support.v4.widget -->
+<A HREF="pkg_android.support.v4.widget.html" class="hiddenlink" target="rightframe">android.support.v4.widget</A><br>
+<!-- Package android.support.v7.app -->
+<A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
+<!-- Package android.support.v7.widget -->
+<A HREF="pkg_android.support.v7.widget.html" class="hiddenlink" target="rightframe">android.support.v7.widget</A><br>
+<!-- Class BidiFormatter -->
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.text.BidiFormatter.html" class="hiddenlink" target="rightframe">BidiFormatter</A><br>
+<!-- Class ConnectivityManagerCompat -->
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.net.ConnectivityManagerCompat.html" class="hiddenlink" target="rightframe">ConnectivityManagerCompat</A><br>
+<!-- Class ContextCompat -->
+<i>ContextCompat</i><br>
+ <A HREF="android.support.v4.content.ContextCompat.html" class="hiddenlink" target="rightframe">android.support.v4.content</A><br>
+<!-- Constructor ContextCompat -->
+ <nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.ctor_changed()" class="hiddenlink" target="rightframe">ContextCompat
+()</A></nobr> constructor<br>
+<!-- Class CustomTabsIntent -->
+<A HREF="android.support.customtabs.CustomTabsIntent.html" class="hiddenlink" target="rightframe">CustomTabsIntent</A><br>
+<!-- Class FloatingActionButton -->
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.design.widget.FloatingActionButton.html" class="hiddenlink" target="rightframe">FloatingActionButton</A><br>
+<!-- Method getReferrer -->
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.getReferrer_changed(android.app.Activity)" class="hiddenlink" target="rightframe">getReferrer
+(<code>Activity</code>)</A></nobr><br>
+<!-- Method launchUrl -->
+<A NAME="L"></A>
+<br><font size="+2">L</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.customtabs.CustomTabsIntent.html#android.support.customtabs.CustomTabsIntent.launchUrl_changed(android.content.Context, android.net.Uri)" class="hiddenlink" target="rightframe">launchUrl
+(<code>Context, Uri</code>)</A></nobr><br>
+<!-- Class NotificationCompat.WearableExtender -->
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html" class="hiddenlink" target="rightframe">NotificationCompat.WearableExtender</A><br>
+<!-- Class RecyclerView -->
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v7.widget.RecyclerView.html" class="hiddenlink" target="rightframe">RecyclerView</A><br>
+<!-- Class RecyclerView.LayoutManager -->
+<A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html" class="hiddenlink" target="rightframe">RecyclerView.LayoutManager</A><br>
+<!-- Method startActivity -->
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.startActivity_changed(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe">startActivity
+(<code>Context, Intent, Bundle</code>)</A></nobr><br>
+<!-- Class SwipeRefreshLayout -->
+<A HREF="android.support.v4.widget.SwipeRefreshLayout.html" class="hiddenlink" target="rightframe">SwipeRefreshLayout</A><br>
+<!-- Class ViewCompat -->
+<A NAME="V"></A>
+<br><font size="+2">V</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.view.ViewCompat.html" class="hiddenlink" target="rightframe">ViewCompat</A><br>
+<!-- Class ViewPager -->
+<A HREF="android.support.v4.view.ViewPager.html" class="hiddenlink" target="rightframe">ViewPager</A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_removals.html b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_removals.html
new file mode 100644
index 0000000..76010db1
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/alldiffs_index_removals.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a>
+ <br>
+<b>Removals</b>
+ <br>
+<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<!-- Class Space -->
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#Space" class="hiddenlink" target="rightframe"><strike>Space</strike></A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.customtabs.CustomTabsIntent.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.customtabs.CustomTabsIntent.html
new file mode 100644
index 0000000..891be3d
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.customtabs.CustomTabsIntent.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.customtabs.CustomTabsIntent
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.customtabs.<A HREF="../../../../reference/android/support/customtabs/CustomTabsIntent.html" target="_top"><font size="+2"><code>CustomTabsIntent</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.customtabs.CustomTabsIntent.launchUrl_changed(android.content.Context, android.net.Uri)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/customtabs/CustomTabsIntent.html#launchUrl(android.content.Context, android.net.Uri)" target="_top"><code>launchUrl</code></A>(<code>Context,</nobr> Uri<nobr><nobr></code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Change in signature from (<code>Activity, Uri</code>) to (<code>Context, Uri</code>).<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.design.widget.FloatingActionButton.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.design.widget.FloatingActionButton.html
new file mode 100644
index 0000000..d048222
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.design.widget.FloatingActionButton.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.design.widget.FloatingActionButton
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.design.widget.<A HREF="../../../../reference/android/support/design/widget/FloatingActionButton.html" target="_top"><font size="+2"><code>FloatingActionButton</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.design.widget.FloatingActionButton.getRippleColor_added()"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/design/widget/FloatingActionButton.html#getRippleColor()" target="_top"><code>getRippleColor</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v13.app.ActivityCompat.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v13.app.ActivityCompat.html
new file mode 100644
index 0000000..c11dce2
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v13.app.ActivityCompat.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v13.app.ActivityCompat
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v13.app.<A HREF="../../../../reference/android/support/v13/app/ActivityCompat.html" target="_top"><font size="+2"><code>ActivityCompat</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Constructors" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Constructors</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v13.app.ActivityCompat.ctor_added()"></A>
+ <nobr><A HREF="../../../../reference/android/support/v13/app/ActivityCompat.html#ActivityCompat()" target="_top"><code>ActivityCompat</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.app.ActivityCompat.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.app.ActivityCompat.html
new file mode 100644
index 0000000..e728c87
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.app.ActivityCompat.html
@@ -0,0 +1,154 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.app.ActivityCompat
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.app.<A HREF="../../../../reference/android/support/v4/app/ActivityCompat.html" target="_top"><font size="+2"><code>ActivityCompat</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Constructors" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Constructors</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.ActivityCompat.ctor_changed()"></A>
+ <nobr><A HREF="../../../../reference/android/support/v4/app/ActivityCompat.html#ActivityCompat()" target="_top"><code>ActivityCompat</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Change from deprecated to undeprecated.<br> Change of visibility from public to protected.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="methods"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.ActivityCompat.getReferrer_changed(android.app.Activity)"></A>
+ <nobr><code>Uri</code> <A HREF="../../../../reference/android/support/v4/app/ActivityCompat.html#getReferrer(android.app.Activity)" target="_top"><code>getReferrer</code></A>(<code>Activity</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Change from non-static to static.<br> Change from deprecated to undeprecated.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.ActivityCompat.startActivity_changed(android.content.Context, android.content.Intent, android.os.Bundle)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v4/content/ContextCompat.html#startActivity(android.content.Context, android.content.Intent, android.os.Bundle)" target="_top"><code>startActivity</code></A>(<code>Context,</nobr> Intent<nobr>,</nobr> Bundle<nobr><nobr></code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Change in signature from (<code>Activity, Intent, Bundle</code>) to (<code>Context, Intent, Bundle</code>).<br>
+ Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v4/content/ContextCompat.html#startActivity(android.content.Context, android.content.Intent, android.os.Bundle)" target="_top"><code>ContextCompat</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.app.NotificationCompat.WearableExtender.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.app.NotificationCompat.WearableExtender.html
new file mode 100644
index 0000000..fb9d1fc
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.app.NotificationCompat.WearableExtender.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.app.NotificationCompat.WearableExtender
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.app.<A HREF="../../../../reference/android/support/v4/app/NotificationCompat.WearableExtender.html" target="_top"><font size="+2"><code>NotificationCompat.WearableExtender</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.NotificationCompat.WearableExtender.getBridgeTag_added()"></A>
+ <nobr><code>String</code> <A HREF="../../../../reference/android/support/v4/app/NotificationCompat.WearableExtender.html#getBridgeTag()" target="_top"><code>getBridgeTag</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.NotificationCompat.WearableExtender.setBridgeTag_added(java.lang.String)"></A>
+ <nobr><code>WearableExtender</code> <A HREF="../../../../reference/android/support/v4/app/NotificationCompat.WearableExtender.html#setBridgeTag(java.lang.String)" target="_top"><code>setBridgeTag</code></A>(<code>String</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.content.ContextCompat.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.content.ContextCompat.html
new file mode 100644
index 0000000..ffcebd0
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.content.ContextCompat.html
@@ -0,0 +1,140 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.content.ContextCompat
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.content.<A HREF="../../../../reference/android/support/v4/content/ContextCompat.html" target="_top"><font size="+2"><code>ContextCompat</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Constructors" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Constructors</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.content.ContextCompat.ctor_changed()"></A>
+ <nobr><A HREF="../../../../reference/android/support/v4/content/ContextCompat.html#ContextCompat()" target="_top"><code>ContextCompat</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Change from deprecated to undeprecated.<br> Change of visibility from public to protected.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.content.ContextCompat.startActivity_added(android.content.Context, android.content.Intent, android.os.Bundle)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v4/content/ContextCompat.html#startActivity(android.content.Context, android.content.Intent, android.os.Bundle)" target="_top"><code>startActivity</code></A>(<code>Context,</nobr> Intent<nobr>,</nobr> Bundle<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.net.ConnectivityManagerCompat.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.net.ConnectivityManagerCompat.html
new file mode 100644
index 0000000..f9ca4c0
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.net.ConnectivityManagerCompat.html
@@ -0,0 +1,151 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.net.ConnectivityManagerCompat
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.net.<A HREF="../../../../reference/android/support/v4/net/ConnectivityManagerCompat.html" target="_top"><font size="+2"><code>ConnectivityManagerCompat</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.net.ConnectivityManagerCompat.getRestrictBackgroundStatus_added(android.net.ConnectivityManager)"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v4/net/ConnectivityManagerCompat.html#getRestrictBackgroundStatus(android.net.ConnectivityManager)" target="_top"><code>getRestrictBackgroundStatus</code></A>(<code>ConnectivityManager</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Fields" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Fields</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_DISABLED"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v4/net/ConnectivityManagerCompat.html#RESTRICT_BACKGROUND_STATUS_DISABLED" target="_top"><code>RESTRICT_BACKGROUND_STATUS_DISABLED</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v4/net/ConnectivityManagerCompat.html#RESTRICT_BACKGROUND_STATUS_ENABLED" target="_top"><code>RESTRICT_BACKGROUND_STATUS_ENABLED</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v4/net/ConnectivityManagerCompat.html#RESTRICT_BACKGROUND_STATUS_WHITELISTED" target="_top"><code>RESTRICT_BACKGROUND_STATUS_WHITELISTED</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.text.BidiFormatter.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.text.BidiFormatter.html
new file mode 100644
index 0000000..63ee221
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.text.BidiFormatter.html
@@ -0,0 +1,150 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.text.BidiFormatter
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.text.<A HREF="../../../../reference/android/support/v4/text/BidiFormatter.html" target="_top"><font size="+2"><code>BidiFormatter</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.text.BidiFormatter.isRtl_added(java.lang.CharSequence)"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v4/text/BidiFormatter.html#isRtl(java.lang.CharSequence)" target="_top"><code>isRtl</code></A>(<code>CharSequence</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence)"></A>
+ <nobr><code>CharSequence</code> <A HREF="../../../../reference/android/support/v4/text/BidiFormatter.html#unicodeWrap(java.lang.CharSequence)" target="_top"><code>unicodeWrap</code></A>(<code>CharSequence</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)"></A>
+ <nobr><code>CharSequence</code> <A HREF="../../../../reference/android/support/v4/text/BidiFormatter.html#unicodeWrap(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)" target="_top"><code>unicodeWrap</code></A>(<code>CharSequence,</nobr> TextDirectionHeuristicCompat<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)"></A>
+ <nobr><code>CharSequence</code> <A HREF="../../../../reference/android/support/v4/text/BidiFormatter.html#unicodeWrap(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)" target="_top"><code>unicodeWrap</code></A>(<code>CharSequence,</nobr> TextDirectionHeuristicCompat<nobr>,</nobr> boolean<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, boolean)"></A>
+ <nobr><code>CharSequence</code> <A HREF="../../../../reference/android/support/v4/text/BidiFormatter.html#unicodeWrap(java.lang.CharSequence, boolean)" target="_top"><code>unicodeWrap</code></A>(<code>CharSequence,</nobr> boolean<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.view.ViewCompat.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.view.ViewCompat.html
new file mode 100644
index 0000000..9e99e73
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.view.ViewCompat.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.view.ViewCompat
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.view.<A HREF="../../../../reference/android/support/v4/view/ViewCompat.html" target="_top"><font size="+2"><code>ViewCompat</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.view.ViewCompat.getDisplay_added(android.view.View)"></A>
+ <nobr><code>Display</code> <A HREF="../../../../reference/android/support/v4/view/ViewCompat.html#getDisplay(android.view.View)" target="_top"><code>getDisplay</code></A>(<code>View</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.view.ViewCompat.setBackground_added(android.view.View, android.graphics.drawable.Drawable)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v4/view/ViewCompat.html#setBackground(android.view.View, android.graphics.drawable.Drawable)" target="_top"><code>setBackground</code></A>(<code>View,</nobr> Drawable<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.view.ViewPager.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.view.ViewPager.html
new file mode 100644
index 0000000..ca17f87
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.view.ViewPager.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.view.ViewPager
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.view.<A HREF="../../../../reference/android/support/v4/view/ViewPager.html" target="_top"><font size="+2"><code>ViewPager</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.view.ViewPager.setPageTransformer_added(boolean, android.support.v4.view.ViewPager.PageTransformer, int)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v4/view/ViewPager.html#setPageTransformer(boolean, android.support.v4.view.ViewPager.PageTransformer, int)" target="_top"><code>setPageTransformer</code></A>(<code>boolean,</nobr> PageTransformer<nobr>,</nobr> int<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.widget.SwipeRefreshLayout.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.widget.SwipeRefreshLayout.html
new file mode 100644
index 0000000..aca6ab9
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v4.widget.SwipeRefreshLayout.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.widget.SwipeRefreshLayout
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.widget.<A HREF="../../../../reference/android/support/v4/widget/SwipeRefreshLayout.html" target="_top"><font size="+2"><code>SwipeRefreshLayout</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.widget.SwipeRefreshLayout.getProgressViewEndOffset_added()"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v4/widget/SwipeRefreshLayout.html#getProgressViewEndOffset()" target="_top"><code>getProgressViewEndOffset</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.widget.SwipeRefreshLayout.getProgressViewStartOffset_added()"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v4/widget/SwipeRefreshLayout.html#getProgressViewStartOffset()" target="_top"><code>getProgressViewStartOffset</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v7.widget.RecyclerView.LayoutManager.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v7.widget.RecyclerView.LayoutManager.html
new file mode 100644
index 0000000..7a5df64
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v7.widget.RecyclerView.LayoutManager.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.widget.RecyclerView.LayoutManager
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v7.widget.<A HREF="../../../../reference/android/support/v7/widget/RecyclerView.LayoutManager.html" target="_top"><font size="+2"><code>RecyclerView.LayoutManager</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.widget.RecyclerView.LayoutManager.isItemPrefetchEnabled_added()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v7/widget/RecyclerView.LayoutManager.html#isItemPrefetchEnabled()" target="_top"><code>isItemPrefetchEnabled</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.widget.RecyclerView.LayoutManager.setItemPrefetchEnabled_added(boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v7/widget/RecyclerView.LayoutManager.html#setItemPrefetchEnabled(boolean)" target="_top"><code>setItemPrefetchEnabled</code></A>(<code>boolean</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v7.widget.RecyclerView.html b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v7.widget.RecyclerView.html
new file mode 100644
index 0000000..af4c24d
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/android.support.v7.widget.RecyclerView.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.widget.RecyclerView
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v7.widget.<A HREF="../../../../reference/android/support/v7/widget/RecyclerView.html" target="_top"><font size="+2"><code>RecyclerView</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.widget.RecyclerView.getDecoratedBoundsWithMargins_added(android.view.View, android.graphics.Rect)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v7/widget/RecyclerView.html#getDecoratedBoundsWithMargins(android.view.View, android.graphics.Rect)" target="_top"><code>getDecoratedBoundsWithMargins</code></A>(<code>View,</nobr> Rect<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/changes-summary.html b/docs/html/sdk/support_api_diff/25.0.0/changes/changes-summary.html
new file mode 100644
index 0000000..d8bd829
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/changes-summary.html
@@ -0,0 +1,220 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Support Library API Differences Report
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<body class="gc-documentation">
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+ <div id="docTitleContainer">
+ <h1>Support Library API Differences Report</h1>
+<p>This report details the changes in the core Android framework API between two <a
+href="https://developer.android.com/guide/appendix/api-levels.html" target="_top">API Level</a>
+specifications. It shows additions, modifications, and removals for packages, classes, methods, and fields.
+The report also includes general statistics that characterize the extent and type of the differences.</p>
+<p>This report is based a comparison of the Android API specifications
+whose API Level identifiers are given in the upper-right corner of this page. It compares a
+newer "to" API to an older "from" API, noting all changes relative to the
+older API. So, for example, API elements marked as removed are no longer present in the "to"
+API specification.</p>
+<p>To navigate the report, use the "Select a Diffs Index" and "Filter the Index"
+controls on the left. The report uses text formatting to indicate <em>interface names</em>,
+<a href= ><code>links to reference documentation</code></a>, and <a href= >links to change
+description</a>. The statistics are accessible from the "Statistics" link in the upper-right corner.</p>
+<p>For more information about the Android framework API and SDK,
+see the <a href="https://developer.android.com/index.html" target="_top">Android Developers site</a>.</p>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Packages" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Packages</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v13.view.inputmethod"></A>
+ <nobr><A HREF="../../../../reference/android/support/v13/view/inputmethod/package-summary.html" target="_top"><code>android.support.v13.view.inputmethod</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Packages" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Packages</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.customtabs"></A>
+ <nobr><A HREF="pkg_android.support.customtabs.html">android.support.customtabs</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.design.widget"></A>
+ <nobr><A HREF="pkg_android.support.design.widget.html">android.support.design.widget</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v13.app"></A>
+ <nobr><A HREF="pkg_android.support.v13.app.html">android.support.v13.app</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app"></A>
+ <nobr><A HREF="pkg_android.support.v4.app.html">android.support.v4.app</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.content"></A>
+ <nobr><A HREF="pkg_android.support.v4.content.html">android.support.v4.content</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.net"></A>
+ <nobr><A HREF="pkg_android.support.v4.net.html">android.support.v4.net</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.text"></A>
+ <nobr><A HREF="pkg_android.support.v4.text.html">android.support.v4.text</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.view"></A>
+ <nobr><A HREF="pkg_android.support.v4.view.html">android.support.v4.view</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.widget"></A>
+ <nobr><A HREF="pkg_android.support.v4.widget.html">android.support.v4.widget</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.app"></A>
+ <nobr><A HREF="pkg_android.support.v7.app.html">android.support.v7.app</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.widget"></A>
+ <nobr><A HREF="pkg_android.support.v7.widget.html">android.support.v7.widget</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<!-- End of API section -->
+<!-- Start of packages section -->
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_additions.html b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_additions.html
new file mode 100644
index 0000000..c3286a8
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_additions.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="classes_index_all.html" class="staysblack">All Classes</a>
+ <br>
+<A HREF="classes_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<b>Additions</b>
+ <br>
+<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#N"><font size="-2">N</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView" class="hiddenlink" target="rightframe"><b>BottomNavigationView</b></A><br>
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView.OnNavigationItemSelectedListener" class="hiddenlink" target="rightframe"><b><i>BottomNavigationView.OnNavigationItemSelectedListener</i></b></A><br>
+<A NAME="D"></A>
+<br><font size="+2">D</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#N"><font size="-2">N</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#DividerItemDecoration" class="hiddenlink" target="rightframe"><b>DividerItemDecoration</b></A><br>
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedCustomViewStyle</b></A><br>
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedMediaCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedMediaCustomViewStyle</b></A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_all.html b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_all.html
new file mode 100644
index 0000000..6a862ff
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_all.html
@@ -0,0 +1,189 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Classes</b>
+ <br>
+<A HREF="classes_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>ActivityCompat</i><br>
+ <A HREF="android.support.v13.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+ <A HREF="android.support.v4.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.text.BidiFormatter.html" class="hiddenlink" target="rightframe">BidiFormatter</A><br>
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView" class="hiddenlink" target="rightframe"><b>BottomNavigationView</b></A><br>
+<A HREF="pkg_android.support.design.widget.html#BottomNavigationView.OnNavigationItemSelectedListener" class="hiddenlink" target="rightframe"><b><i>BottomNavigationView.OnNavigationItemSelectedListener</i></b></A><br>
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.net.ConnectivityManagerCompat.html" class="hiddenlink" target="rightframe">ConnectivityManagerCompat</A><br>
+<A HREF="android.support.v4.content.ContextCompat.html" class="hiddenlink" target="rightframe">ContextCompat</A><br>
+<A HREF="android.support.customtabs.CustomTabsIntent.html" class="hiddenlink" target="rightframe">CustomTabsIntent</A><br>
+<A NAME="D"></A>
+<br><font size="+2">D</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#DividerItemDecoration" class="hiddenlink" target="rightframe"><b>DividerItemDecoration</b></A><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.design.widget.FloatingActionButton.html" class="hiddenlink" target="rightframe">FloatingActionButton</A><br>
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedCustomViewStyle</b></A><br>
+<A HREF="pkg_android.support.v7.app.html#NotificationCompat.DecoratedMediaCustomViewStyle" class="hiddenlink" target="rightframe"><b>NotificationCompat.DecoratedMediaCustomViewStyle</b></A><br>
+<A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html" class="hiddenlink" target="rightframe">NotificationCompat.WearableExtender</A><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v7.widget.RecyclerView.html" class="hiddenlink" target="rightframe">RecyclerView</A><br>
+<A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html" class="hiddenlink" target="rightframe">RecyclerView.LayoutManager</A><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#Space" class="hiddenlink" target="rightframe"><strike>Space</strike></A><br>
+<A HREF="android.support.v4.widget.SwipeRefreshLayout.html" class="hiddenlink" target="rightframe">SwipeRefreshLayout</A><br>
+<A NAME="V"></A>
+<br><font size="+2">V</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.view.ViewCompat.html" class="hiddenlink" target="rightframe">ViewCompat</A><br>
+<A HREF="android.support.v4.view.ViewPager.html" class="hiddenlink" target="rightframe">ViewPager</A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_changes.html b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_changes.html
new file mode 100644
index 0000000..9881ce6
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_changes.html
@@ -0,0 +1,163 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="classes_index_all.html" class="staysblack">All Classes</a>
+ <br>
+<A HREF="classes_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>ActivityCompat</i><br>
+ <A HREF="android.support.v13.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+ <A HREF="android.support.v4.app.ActivityCompat.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.text.BidiFormatter.html" class="hiddenlink" target="rightframe">BidiFormatter</A><br>
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.net.ConnectivityManagerCompat.html" class="hiddenlink" target="rightframe">ConnectivityManagerCompat</A><br>
+<A HREF="android.support.v4.content.ContextCompat.html" class="hiddenlink" target="rightframe">ContextCompat</A><br>
+<A HREF="android.support.customtabs.CustomTabsIntent.html" class="hiddenlink" target="rightframe">CustomTabsIntent</A><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.design.widget.FloatingActionButton.html" class="hiddenlink" target="rightframe">FloatingActionButton</A><br>
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html" class="hiddenlink" target="rightframe">NotificationCompat.WearableExtender</A><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v7.widget.RecyclerView.html" class="hiddenlink" target="rightframe">RecyclerView</A><br>
+<A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html" class="hiddenlink" target="rightframe">RecyclerView.LayoutManager</A><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#V"><font size="-2">V</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.widget.SwipeRefreshLayout.html" class="hiddenlink" target="rightframe">SwipeRefreshLayout</A><br>
+<A NAME="V"></A>
+<br><font size="+2">V</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.view.ViewCompat.html" class="hiddenlink" target="rightframe">ViewCompat</A><br>
+<A HREF="android.support.v4.view.ViewPager.html" class="hiddenlink" target="rightframe">ViewPager</A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_removals.html b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_removals.html
new file mode 100644
index 0000000..65dc88b
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/classes_index_removals.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="classes_index_all.html" class="staysblack">All Classes</a>
+ <br>
+<b>Removals</b>
+ <br>
+<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#Space" class="hiddenlink" target="rightframe"><strike>Space</strike></A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_additions.html b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_additions.html
new file mode 100644
index 0000000..b119899
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_additions.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="constructors_index_all.html" class="staysblack">All Constructors</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<b>Additions</b>
+ <br>
+<A HREF="constructors_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v13.app.ActivityCompat.html#android.support.v13.app.ActivityCompat.ctor_added()" class="hiddenlink" target="rightframe"><b>ActivityCompat</b>
+()</A></nobr> constructor<br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_all.html b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_all.html
new file mode 100644
index 0000000..d19abe3
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_all.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Constructors</b>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="constructors_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="constructors_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#C"><font size="-2">C</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>ActivityCompat</i><br>
+ <nobr><A HREF="android.support.v13.app.ActivityCompat.html#android.support.v13.app.ActivityCompat.ctor_added()" class="hiddenlink" target="rightframe"><b>ActivityCompat</b>
+()</A></nobr> constructor<br>
+ <nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.ctor_changed()" class="hiddenlink" target="rightframe">ActivityCompat
+()</A></nobr> constructor<br>
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.ctor_changed()" class="hiddenlink" target="rightframe">ContextCompat
+()</A></nobr> constructor<br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_changes.html b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_changes.html
new file mode 100644
index 0000000..9c48ca4
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_changes.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="constructors_index_all.html" class="staysblack">All Constructors</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="constructors_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#C"><font size="-2">C</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.ctor_changed()" class="hiddenlink" target="rightframe">ActivityCompat
+()</A></nobr> constructor<br>
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.ctor_changed()" class="hiddenlink" target="rightframe">ContextCompat
+()</A></nobr> constructor<br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_removals.html b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_removals.html
new file mode 100644
index 0000000..55afb30
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/constructors_index_removals.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="constructors_index_all.html" class="staysblack">All Constructors</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="constructors_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="constructors_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_additions.html b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_additions.html
new file mode 100644
index 0000000..19d2189
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_additions.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="fields_index_all.html" class="staysblack">All Fields</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<b>Additions</b>
+ <br>
+<font color="#999999">Changes</font>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_DISABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_DISABLED</A>
+</nobr><br>
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_ENABLED</A>
+</nobr><br>
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_WHITELISTED</A>
+</nobr><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_all.html b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_all.html
new file mode 100644
index 0000000..2f658ab
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_all.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Fields</b>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="fields_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<font color="#999999">Changes</font>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_DISABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_DISABLED</A>
+</nobr><br>
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_ENABLED</A>
+</nobr><br>
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED" class="hiddenlink" target="rightframe">RESTRICT_BACKGROUND_STATUS_WHITELISTED</A>
+</nobr><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_changes.html b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_changes.html
new file mode 100644
index 0000000..f6d9158
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_changes.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="fields_index_all.html" class="staysblack">All Fields</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="fields_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<font color="#999999">Changes</font>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_removals.html b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_removals.html
new file mode 100644
index 0000000..b16c79f
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/fields_index_removals.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="fields_index_all.html" class="staysblack">All Fields</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="fields_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<font color="#999999">Changes</font>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_help.html b/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_help.html
new file mode 100644
index 0000000..0f826e3
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_help.html
@@ -0,0 +1,134 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+JDiff Help
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<TABLE summary="Navigation bar" BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+ <TABLE summary="Navigation bar" BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../../reference/index.html" target="_top"><FONT CLASS="NavBarFont1"><B><code>25.0.0</code></B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="changes-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT> </TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="jdiff_statistics.html"><FONT CLASS="NavBarFont1"><B>Statistics</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT> </TD>
+ </TR>
+ </TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM><b>Generated by<br><a href="http://www.jdiff.org" class="staysblack" target="_top">JDiff</a></b></EM></TD>
+</TR>
+<TR>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell2"><FONT SIZE="-2"></FONT>
+</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../changes.html" TARGET="_top"><B>FRAMES</B></A>
+ <A HREF="jdiff_help.html" TARGET="_top"><B>NO FRAMES</B></A></FONT></TD>
+</TR>
+</TABLE>
+<HR>
+<!-- End of nav bar -->
+<center>
+<H1>JDiff Documentation</H1>
+</center>
+<BLOCKQUOTE>
+JDiff is a <a href="http://java.sun.com/j2se/javadoc/" target="_top">Javadoc</a> doclet which generates a report of the API differences between two versions of a product. It does not report changes in Javadoc comments, or changes in what a class or method does.
+This help page describes the different parts of the output from JDiff.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+ See the reference page in the <a href="http://www.jdiff.org">source for JDiff</a> for information about how to generate a report like this one.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+The indexes shown in the top-left frame help show each type of change in more detail. The index "All Differences" contains all the differences between the APIs, in alphabetical order.
+These indexes all use the same format:
+<ul>
+<li>Removed packages, classes, constructors, methods and fields are <strike>struck through</strike>.</li>
+<li>Added packages, classes, constructors, methods and fields appear in <b>bold</b>.</li>
+<li>Changed packages, classes, constructors, methods and fields appear in normal text.</li>
+</ul>
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+You can always tell when you are reading a JDiff page, rather than a Javadoc page, by the color of the index bar and the color of the background.
+Links which take you to a Javadoc page are always in a <code>typewriter</code> font.
+Just like Javadoc, all interface names are in <i>italic</i>, and class names are not italicized. Where there are multiple entries in an index with the same name, the heading for them is also in italics, but is not a link.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3><b><code>Javadoc</code></b></H3>
+This is a link to the <a href="../../../../reference/index.html" target="_top">top-level</a> Javadoc page for the new version of the product.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Overview</H3>
+The <a href="changes-summary.html">overview</a> is the top-level summary of what was removed, added and changed between versions.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Package</H3>
+This is a link to the package containing the current changed class or interface.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Class</H3>
+This is highlighted when you are looking at the changed class or interface.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Text Changes</H3>
+This is a link to the top-level index of all documentation changes for the current package or class.
+If it is not present, then there are no documentation changes for the current package or class.
+This link can be removed entirely by not using the <code>-docchanges</code> option.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Statistics</H3>
+This is a link to a page which shows statistics about the changes between the two APIs.
+This link can be removed entirely by not using the <code>-stats</code> option.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Help</H3>
+A link to this Help page for JDiff.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Prev/Next</H3>
+These links take you to the previous and next changed package or class.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Frames/No Frames</H3>
+These links show and hide the HTML frames. All pages are available with or without frames.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H2>Complex Changes</H2>
+There are some complex changes which can occur between versions, for example, when two or more methods with the same name change simultaneously, or when a method or field is moved into or from a superclass.
+In these cases, the change will be seen as a removal and an addition, rather than as a change. Unexpected removals or additions are often part of one of these type of changes.
+</BLOCKQUOTE>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_statistics.html b/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_statistics.html
new file mode 100644
index 0000000..de60506
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_statistics.html
@@ -0,0 +1,302 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+API Change Statistics
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<body class="gc-documentation">
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;xborder-bottom:none;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="../changes.html" target="_top">Top of Report</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<h1>API Change Statistics</h1>
+<p>The overall difference between API Levels 24.2.0 and 25.0.0 is approximately <span style="color:222;font-weight:bold;">1.82%</span>.
+</p>
+<br>
+<a name="numbers"></a>
+<h2>Total of Differences, by Number and Type</h2>
+<p>
+The table below lists the numbers of program elements (packages, classes, constructors, methods, and fields) that were added, changed, or removed. The table includes only the highest-level program elements — that is, if a class with two methods was added, the number of methods added does not include those two methods, but the number of classes added does include that class.
+</p>
+<TABLE summary="Number of differences" WIDTH="100%">
+<TR>
+ <th>Type</th>
+ <TH ALIGN="center"><b>Additions</b></TH>
+ <TH ALIGN="center"><b>Changes</b></TH>
+ <TH ALIGN="center">Removals</TH>
+ <TH ALIGN="center"><b>Total</b></TH>
+</TR>
+<TR>
+ <TD>Packages</TD>
+ <TD ALIGN="right">1</TD>
+ <TD ALIGN="right">11</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">12</TD>
+</TR>
+<TR>
+ <TD>Classes and <i>Interfaces</i></TD>
+ <TD ALIGN="right">5</TD>
+ <TD ALIGN="right">13</TD>
+ <TD ALIGN="right">1</TD>
+ <TD ALIGN="right">19</TD>
+</TR>
+<TR>
+ <TD>Constructors</TD>
+ <TD ALIGN="right">1</TD>
+ <TD ALIGN="right">2</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">3</TD>
+</TR>
+<TR>
+ <TD>Methods</TD>
+ <TD ALIGN="right">18</TD>
+ <TD ALIGN="right">3</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">21</TD>
+</TR>
+<TR>
+ <TD>Fields</TD>
+ <TD ALIGN="right">3</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">3</TD>
+</TR>
+<TR>
+ <TD style="background-color:#FAFAFA"><b>Total</b></TD>
+ <TD style="background-color:#FAFAFA" ALIGN="right"><strong>28</strong></TD>
+ <TD style="background-color:#FAFAFA" ALIGN="right"><strong>29</strong></TD>
+ <TD style="background-color:#FAFAFA" ALIGN="right"><strong>1</strong></TD>
+ <TD style="background-color:#FAFAFA" ALIGN="right"><strong>58</strong></TD>
+</TR>
+</TABLE>
+<br>
+<a name="packages"></a>
+<h2>Changed Packages, Sorted by Percentage Difference</h2>
+<TABLE summary="Packages sorted by percentage difference" WIDTH="100%">
+<TR>
+ <TH WIDTH="10%">Percentage Difference*</TH>
+ <TH>Package</TH>
+</TR>
+<TR>
+ <TD ALIGN="center">25</TD>
+ <TD><A HREF="pkg_android.support.v4.net.html">android.support.v4.net</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">5</TD>
+ <TD><A HREF="pkg_android.support.v13.app.html">android.support.v13.app</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">3</TD>
+ <TD><A HREF="pkg_android.support.v7.app.html">android.support.v7.app</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">3</TD>
+ <TD><A HREF="pkg_android.support.v4.text.html">android.support.v4.text</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">2</TD>
+ <TD><A HREF="pkg_android.support.design.widget.html">android.support.design.widget</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">1</TD>
+ <TD><A HREF="pkg_android.support.v7.widget.html">android.support.v7.widget</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.v4.content.html">android.support.v4.content</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.v4.app.html">android.support.v4.app</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.customtabs.html">android.support.customtabs</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.v4.widget.html">android.support.v4.widget</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.v4.view.html">android.support.v4.view</A></TD>
+</TR>
+</TABLE>
+<p style="font-size:10px">* See <a href="#calculation">Calculation of Change Percentages</a>, below.</p>
+<br>
+<a name="classes"></a>
+<h2>Changed Classes and <i>Interfaces</i>, Sorted by Percentage Difference</h2>
+<TABLE summary="Classes sorted by percentage difference" WIDTH="100%">
+<TR WIDTH="20%">
+ <TH WIDTH="10%">Percentage<br>Difference*</TH>
+ <TH><b>Class or <i>Interface</i></b></TH>
+</TR>
+<TR>
+ <TD ALIGN="center">50</TD>
+ <TD><A HREF="android.support.v4.net.ConnectivityManagerCompat.html">
+android.support.v4.net.ConnectivityManagerCompat</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">33</TD>
+ <TD><A HREF="android.support.v13.app.ActivityCompat.html">
+android.support.v13.app.ActivityCompat</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">20</TD>
+ <TD><A HREF="android.support.v4.text.BidiFormatter.html">
+android.support.v4.text.BidiFormatter</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">11</TD>
+ <TD><A HREF="android.support.v4.app.ActivityCompat.html">
+android.support.v4.app.ActivityCompat</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">6</TD>
+ <TD><A HREF="android.support.v4.content.ContextCompat.html">
+android.support.v4.content.ContextCompat</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">4</TD>
+ <TD><A HREF="android.support.v4.widget.SwipeRefreshLayout.html">
+android.support.v4.widget.SwipeRefreshLayout</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">2</TD>
+ <TD><A HREF="android.support.design.widget.FloatingActionButton.html">
+android.support.design.widget.FloatingActionButton</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">1</TD>
+ <TD><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html">
+android.support.v4.app.NotificationCompat.WearableExtender</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">1</TD>
+ <TD><A HREF="android.support.customtabs.CustomTabsIntent.html">
+android.support.customtabs.CustomTabsIntent</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">1</TD>
+ <TD><A HREF="android.support.v4.view.ViewPager.html">
+android.support.v4.view.ViewPager</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html">
+android.support.v7.widget.RecyclerView.LayoutManager</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="android.support.v4.view.ViewCompat.html">
+android.support.v4.view.ViewCompat</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="android.support.v7.widget.RecyclerView.html">
+android.support.v7.widget.RecyclerView</A></TD>
+</TR>
+</TABLE>
+<p style="font-size:10px">* See <a href="#calculation">Calculation of Change Percentages</a>, below.</p>
+<br>
+<h2 id="calculation">Calculation of Change Percentages</h2>
+<p>
+The percent change statistic reported for all elements in the "to" API Level specification is defined recursively as follows:</p>
+<pre>
+Percentage difference = 100 * (added + removed + 2*changed)
+ -----------------------------------
+ sum of public elements in BOTH APIs
+</pre>
+<p>where <code>added</code> is the number of packages added, <code>removed</code> is the number of packages removed, and <code>changed</code> is the number of packages changed.
+This definition is applied recursively for the classes and their program elements, so the value for a changed package will be less than 1, unless every class in that package has changed.
+The definition ensures that if all packages are removed and all new packages are
+added, the change will be 100%.</p>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY></HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_topleftframe.html b/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_topleftframe.html
new file mode 100644
index 0000000..4368791
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/jdiff_topleftframe.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Android API Version Differences
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<table class="jdiffIndex" summary="Links to diff index files" BORDER="0" WIDTH="100%" cellspacing="0" cellpadding="0" style="margin:0">
+<TR>
+ <th class="indexHeader" nowrap>
+ Select a Diffs Index:</th>
+</TR>
+<TR>
+ <TD><FONT CLASS="indexText" size="-2"><A HREF="alldiffs_index_all.html" TARGET="bottomleftframe">All Differences</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="packages_index_all.html" TARGET="bottomleftframe">By Package</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="classes_index_all.html" TARGET="bottomleftframe">By Class</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="constructors_index_all.html" TARGET="bottomleftframe">By Constructor</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="methods_index_all.html" TARGET="bottomleftframe">By Method</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="fields_index_all.html" TARGET="bottomleftframe">By Field</A></FONT><br></TD>
+</TR>
+</TABLE>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_additions.html b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_additions.html
new file mode 100644
index 0000000..0ef8e0d
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_additions.html
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="methods_index_all.html" class="staysblack">All Methods</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<b>Additions</b>
+ <br>
+<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.getBridgeTag_added()" class="hiddenlink" target="rightframe"><b>getBridgeTag</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.RecyclerView.html#android.support.v7.widget.RecyclerView.getDecoratedBoundsWithMargins_added(android.view.View, android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getDecoratedBoundsWithMargins</b>
+(<code>View, Rect</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.getDisplay_added(android.view.View)" class="hiddenlink" target="rightframe"><b>getDisplay</b>
+(<code>View</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewEndOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewEndOffset</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewStartOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewStartOffset</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.getRestrictBackgroundStatus_added(android.net.ConnectivityManager)" class="hiddenlink" target="rightframe"><b>getRestrictBackgroundStatus</b>
+(<code>ConnectivityManager</code>)</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.FloatingActionButton.html#android.support.design.widget.FloatingActionButton.getRippleColor_added()" class="hiddenlink" target="rightframe"><b>getRippleColor</b>
+()</A></nobr><br>
+<A NAME="I"></A>
+<br><font size="+2">I</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.isItemPrefetchEnabled_added()" class="hiddenlink" target="rightframe"><b>isItemPrefetchEnabled</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.isRtl_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>isRtl</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.setBackground_added(android.view.View, android.graphics.drawable.Drawable)" class="hiddenlink" target="rightframe"><b>setBackground</b>
+(<code>View, Drawable</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.setBridgeTag_added(java.lang.String)" class="hiddenlink" target="rightframe"><b>setBridgeTag</b>
+(<code>String</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.setItemPrefetchEnabled_added(boolean)" class="hiddenlink" target="rightframe"><b>setItemPrefetchEnabled</b>
+(<code>boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.view.ViewPager.html#android.support.v4.view.ViewPager.setPageTransformer_added(boolean, android.support.v4.view.ViewPager.PageTransformer, int)" class="hiddenlink" target="rightframe"><b>setPageTransformer</b>
+(<code>boolean, PageTransformer, int</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.startActivity_added(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe"><b>startActivity</b>
+(<code>Context, Intent, Bundle</code>)</A></nobr><br>
+<A NAME="U"></A>
+<br><font size="+2">U</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>unicodeWrap</i><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_all.html b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_all.html
new file mode 100644
index 0000000..08df085
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_all.html
@@ -0,0 +1,151 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Methods</b>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.getBridgeTag_added()" class="hiddenlink" target="rightframe"><b>getBridgeTag</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.RecyclerView.html#android.support.v7.widget.RecyclerView.getDecoratedBoundsWithMargins_added(android.view.View, android.graphics.Rect)" class="hiddenlink" target="rightframe"><b>getDecoratedBoundsWithMargins</b>
+(<code>View, Rect</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.getDisplay_added(android.view.View)" class="hiddenlink" target="rightframe"><b>getDisplay</b>
+(<code>View</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewEndOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewEndOffset</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html#android.support.v4.widget.SwipeRefreshLayout.getProgressViewStartOffset_added()" class="hiddenlink" target="rightframe"><b>getProgressViewStartOffset</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.getReferrer_changed(android.app.Activity)" class="hiddenlink" target="rightframe">getReferrer
+(<code>Activity</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html#android.support.v4.net.ConnectivityManagerCompat.getRestrictBackgroundStatus_added(android.net.ConnectivityManager)" class="hiddenlink" target="rightframe"><b>getRestrictBackgroundStatus</b>
+(<code>ConnectivityManager</code>)</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.FloatingActionButton.html#android.support.design.widget.FloatingActionButton.getRippleColor_added()" class="hiddenlink" target="rightframe"><b>getRippleColor</b>
+()</A></nobr><br>
+<A NAME="I"></A>
+<br><font size="+2">I</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.isItemPrefetchEnabled_added()" class="hiddenlink" target="rightframe"><b>isItemPrefetchEnabled</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.isRtl_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>isRtl</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<A NAME="L"></A>
+<br><font size="+2">L</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.customtabs.CustomTabsIntent.html#android.support.customtabs.CustomTabsIntent.launchUrl_changed(android.content.Context, android.net.Uri)" class="hiddenlink" target="rightframe">launchUrl
+(<code>Context, Uri</code>)</A></nobr><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.view.ViewCompat.html#android.support.v4.view.ViewCompat.setBackground_added(android.view.View, android.graphics.drawable.Drawable)" class="hiddenlink" target="rightframe"><b>setBackground</b>
+(<code>View, Drawable</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html#android.support.v4.app.NotificationCompat.WearableExtender.setBridgeTag_added(java.lang.String)" class="hiddenlink" target="rightframe"><b>setBridgeTag</b>
+(<code>String</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html#android.support.v7.widget.RecyclerView.LayoutManager.setItemPrefetchEnabled_added(boolean)" class="hiddenlink" target="rightframe"><b>setItemPrefetchEnabled</b>
+(<code>boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.view.ViewPager.html#android.support.v4.view.ViewPager.setPageTransformer_added(boolean, android.support.v4.view.ViewPager.PageTransformer, int)" class="hiddenlink" target="rightframe"><b>setPageTransformer</b>
+(<code>boolean, PageTransformer, int</code>)</A></nobr><br>
+<i>startActivity</i><br>
+ <nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.startActivity_changed(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe">type
+(<code>Context, Intent, Bundle</code>) in android.support.v4.app.ActivityCompat
+</A></nobr><br>
+ <nobr><A HREF="android.support.v4.content.ContextCompat.html#android.support.v4.content.ContextCompat.startActivity_added(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe">type <b>
+(<code>Context, Intent, Bundle</code>)</b> in android.support.v4.content.ContextCompat
+</A></nobr><br>
+<A NAME="U"></A>
+<br><font size="+2">U</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>unicodeWrap</i><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, TextDirectionHeuristicCompat, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html#android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>CharSequence, boolean</code>)</b> in android.support.v4.text.BidiFormatter
+</A></nobr><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_changes.html b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_changes.html
new file mode 100644
index 0000000..b2aae91
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_changes.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="methods_index_all.html" class="staysblack">All Methods</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.getReferrer_changed(android.app.Activity)" class="hiddenlink" target="rightframe">getReferrer
+(<code>Activity</code>)</A></nobr><br>
+<A NAME="L"></A>
+<br><font size="+2">L</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.customtabs.CustomTabsIntent.html#android.support.customtabs.CustomTabsIntent.launchUrl_changed(android.content.Context, android.net.Uri)" class="hiddenlink" target="rightframe">launchUrl
+(<code>Context, Uri</code>)</A></nobr><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.ActivityCompat.html#android.support.v4.app.ActivityCompat.startActivity_changed(android.content.Context, android.content.Intent, android.os.Bundle)" class="hiddenlink" target="rightframe">startActivity
+(<code>Context, Intent, Bundle</code>)</A></nobr><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_removals.html b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_removals.html
new file mode 100644
index 0000000..d88010f
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/methods_index_removals.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="methods_index_all.html" class="staysblack">All Methods</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_additions.html b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_additions.html
new file mode 100644
index 0000000..bcbbaf0
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_additions.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="packages_index_all.html" class="staysblack">All Packages</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<b>Additions</b>
+ <br>
+<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<A NAME="A"></A>
+<A HREF="changes-summary.html#android.support.v13.view.inputmethod" class="hiddenlink" target="rightframe"><b>android.support.v13.view.inputmethod</b></A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_all.html b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_all.html
new file mode 100644
index 0000000..bfadc87
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_all.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Packages</b>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="packages_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<A NAME="A"></A>
+<A HREF="pkg_android.support.customtabs.html" class="hiddenlink" target="rightframe">android.support.customtabs</A><br>
+<A HREF="pkg_android.support.design.widget.html" class="hiddenlink" target="rightframe">android.support.design.widget</A><br>
+<A HREF="pkg_android.support.v13.app.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+<A HREF="changes-summary.html#android.support.v13.view.inputmethod" class="hiddenlink" target="rightframe"><b>android.support.v13.view.inputmethod</b></A><br>
+<A HREF="pkg_android.support.v4.app.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<A HREF="pkg_android.support.v4.content.html" class="hiddenlink" target="rightframe">android.support.v4.content</A><br>
+<A HREF="pkg_android.support.v4.net.html" class="hiddenlink" target="rightframe">android.support.v4.net</A><br>
+<A HREF="pkg_android.support.v4.text.html" class="hiddenlink" target="rightframe">android.support.v4.text</A><br>
+<A HREF="pkg_android.support.v4.view.html" class="hiddenlink" target="rightframe">android.support.v4.view</A><br>
+<A HREF="pkg_android.support.v4.widget.html" class="hiddenlink" target="rightframe">android.support.v4.widget</A><br>
+<A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
+<A HREF="pkg_android.support.v7.widget.html" class="hiddenlink" target="rightframe">android.support.v7.widget</A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_changes.html b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_changes.html
new file mode 100644
index 0000000..df27300
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_changes.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="packages_index_all.html" class="staysblack">All Packages</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="packages_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<A NAME="A"></A>
+<A HREF="pkg_android.support.customtabs.html" class="hiddenlink" target="rightframe">android.support.customtabs</A><br>
+<A HREF="pkg_android.support.design.widget.html" class="hiddenlink" target="rightframe">android.support.design.widget</A><br>
+<A HREF="pkg_android.support.v13.app.html" class="hiddenlink" target="rightframe">android.support.v13.app</A><br>
+<A HREF="pkg_android.support.v4.app.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<A HREF="pkg_android.support.v4.content.html" class="hiddenlink" target="rightframe">android.support.v4.content</A><br>
+<A HREF="pkg_android.support.v4.net.html" class="hiddenlink" target="rightframe">android.support.v4.net</A><br>
+<A HREF="pkg_android.support.v4.text.html" class="hiddenlink" target="rightframe">android.support.v4.text</A><br>
+<A HREF="pkg_android.support.v4.view.html" class="hiddenlink" target="rightframe">android.support.v4.view</A><br>
+<A HREF="pkg_android.support.v4.widget.html" class="hiddenlink" target="rightframe">android.support.v4.widget</A><br>
+<A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
+<A HREF="pkg_android.support.v7.widget.html" class="hiddenlink" target="rightframe">android.support.v7.widget</A><br>
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_removals.html b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_removals.html
new file mode 100644
index 0000000..c91155c
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/packages_index_removals.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="packages_index_all.html" class="staysblack">All Packages</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="packages_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.customtabs.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.customtabs.html
new file mode 100644
index 0000000..7e1276d
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.customtabs.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.customtabs
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/customtabs/package-summary.html" target="_top"><font size="+1"><code>android.support.customtabs</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="CustomTabsIntent"></A>
+ <nobr><A HREF="android.support.customtabs.CustomTabsIntent.html">CustomTabsIntent</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.design.widget.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.design.widget.html
new file mode 100644
index 0000000..e7326e7
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.design.widget.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.design.widget
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/design/widget/package-summary.html" target="_top"><font size="+1"><code>android.support.design.widget</code></font></A>
+</H2>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes and Interfaces" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Classes and Interfaces</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BottomNavigationView"></A>
+ <nobr><A HREF="../../../../reference/android/support/design/widget/BottomNavigationView.html" target="_top"><code>BottomNavigationView</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BottomNavigationView.OnNavigationItemSelectedListener"></A>
+ <nobr><A HREF="../../../../reference/android/support/design/widget/BottomNavigationView.OnNavigationItemSelectedListener.html" target="_top"><code><I>BottomNavigationView.<br>OnNavigationItemSelectedListener</I></code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="FloatingActionButton"></A>
+ <nobr><A HREF="android.support.design.widget.FloatingActionButton.html">FloatingActionButton</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v13.app.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v13.app.html
new file mode 100644
index 0000000..5f9d84e
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v13.app.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v13.app
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v13/app/package-summary.html" target="_top"><font size="+1"><code>android.support.v13.app</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="ActivityCompat"></A>
+ <nobr><A HREF="android.support.v13.app.ActivityCompat.html">ActivityCompat</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.app.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.app.html
new file mode 100644
index 0000000..4ebfbdd
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.app.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.app
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/app/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.app</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="ActivityCompat"></A>
+ <nobr><A HREF="android.support.v4.app.ActivityCompat.html">ActivityCompat</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="NotificationCompat.WearableExtender"></A>
+ <nobr><A HREF="android.support.v4.app.NotificationCompat.WearableExtender.html">NotificationCompat.WearableExtender</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.content.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.content.html
new file mode 100644
index 0000000..a5e7ef8
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.content.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.content
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/content/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.content</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="ContextCompat"></A>
+ <nobr><A HREF="android.support.v4.content.ContextCompat.html">ContextCompat</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.net.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.net.html
new file mode 100644
index 0000000..978acb2
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.net.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.net
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/net/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.net</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="ConnectivityManagerCompat"></A>
+ <nobr><A HREF="android.support.v4.net.ConnectivityManagerCompat.html">ConnectivityManagerCompat</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.text.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.text.html
new file mode 100644
index 0000000..821ac23
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.text.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.text
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/text/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.text</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BidiFormatter"></A>
+ <nobr><A HREF="android.support.v4.text.BidiFormatter.html">BidiFormatter</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.view.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.view.html
new file mode 100644
index 0000000..062bb90
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.view.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.view
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/view/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.view</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="ViewCompat"></A>
+ <nobr><A HREF="android.support.v4.view.ViewCompat.html">ViewCompat</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="ViewPager"></A>
+ <nobr><A HREF="android.support.v4.view.ViewPager.html">ViewPager</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.widget.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.widget.html
new file mode 100644
index 0000000..7c6be7a
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v4.widget.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.widget
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/widget/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.widget</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="SwipeRefreshLayout"></A>
+ <nobr><A HREF="android.support.v4.widget.SwipeRefreshLayout.html">SwipeRefreshLayout</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v7.app.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v7.app.html
new file mode 100644
index 0000000..eaf702c
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v7.app.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.app
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v7/app/package-summary.html" target="_top"><font size="+1"><code>android.support.v7.app</code></font></A>
+</H2>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="NotificationCompat.DecoratedCustomViewStyle"></A>
+ <nobr><A HREF="../../../../reference/android/support/v7/app/NotificationCompat.DecoratedCustomViewStyle.html" target="_top"><code>NotificationCompat.DecoratedCustomViewStyle</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="NotificationCompat.DecoratedMediaCustomViewStyle"></A>
+ <nobr><A HREF="../../../../reference/android/support/v7/app/NotificationCompat.DecoratedMediaCustomViewStyle.html" target="_top"><code>NotificationCompat.DecoratedMediaCustomViewStyle</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v7.widget.html b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v7.widget.html
new file mode 100644
index 0000000..d6c4f12
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/changes/pkg_android.support.v7.widget.html
@@ -0,0 +1,156 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.widget
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="https://developer.android.com" target="_top">Android Developers</a> | <a href="https://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">24.2.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.11.11 17:08</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v7/widget/package-summary.html" target="_top"><font size="+1"><code>android.support.v7.widget</code></font></A>
+</H2>
+<p>
+<a NAME="Removed"></a>
+<TABLE summary="Removed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Removed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="Space"></A>
+ Space
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="DividerItemDecoration"></A>
+ <nobr><A HREF="../../../../reference/android/support/v7/widget/DividerItemDecoration.html" target="_top"><code>DividerItemDecoration</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="RecyclerView"></A>
+ <nobr><A HREF="android.support.v7.widget.RecyclerView.html">RecyclerView</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="RecyclerView.LayoutManager"></A>
+ <nobr><A HREF="android.support.v7.widget.RecyclerView.LayoutManager.html">RecyclerView.LayoutManager</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="https://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="https://developer.android.com/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="https://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="https://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="https://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="https://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.0.0/missingSinces.txt b/docs/html/sdk/support_api_diff/25.0.0/missingSinces.txt
new file mode 100644
index 0000000..5d93bd9
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/missingSinces.txt
@@ -0,0 +1,27 @@
+NO DOC BLOCK: android.support.design.widget.BottomNavigationView Class
+NO DOC BLOCK: android.support.design.widget.BottomNavigationView.OnNavigationItemSelectedListener Interface
+NO DOC BLOCK: android.support.v7.widget.DividerItemDecoration Class
+NO DOC BLOCK: android.support.v7.app.NotificationCompat.DecoratedCustomViewStyle Class
+NO DOC BLOCK: android.support.v7.app.NotificationCompat.DecoratedMediaCustomViewStyle Class
+NO DOC BLOCK: android.support.v13.app.ActivityCompat Constructor ()
+NO DOC BLOCK: android.support.v4.app.NotificationCompat.WearableExtender Method getBridgeTag()
+NO DOC BLOCK: android.support.v7.widget.RecyclerView Method getDecoratedBoundsWithMargins(android.view.View, android.graphics.Rect)
+NO DOC BLOCK: android.support.v4.view.ViewCompat Method getDisplay(android.view.View)
+NO DOC BLOCK: android.support.v4.widget.SwipeRefreshLayout Method getProgressViewEndOffset()
+NO DOC BLOCK: android.support.v4.widget.SwipeRefreshLayout Method getProgressViewStartOffset()
+NO DOC BLOCK: android.support.v4.net.ConnectivityManagerCompat Method getRestrictBackgroundStatus(android.net.ConnectivityManager)
+NO DOC BLOCK: android.support.design.widget.FloatingActionButton Method getRippleColor()
+NO DOC BLOCK: android.support.v7.widget.RecyclerView.LayoutManager Method isItemPrefetchEnabled()
+NO DOC BLOCK: android.support.v4.text.BidiFormatter Method isRtl(java.lang.CharSequence)
+NO DOC BLOCK: android.support.v4.view.ViewCompat Method setBackground(android.view.View, android.graphics.drawable.Drawable)
+NO DOC BLOCK: android.support.v4.app.NotificationCompat.WearableExtender Method setBridgeTag(java.lang.String)
+NO DOC BLOCK: android.support.v7.widget.RecyclerView.LayoutManager Method setItemPrefetchEnabled(boolean)
+NO DOC BLOCK: android.support.v4.view.ViewPager Method setPageTransformer(boolean, android.support.v4.view.ViewPager.PageTransformer, int)
+NO DOC BLOCK: android.support.v4.content.ContextCompat Method startActivity(android.content.Context, android.content.Intent, android.os.Bundle)
+NO DOC BLOCK: android.support.v4.text.BidiFormatter Method unicodeWrap(java.lang.CharSequence)
+NO DOC BLOCK: android.support.v4.text.BidiFormatter Method unicodeWrap(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)
+NO DOC BLOCK: android.support.v4.text.BidiFormatter Method unicodeWrap(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)
+NO DOC BLOCK: android.support.v4.text.BidiFormatter Method unicodeWrap(java.lang.CharSequence, boolean)
+NO DOC BLOCK: android.support.v4.net.ConnectivityManagerCompat Field RESTRICT_BACKGROUND_STATUS_DISABLED
+NO DOC BLOCK: android.support.v4.net.ConnectivityManagerCompat Field RESTRICT_BACKGROUND_STATUS_ENABLED
+NO DOC BLOCK: android.support.v4.net.ConnectivityManagerCompat Field RESTRICT_BACKGROUND_STATUS_WHITELISTED
diff --git a/docs/html/sdk/support_api_diff/25.0.0/stylesheet-jdiff.css b/docs/html/sdk/support_api_diff/25.0.0/stylesheet-jdiff.css
new file mode 100644
index 0000000..edafaa3
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/stylesheet-jdiff.css
@@ -0,0 +1,44 @@
+
+/* (http://www.jdiff.org) */
+
+div.and-diff-id {border: 1px solid #eee;position:relative;float:right;clear:both;padding:0px;}
+table.diffspectable {border:1px;padding:0px;margin:0px;}
+.diffspechead {background-color:#eee;}
+.diffspectable tr {border:0px;padding:0px;}
+.diffspectable td {background-color:eee;border:0px;font-size:90%;font-weight:normal;padding:0px;padding-left:1px;padding-right:1px;text-align:center;color:777;}
+td.diffvalueold {color:orange;background-color:white;border:0px;font-size:80%;font-style:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;}
+td.diffvaluenew {color:green;background-color:white;border:0px;font-size:80%;font-weight:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;}
+td.diffvalue {color:444;background-color:white;border:0px;font-size:80%;font-weight:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;}
+td.diffspec {background-color:white;border:0px;font-size:80%;font-weight:normal;padding:1px;color:444;text-align:right;padding-right:.5em;line-height:.95em;}
+tt {font-size:11pt;font-family:monospace;}
+.indexHeader {
+ font-size:96%;
+ line-height:.8em;}
+.jdiffIndex td {
+ font-size:96%;
+ xline-height:.8em;
+ padding:2px;
+ padding-left:1em;}
+.indexText {
+ font-size:100%;
+ padding-left:1em;}
+#indexTableCaption {
+ font-size:96%;
+ margin-top:.25em;
+ margin-bottom:0;
+ }
+.hiddenlink {
+ font-size:96%;
+ line-height:.8em;
+ text-decoration:none;}
+a {
+ text-decoration:none;}
+a:hover {
+ text-decoration:underline;}
+.indexBox {
+ border: 1px solid red;
+ margin:1em 0 0 0;}
+.letterIndexHead {
+ font-size: 1.5em;font-weight:9;
+ margin:0 0 0em 0;
+ border: 1px solid red;}
diff --git a/docs/html/sdk/support_api_diff/25.0.0/user_comments_for_24.2.0_to_25.0.0.xml b/docs/html/sdk/support_api_diff/25.0.0/user_comments_for_24.2.0_to_25.0.0.xml
new file mode 100644
index 0000000..9091eb6
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.0.0/user_comments_for_24.2.0_to_25.0.0.xml
@@ -0,0 +1,379 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
+<comments
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+ xsi:noNamespaceSchemaLocation='comments.xsd'
+ name="24.2.0_to_25.0.0"
+ jdversion="1.1.0">
+
+<!-- Use this file to enter an API change description. For example, when you remove a class,
+ you can enter a comment for that class that points developers to the replacement class.
+ You can also provide a change summary for modified API, to give an overview of the changes
+ why they were made, workarounds, etc. -->
+
+<!-- When the API diffs report is generated, the comments in this file get added to the tables of
+ removed, added, and modified packages, classes, methods, and fields. This file does not ship
+ with the final report. -->
+
+<!-- The id attribute in an identifier element identifies the change as noted in the report.
+ An id has the form package[.class[.[ctor|method|field].signature]], where [] indicates optional
+ text. A comment element can have multiple identifier elements, which will will cause the same
+ text to appear at each place in the report, but will be converted to separate comments when the
+ comments file is used. -->
+
+<!-- HTML tags in the text field will appear in the report. You also need to close p HTML elements,
+ used for paragraphs - see the top-level documentation. -->
+
+<!-- You can include standard javadoc links in your change descriptions. You can use the @first command
+ to cause jdiff to include the first line of the API documentation. You also need to close p HTML
+ elements, used for paragraphs - see the top-level documentation. -->
+
+<comment>
+ <identifier id="android.support.customtabs"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.customtabs.CustomTabsIntent"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.customtabs.CustomTabsIntent.launchUrl_changed(android.content.Context, android.net.Uri)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.BottomNavigationView"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.BottomNavigationView.OnNavigationItemSelectedListener"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.FloatingActionButton"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.FloatingActionButton.getRippleColor_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v13.app"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v13.app.ActivityCompat"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v13.app.ActivityCompat.ctor_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v13.view.inputmethod"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.ActivityCompat"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.ActivityCompat.ctor_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.ActivityCompat.getReferrer_changed(android.app.Activity)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.NotificationCompat.WearableExtender"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.NotificationCompat.WearableExtender.getBridgeTag_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.NotificationCompat.WearableExtender.setBridgeTag_added(java.lang.String)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.content"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.content.ContextCompat"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.content.ContextCompat.ctor_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.content.ContextCompat.startActivity_added(android.content.Context, android.content.Intent, android.os.Bundle)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.content.ContextCompat.startActivity_changed(android.content.Context, android.content.Intent, android.os.Bundle)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.net"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.net.ConnectivityManagerCompat"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_DISABLED"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.net.ConnectivityManagerCompat.getRestrictBackgroundStatus_added(android.net.ConnectivityManager)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.text"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.text.BidiFormatter"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.text.BidiFormatter.isRtl_added(java.lang.CharSequence)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, android.support.v4.text.TextDirectionHeuristicCompat, boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.text.BidiFormatter.unicodeWrap_added(java.lang.CharSequence, boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.view"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.view.ViewCompat"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.view.ViewCompat.getDisplay_added(android.view.View)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.view.ViewCompat.setBackground_added(android.view.View, android.graphics.drawable.Drawable)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.view.ViewPager"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.view.ViewPager.setPageTransformer_added(boolean, android.support.v4.view.ViewPager.PageTransformer, int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.widget"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.widget.SwipeRefreshLayout"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.widget.SwipeRefreshLayout.getProgressViewEndOffset_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.widget.SwipeRefreshLayout.getProgressViewStartOffset_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.app"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.app.NotificationCompat.DecoratedCustomViewStyle"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.app.NotificationCompat.DecoratedMediaCustomViewStyle"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.DividerItemDecoration"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.RecyclerView"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.RecyclerView.LayoutManager"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.RecyclerView.LayoutManager.isItemPrefetchEnabled_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.RecyclerView.LayoutManager.setItemPrefetchEnabled_added(boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.RecyclerView.getDecoratedBoundsWithMargins_added(android.view.View, android.graphics.Rect)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.Space"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+
+</comments>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes.html b/docs/html/sdk/support_api_diff/25.1.0/changes.html
new file mode 100644
index 0000000..269519e
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<!-- on Thu Dec 08 16:29:21 EST 2016 -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Support Library API Differences Report
+</TITLE>
+<link href="../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</head>
+<frameset cols="242,**" framespacing="1" frameborder="yes" border="1" bordercolor="#e9e9e9">
+<frameset rows="174,**" framespacing="1" frameborder="yes" border="1" bordercolor="#e9e9e9">
+ <frame src="changes/jdiff_topleftframe.html" scrolling="no" name="topleftframe" frameborder="1">
+ <frame src="changes/alldiffs_index_all.html" scrolling="auto" name="bottomleftframe" frameborder="1">
+ </frameset>
+ <frame src="changes/changes-summary.html" scrolling="auto" name="rightframe" frameborder="1">
+</frameset>
+<noframes>
+<h2>
+Frame Alert
+</h2>
+
+<p>
+This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+<br>
+Link to <a href="changes/changes-summary.html" target="_top">Non-frame version.</A>
+</noframes>
+</html>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/alldiffs_index_additions.html b/docs/html/sdk/support_api_diff/25.1.0/changes/alldiffs_index_additions.html
new file mode 100644
index 0000000..8b8446e
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/alldiffs_index_additions.html
@@ -0,0 +1,579 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a>
+ <br>
+<A HREF="alldiffs_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<b>Additions</b>
+ <br>
+<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<!-- Class AnimatedVectorDrawableCompat -->
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.graphics.drawable.html#AnimatedVectorDrawableCompat" class="hiddenlink" target="rightframe"><b>AnimatedVectorDrawableCompat</b></A><br>
+<!-- Class ArraySet -->
+<A HREF="pkg_android.support.v4.util.html#ArraySet" class="hiddenlink" target="rightframe"><b>ArraySet</b></A><br>
+<!-- Method attachToView -->
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.attachToView_added(android.view.View)" class="hiddenlink" target="rightframe"><b>attachToView</b>
+(<code>View</code>)</A></nobr><br>
+<!-- Class BaseTransientBottomBar -->
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.design.widget.html#BaseTransientBottomBar" class="hiddenlink" target="rightframe"><b>BaseTransientBottomBar</b></A><br>
+<!-- Class BaseTransientBottomBar.BaseCallback -->
+<A HREF="pkg_android.support.design.widget.html#BaseTransientBottomBar.BaseCallback" class="hiddenlink" target="rightframe"><b>BaseTransientBottomBar.BaseCallback</b></A><br>
+<!-- Class BaseTransientBottomBar.ContentViewCallback -->
+<A HREF="pkg_android.support.design.widget.html#BaseTransientBottomBar.ContentViewCallback" class="hiddenlink" target="rightframe"><b><i>BaseTransientBottomBar.ContentViewCallback</i></b></A><br>
+<!-- Method clearDrawable -->
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.clearDrawable_added()" class="hiddenlink" target="rightframe"><b>clearDrawable</b>
+()</A></nobr><br>
+<!-- Method collapseAction -->
+<i>collapseAction</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html#android.support.v17.leanback.app.GuidedStepFragment.collapseAction_added(boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepFragment
+</A></nobr><br>
+<!-- Method collapseAction -->
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html#android.support.v17.leanback.app.GuidedStepSupportFragment.collapseAction_added(boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepSupportFragment
+</A></nobr><br>
+<!-- Method collapseAction -->
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.collapseAction_added(boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>boolean</code>)</b> in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<!-- Method createSnapScroller -->
+<nobr><A HREF="android.support.v7.widget.SnapHelper.html#android.support.v7.widget.SnapHelper.createSnapScroller_added(android.support.v7.widget.RecyclerView.LayoutManager)" class="hiddenlink" target="rightframe"><b>createSnapScroller</b>
+(<code>LayoutManager</code>)</A></nobr><br>
+<!-- Method expandAction -->
+<A NAME="E"></A>
+<br><font size="+2">E</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>expandAction</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html#android.support.v17.leanback.app.GuidedStepFragment.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>GuidedAction, boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepFragment
+</A></nobr><br>
+<!-- Method expandAction -->
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html#android.support.v17.leanback.app.GuidedStepSupportFragment.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>GuidedAction, boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepSupportFragment
+</A></nobr><br>
+<!-- Method expandAction -->
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>GuidedAction, boolean</code>)</b> in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<!-- Method findRowViewHolderByPosition -->
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>findRowViewHolderByPosition</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.html#android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter
+</A></nobr><br>
+<!-- Method findRowViewHolderByPosition -->
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.html#android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter
+</A></nobr><br>
+<!-- Method findRowViewHolderByPosition -->
+ <nobr><A HREF="android.support.v17.leanback.app.RowsFragment.html#android.support.v17.leanback.app.RowsFragment.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.RowsFragment
+</A></nobr><br>
+<!-- Method findRowViewHolderByPosition -->
+ <nobr><A HREF="android.support.v17.leanback.app.RowsSupportFragment.html#android.support.v17.leanback.app.RowsSupportFragment.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.RowsSupportFragment
+</A></nobr><br>
+<!-- Class FragmentManager.FragmentLifecycleCallbacks -->
+<A HREF="pkg_android.support.v4.app.html#FragmentManager.FragmentLifecycleCallbacks" class="hiddenlink" target="rightframe"><b>FragmentManager.FragmentLifecycleCallbacks</b></A><br>
+<!-- Method getBluetoothRoute -->
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v7.media.MediaRouter.html#android.support.v7.media.MediaRouter.getBluetoothRoute_added()" class="hiddenlink" target="rightframe"><b>getBluetoothRoute</b>
+()</A></nobr><br>
+<!-- Method getBufferedProgressLong -->
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.getBufferedProgressLong_added()" class="hiddenlink" target="rightframe"><b>getBufferedProgressLong</b>
+()</A></nobr><br>
+<!-- Method getCurrentTimeLong -->
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.getCurrentTimeLong_added()" class="hiddenlink" target="rightframe"><b>getCurrentTimeLong</b>
+()</A></nobr><br>
+<!-- Method getDescription -->
+<nobr><A HREF="android.support.v17.leanback.widget.HeaderItem.html#android.support.v17.leanback.widget.HeaderItem.getDescription_added()" class="hiddenlink" target="rightframe"><b>getDescription</b>
+()</A></nobr><br>
+<!-- Method getEventHandler -->
+<i>getEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.getEventHandler_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+<!-- Method getEventHandler -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.getEventHandler_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<!-- Method getGravity -->
+<nobr><A HREF="android.support.v7.widget.LinearLayoutCompat.html#android.support.v7.widget.LinearLayoutCompat.getGravity_added()" class="hiddenlink" target="rightframe"><b>getGravity</b>
+()</A></nobr><br>
+<!-- Method getMainFragment -->
+<i>getMainFragment</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseFragment.html#android.support.v17.leanback.app.BrowseFragment.getMainFragment_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseFragment
+</A></nobr><br>
+<!-- Method getMainFragment -->
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.html#android.support.v17.leanback.app.BrowseSupportFragment.getMainFragment_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseSupportFragment
+</A></nobr><br>
+<!-- Method getMediaController -->
+<nobr><A HREF="android.support.v4.media.session.MediaControllerCompat.html#android.support.v4.media.session.MediaControllerCompat.getMediaController_added(android.app.Activity)" class="hiddenlink" target="rightframe"><b>getMediaController</b>
+(<code>Activity</code>)</A></nobr><br>
+<!-- Method getPreferenceComparisonCallback -->
+<nobr><A HREF="android.support.v7.preference.PreferenceManager.html#android.support.v7.preference.PreferenceManager.getPreferenceComparisonCallback_added()" class="hiddenlink" target="rightframe"><b>getPreferenceComparisonCallback</b>
+()</A></nobr><br>
+<!-- Method getRecycledViewCount -->
+<nobr><A HREF="android.support.v7.widget.RecyclerView.RecycledViewPool.html#android.support.v7.widget.RecyclerView.RecycledViewPool.getRecycledViewCount_added(int)" class="hiddenlink" target="rightframe"><b>getRecycledViewCount</b>
+(<code>int</code>)</A></nobr><br>
+<!-- Method getSelectedItem -->
+<nobr><A HREF="android.support.v17.leanback.widget.RowPresenter.ViewHolder.html#android.support.v17.leanback.widget.RowPresenter.ViewHolder.getSelectedItem_added()" class="hiddenlink" target="rightframe"><b>getSelectedItem</b>
+()</A></nobr><br>
+<!-- Method getSelectedItemViewHolder -->
+<nobr><A HREF="android.support.v17.leanback.widget.RowPresenter.ViewHolder.html#android.support.v17.leanback.widget.RowPresenter.ViewHolder.getSelectedItemViewHolder_added()" class="hiddenlink" target="rightframe"><b>getSelectedItemViewHolder</b>
+()</A></nobr><br>
+<!-- Method getSelectedRowViewHolder -->
+<i>getSelectedRowViewHolder</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseFragment.html#android.support.v17.leanback.app.BrowseFragment.getSelectedRowViewHolder_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseFragment
+</A></nobr><br>
+<!-- Method getSelectedRowViewHolder -->
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.html#android.support.v17.leanback.app.BrowseSupportFragment.getSelectedRowViewHolder_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseSupportFragment
+</A></nobr><br>
+<!-- Method getTotalTimeLong -->
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.getTotalTimeLong_added()" class="hiddenlink" target="rightframe"><b>getTotalTimeLong</b>
+()</A></nobr><br>
+<!-- Method getVerticalGridView -->
+<i>getVerticalGridView</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BaseRowFragment.html#android.support.v17.leanback.app.BaseRowFragment.getVerticalGridView_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BaseRowFragment
+</A></nobr><br>
+<!-- Method getVerticalGridView -->
+ <nobr><A HREF="android.support.v17.leanback.app.BaseRowSupportFragment.html#android.support.v17.leanback.app.BaseRowSupportFragment.getVerticalGridView_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BaseRowSupportFragment
+</A></nobr><br>
+<!-- Method isAtLeastO -->
+<A NAME="I"></A>
+<br><font size="+2">I</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.os.BuildCompat.html#android.support.v4.os.BuildCompat.isAtLeastO_added()" class="hiddenlink" target="rightframe"><b>isAtLeastO</b>
+()</A></nobr><br>
+<!-- Method isAutoReleaseOnStop -->
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.isAutoReleaseOnStop_added()" class="hiddenlink" target="rightframe"><b>isAutoReleaseOnStop</b>
+()</A></nobr><br>
+<!-- Method isBackKeyToCollapseActivatorView -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.isBackKeyToCollapseActivatorView_added()" class="hiddenlink" target="rightframe"><b>isBackKeyToCollapseActivatorView</b>
+()</A></nobr><br>
+<!-- Method isBackKeyToCollapseSubActions -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.isBackKeyToCollapseSubActions_added()" class="hiddenlink" target="rightframe"><b>isBackKeyToCollapseSubActions</b>
+()</A></nobr><br>
+<!-- Method isBluetooth -->
+<nobr><A HREF="android.support.v7.media.MediaRouter.RouteInfo.html#android.support.v7.media.MediaRouter.RouteInfo.isBluetooth_added()" class="hiddenlink" target="rightframe"><b>isBluetooth</b>
+()</A></nobr><br>
+<!-- Method isDeviceSpeaker -->
+<nobr><A HREF="android.support.v7.media.MediaRouter.RouteInfo.html#android.support.v7.media.MediaRouter.RouteInfo.isDeviceSpeaker_added()" class="hiddenlink" target="rightframe"><b>isDeviceSpeaker</b>
+()</A></nobr><br>
+<!-- Method isExpanded -->
+<i>isExpanded</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html#android.support.v17.leanback.app.GuidedStepFragment.isExpanded_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.GuidedStepFragment
+</A></nobr><br>
+<!-- Method isExpanded -->
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html#android.support.v17.leanback.app.GuidedStepSupportFragment.isExpanded_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.GuidedStepSupportFragment
+</A></nobr><br>
+<!-- Method isExpanded -->
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.isExpanded_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<!-- Method isVirtual -->
+<nobr><A HREF="android.support.v4.provider.DocumentFile.html#android.support.v4.provider.DocumentFile.isVirtual_added()" class="hiddenlink" target="rightframe"><b>isVirtual</b>
+()</A></nobr><br>
+<!-- Constructor MediaControllerGlue -->
+<A NAME="M"></A>
+<br><font size="+2">M</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.ctor_added(android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])" class="hiddenlink" target="rightframe"><b>MediaControllerGlue</b>
+(<code>Context, PlaybackGlueHost, int[], int[]</code>)</A></nobr> constructor<br>
+<!-- Method onChildViewHolderSelectedAndPositioned -->
+<A NAME="O"></A>
+<br><font size="+2">O</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.html#android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.onChildViewHolderSelectedAndPositioned_added(android.support.v7.widget.RecyclerView, android.support.v7.widget.RecyclerView.ViewHolder, int, int)" class="hiddenlink" target="rightframe"><b>onChildViewHolderSelectedAndPositioned</b>
+(<code>RecyclerView, ViewHolder, int, int</code>)</A></nobr><br>
+<!-- Method onEditingModeChange -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.onEditingModeChange_added(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean, boolean)" class="hiddenlink" target="rightframe"><b>onEditingModeChange</b>
+(<code>ViewHolder, boolean, boolean</code>)</A></nobr><br>
+<!-- Class PagerSnapHelper -->
+<A NAME="P"></A>
+<br><font size="+2">P</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#PagerSnapHelper" class="hiddenlink" target="rightframe"><b>PagerSnapHelper</b></A><br>
+<!-- Constructor PlaybackControlGlue -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.ctor_added(android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])" class="hiddenlink" target="rightframe"><b>PlaybackControlGlue</b>
+(<code>Context, PlaybackGlueHost, int[], int[]</code>)</A></nobr> constructor<br>
+<!-- Class PlaybackControlGlue.InputEventHandler -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackControlGlue.InputEventHandler" class="hiddenlink" target="rightframe"><b><i>PlaybackControlGlue.InputEventHandler</i></b></A><br>
+<!-- Class PlaybackFragment -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackFragment" class="hiddenlink" target="rightframe"><b>PlaybackFragment</b></A><br>
+<!-- Class PlaybackFragment.OnFadeCompleteListener -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackFragment.OnFadeCompleteListener" class="hiddenlink" target="rightframe"><b>PlaybackFragment.OnFadeCompleteListener</b></A><br>
+<!-- Class PlaybackFragmentGlueHost -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackFragmentGlueHost" class="hiddenlink" target="rightframe"><b>PlaybackFragmentGlueHost</b></A><br>
+<!-- Class PlaybackGlue -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue" class="hiddenlink" target="rightframe"><b>PlaybackGlue</b></A><br>
+<!-- Class PlaybackGlue.HostLifecycleCallback -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue.HostLifecycleCallback" class="hiddenlink" target="rightframe"><b>PlaybackGlue.HostLifecycleCallback</b></A><br>
+<!-- Class PlaybackGlue.PlaybackGlueHost -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue.PlaybackGlueHost" class="hiddenlink" target="rightframe"><b>PlaybackGlue.PlaybackGlueHost</b></A><br>
+<!-- Class PlaybackGlue.PlayerCallback -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue.PlayerCallback" class="hiddenlink" target="rightframe"><b>PlaybackGlue.PlayerCallback</b></A><br>
+<!-- Class PlaybackRowPresenter -->
+<A HREF="pkg_android.support.v17.leanback.widget.html#PlaybackRowPresenter" class="hiddenlink" target="rightframe"><b>PlaybackRowPresenter</b></A><br>
+<!-- Class PlaybackRowPresenter.ViewHolder -->
+<A HREF="pkg_android.support.v17.leanback.widget.html#PlaybackRowPresenter.ViewHolder" class="hiddenlink" target="rightframe"><b>PlaybackRowPresenter.ViewHolder</b></A><br>
+<!-- Class PlaybackSupportFragment -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackSupportFragment" class="hiddenlink" target="rightframe"><b>PlaybackSupportFragment</b></A><br>
+<!-- Class PlaybackSupportFragment.OnFadeCompleteListener -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackSupportFragment.OnFadeCompleteListener" class="hiddenlink" target="rightframe"><b>PlaybackSupportFragment.OnFadeCompleteListener</b></A><br>
+<!-- Class PlaybackSupportFragmentGlueHost -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackSupportFragmentGlueHost" class="hiddenlink" target="rightframe"><b>PlaybackSupportFragmentGlueHost</b></A><br>
+<!-- Method postponeEnterTransition -->
+<nobr><A HREF="android.support.v4.app.Fragment.html#android.support.v4.app.Fragment.postponeEnterTransition_added()" class="hiddenlink" target="rightframe"><b>postponeEnterTransition</b>
+()</A></nobr><br>
+<!-- Class PreferenceManager.PreferenceComparisonCallback -->
+<A HREF="pkg_android.support.v7.preference.html#PreferenceManager.PreferenceComparisonCallback" class="hiddenlink" target="rightframe"><b>PreferenceManager.PreferenceComparisonCallback</b></A><br>
+<!-- Class PreferenceManager.SimplePreferenceComparisonCallback -->
+<A HREF="pkg_android.support.v7.preference.html#PreferenceManager.SimplePreferenceComparisonCallback" class="hiddenlink" target="rightframe"><b>PreferenceManager.SimplePreferenceComparisonCallback</b></A><br>
+<!-- Method registerFragmentLifecycleCallbacks -->
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.FragmentManager.html#android.support.v4.app.FragmentManager.registerFragmentLifecycleCallbacks_added(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks, boolean)" class="hiddenlink" target="rightframe"><b>registerFragmentLifecycleCallbacks</b>
+(<code>FragmentLifecycleCallbacks, boolean</code>)</A></nobr><br>
+<!-- Class SeekBarPreference -->
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.preference.html#SeekBarPreference" class="hiddenlink" target="rightframe"><b>SeekBarPreference</b></A><br>
+<!-- Method setAllowOptimization -->
+<nobr><A HREF="android.support.v4.app.FragmentTransaction.html#android.support.v4.app.FragmentTransaction.setAllowOptimization_added(boolean)" class="hiddenlink" target="rightframe"><b>setAllowOptimization</b>
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method setAutoReleaseOnStop -->
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.setAutoReleaseOnStop_added(boolean)" class="hiddenlink" target="rightframe"><b>setAutoReleaseOnStop</b>
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method setBackKeyToCollapseActivatorView -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setBackKeyToCollapseActivatorView_added(boolean)" class="hiddenlink" target="rightframe"><b>setBackKeyToCollapseActivatorView</b>
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method setBackKeyToCollapseSubActions -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setBackKeyToCollapseSubActions_added(boolean)" class="hiddenlink" target="rightframe"><b>setBackKeyToCollapseSubActions</b>
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method setBufferedProgressLong -->
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.setBufferedProgressLong_added(long)" class="hiddenlink" target="rightframe"><b>setBufferedProgressLong</b>
+(<code>long</code>)</A></nobr><br>
+<!-- Method setCurrentTimeLong -->
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.setCurrentTimeLong_added(long)" class="hiddenlink" target="rightframe"><b>setCurrentTimeLong</b>
+(<code>long</code>)</A></nobr><br>
+<!-- Method setDescription -->
+<nobr><A HREF="android.support.v17.leanback.widget.HeaderItem.html#android.support.v17.leanback.widget.HeaderItem.setDescription_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>setDescription</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<!-- Method setErrorTextAppearance -->
+<nobr><A HREF="android.support.design.widget.TextInputLayout.html#android.support.design.widget.TextInputLayout.setErrorTextAppearance_added(int)" class="hiddenlink" target="rightframe"><b>setErrorTextAppearance</b>
+(<code>int</code>)</A></nobr><br>
+<!-- Method setEventHandler -->
+<i>setEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.setEventHandler_added(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)" class="hiddenlink" target="rightframe">type <b>
+(<code>InputEventHandler</code>)</b> in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+<!-- Method setEventHandler -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.setEventHandler_added(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)" class="hiddenlink" target="rightframe">type <b>
+(<code>InputEventHandler</code>)</b> in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<!-- Method setListeningOrbColors -->
+<nobr><A HREF="android.support.v17.leanback.widget.SpeechOrbView.html#android.support.v17.leanback.widget.SpeechOrbView.setListeningOrbColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe"><b>setListeningOrbColors</b>
+(<code>Colors</code>)</A></nobr><br>
+<!-- Method setMediaController -->
+<nobr><A HREF="android.support.v4.media.session.MediaControllerCompat.html#android.support.v4.media.session.MediaControllerCompat.setMediaController_added(android.app.Activity, android.support.v4.media.session.MediaControllerCompat)" class="hiddenlink" target="rightframe"><b>setMediaController</b>
+(<code>Activity, MediaControllerCompat</code>)</A></nobr><br>
+<!-- Method setNotListeningOrbColors -->
+<nobr><A HREF="android.support.v17.leanback.widget.SpeechOrbView.html#android.support.v17.leanback.widget.SpeechOrbView.setNotListeningOrbColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe"><b>setNotListeningOrbColors</b>
+(<code>Colors</code>)</A></nobr><br>
+<!-- Method setOnDispatchKeyListener -->
+<nobr><A HREF="android.support.v17.leanback.widget.BrowseFrameLayout.html#android.support.v17.leanback.widget.BrowseFrameLayout.setOnDispatchKeyListener_added(android.view.View.OnKeyListener)" class="hiddenlink" target="rightframe"><b>setOnDispatchKeyListener</b>
+(<code>OnKeyListener</code>)</A></nobr><br>
+<!-- Method setPreferenceComparisonCallback -->
+<nobr><A HREF="android.support.v7.preference.PreferenceManager.html#android.support.v7.preference.PreferenceManager.setPreferenceComparisonCallback_added(android.support.v7.preference.PreferenceManager.PreferenceComparisonCallback)" class="hiddenlink" target="rightframe"><b>setPreferenceComparisonCallback</b>
+(<code>PreferenceComparisonCallback</code>)</A></nobr><br>
+<!-- Method setSearchAffordanceColors -->
+<i>setSearchAffordanceColors</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.SearchFragment.html#android.support.v17.leanback.app.SearchFragment.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchFragment
+</A></nobr><br>
+<!-- Method setSearchAffordanceColors -->
+ <nobr><A HREF="android.support.v17.leanback.app.SearchSupportFragment.html#android.support.v17.leanback.app.SearchSupportFragment.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchSupportFragment
+</A></nobr><br>
+<!-- Method setSearchAffordanceColors -->
+ <nobr><A HREF="android.support.v17.leanback.widget.SearchBar.html#android.support.v17.leanback.widget.SearchBar.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.widget.SearchBar
+</A></nobr><br>
+<!-- Method setSearchAffordanceColorsInListening -->
+<i>setSearchAffordanceColorsInListening</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.SearchFragment.html#android.support.v17.leanback.app.SearchFragment.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchFragment
+</A></nobr><br>
+<!-- Method setSearchAffordanceColorsInListening -->
+ <nobr><A HREF="android.support.v17.leanback.app.SearchSupportFragment.html#android.support.v17.leanback.app.SearchSupportFragment.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchSupportFragment
+</A></nobr><br>
+<!-- Method setSearchAffordanceColorsInListening -->
+ <nobr><A HREF="android.support.v17.leanback.widget.SearchBar.html#android.support.v17.leanback.widget.SearchBar.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.widget.SearchBar
+</A></nobr><br>
+<!-- Method setTitle -->
+<nobr><A HREF="android.support.v17.preference.LeanbackPreferenceFragment.html#android.support.v17.preference.LeanbackPreferenceFragment.setTitle_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>setTitle</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<!-- Method setTotalTimeLong -->
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.setTotalTimeLong_added(long)" class="hiddenlink" target="rightframe"><b>setTotalTimeLong</b>
+(<code>long</code>)</A></nobr><br>
+<!-- Method smoothScrollBy -->
+<nobr><A HREF="android.support.v7.widget.RecyclerView.html#android.support.v7.widget.RecyclerView.smoothScrollBy_added(int, int, android.view.animation.Interpolator)" class="hiddenlink" target="rightframe"><b>smoothScrollBy</b>
+(<code>int, int, Interpolator</code>)</A></nobr><br>
+<!-- Method startPostponedEnterTransition -->
+<nobr><A HREF="android.support.v4.app.Fragment.html#android.support.v4.app.Fragment.startPostponedEnterTransition_added()" class="hiddenlink" target="rightframe"><b>startPostponedEnterTransition</b>
+()</A></nobr><br>
+<!-- Class SurfaceHolderGlueHost -->
+<A HREF="pkg_android.support.v17.leanback.app.html#SurfaceHolderGlueHost" class="hiddenlink" target="rightframe"><b><i>SurfaceHolderGlueHost</i></b></A><br>
+<!-- Method unregisterFragmentLifecycleCallbacks -->
+<A NAME="U"></A>
+<br><font size="+2">U</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.FragmentManager.html#android.support.v4.app.FragmentManager.unregisterFragmentLifecycleCallbacks_added(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks)" class="hiddenlink" target="rightframe"><b>unregisterFragmentLifecycleCallbacks</b>
+(<code>FragmentLifecycleCallbacks</code>)</A></nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/alldiffs_index_all.html b/docs/html/sdk/support_api_diff/25.1.0/changes/alldiffs_index_all.html
new file mode 100644
index 0000000..4b3966c
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/alldiffs_index_all.html
@@ -0,0 +1,1126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>All Differences</b>
+ <br>
+<A HREF="alldiffs_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<!-- Package android.support.design.widget -->
+<A NAME="A"></A>
+<A HREF="pkg_android.support.design.widget.html" class="hiddenlink" target="rightframe">android.support.design.widget</A><br>
+<!-- Package android.support.graphics.drawable -->
+<A HREF="pkg_android.support.graphics.drawable.html" class="hiddenlink" target="rightframe">android.support.graphics.drawable</A><br>
+<!-- Package android.support.v17.leanback.app -->
+<A HREF="pkg_android.support.v17.leanback.app.html" class="hiddenlink" target="rightframe">android.support.v17.leanback.app</A><br>
+<!-- Package android.support.v17.leanback.widget -->
+<A HREF="pkg_android.support.v17.leanback.widget.html" class="hiddenlink" target="rightframe">android.support.v17.leanback.widget</A><br>
+<!-- Package android.support.v17.preference -->
+<A HREF="pkg_android.support.v17.preference.html" class="hiddenlink" target="rightframe">android.support.v17.preference</A><br>
+<!-- Package android.support.v4.app -->
+<A HREF="pkg_android.support.v4.app.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<!-- Package android.support.v4.media.session -->
+<A HREF="pkg_android.support.v4.media.session.html" class="hiddenlink" target="rightframe">android.support.v4.media.session</A><br>
+<!-- Package android.support.v4.os -->
+<A HREF="pkg_android.support.v4.os.html" class="hiddenlink" target="rightframe">android.support.v4.os</A><br>
+<!-- Package android.support.v4.provider -->
+<A HREF="pkg_android.support.v4.provider.html" class="hiddenlink" target="rightframe">android.support.v4.provider</A><br>
+<!-- Package android.support.v4.util -->
+<A HREF="pkg_android.support.v4.util.html" class="hiddenlink" target="rightframe">android.support.v4.util</A><br>
+<!-- Package android.support.v7.app -->
+<A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
+<!-- Package android.support.v7.media -->
+<A HREF="pkg_android.support.v7.media.html" class="hiddenlink" target="rightframe">android.support.v7.media</A><br>
+<!-- Package android.support.v7.preference -->
+<A HREF="pkg_android.support.v7.preference.html" class="hiddenlink" target="rightframe">android.support.v7.preference</A><br>
+<!-- Package android.support.v7.widget -->
+<A HREF="pkg_android.support.v7.widget.html" class="hiddenlink" target="rightframe">android.support.v7.widget</A><br>
+<!-- Class AnimatedVectorDrawableCompat -->
+<A HREF="pkg_android.support.graphics.drawable.html#AnimatedVectorDrawableCompat" class="hiddenlink" target="rightframe"><b>AnimatedVectorDrawableCompat</b></A><br>
+<!-- Class ArraySet -->
+<A HREF="pkg_android.support.v4.util.html#ArraySet" class="hiddenlink" target="rightframe"><b>ArraySet</b></A><br>
+<!-- Method attachToView -->
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.attachToView_added(android.view.View)" class="hiddenlink" target="rightframe"><b>attachToView</b>
+(<code>View</code>)</A></nobr><br>
+<!-- Class BackgroundManager -->
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.app.BackgroundManager.html" class="hiddenlink" target="rightframe">BackgroundManager</A><br>
+<!-- Class BaseCardView -->
+<A HREF="android.support.v17.leanback.widget.BaseCardView.html" class="hiddenlink" target="rightframe">BaseCardView</A><br>
+<!-- Class BaseRowFragment -->
+<A HREF="android.support.v17.leanback.app.BaseRowFragment.html" class="hiddenlink" target="rightframe">BaseRowFragment</A><br>
+<!-- Class BaseRowSupportFragment -->
+<A HREF="android.support.v17.leanback.app.BaseRowSupportFragment.html" class="hiddenlink" target="rightframe">BaseRowSupportFragment</A><br>
+<!-- Class BaseTransientBottomBar -->
+<A HREF="pkg_android.support.design.widget.html#BaseTransientBottomBar" class="hiddenlink" target="rightframe"><b>BaseTransientBottomBar</b></A><br>
+<!-- Class BaseTransientBottomBar.BaseCallback -->
+<A HREF="pkg_android.support.design.widget.html#BaseTransientBottomBar.BaseCallback" class="hiddenlink" target="rightframe"><b>BaseTransientBottomBar.BaseCallback</b></A><br>
+<!-- Class BaseTransientBottomBar.ContentViewCallback -->
+<A HREF="pkg_android.support.design.widget.html#BaseTransientBottomBar.ContentViewCallback" class="hiddenlink" target="rightframe"><b><i>BaseTransientBottomBar.ContentViewCallback</i></b></A><br>
+<!-- Class BrowseFragment -->
+<A HREF="android.support.v17.leanback.app.BrowseFragment.html" class="hiddenlink" target="rightframe">BrowseFragment</A><br>
+<!-- Class BrowseFragment.MainFragmentRowsAdapter -->
+<A HREF="android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.html" class="hiddenlink" target="rightframe">BrowseFragment.MainFragmentRowsAdapter</A><br>
+<!-- Class BrowseFrameLayout -->
+<A HREF="android.support.v17.leanback.widget.BrowseFrameLayout.html" class="hiddenlink" target="rightframe">BrowseFrameLayout</A><br>
+<!-- Class BrowseSupportFragment -->
+<A HREF="android.support.v17.leanback.app.BrowseSupportFragment.html" class="hiddenlink" target="rightframe">BrowseSupportFragment</A><br>
+<!-- Class BrowseSupportFragment.MainFragmentRowsAdapter -->
+<A HREF="android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.html" class="hiddenlink" target="rightframe">BrowseSupportFragment.MainFragmentRowsAdapter</A><br>
+<!-- Class BuildCompat -->
+<A HREF="android.support.v4.os.BuildCompat.html" class="hiddenlink" target="rightframe">BuildCompat</A><br>
+<!-- Method clearDrawable -->
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.clearDrawable_added()" class="hiddenlink" target="rightframe"><b>clearDrawable</b>
+()</A></nobr><br>
+<!-- Method collapseAction -->
+<i>collapseAction</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html#android.support.v17.leanback.app.GuidedStepFragment.collapseAction_added(boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepFragment
+</A></nobr><br>
+<!-- Method collapseAction -->
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html#android.support.v17.leanback.app.GuidedStepSupportFragment.collapseAction_added(boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepSupportFragment
+</A></nobr><br>
+<!-- Method collapseAction -->
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.collapseAction_added(boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>boolean</code>)</b> in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<!-- Method createControlsRowAndPresenter -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.createControlsRowAndPresenter_changed()" class="hiddenlink" target="rightframe">createControlsRowAndPresenter
+()</A></nobr><br>
+<!-- Method createPrimaryActionsAdapter -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.createPrimaryActionsAdapter_changed(android.support.v17.leanback.widget.PresenterSelector)" class="hiddenlink" target="rightframe">createPrimaryActionsAdapter
+(<code>PresenterSelector</code>)</A></nobr><br>
+<!-- Method createSnapScroller -->
+<nobr><A HREF="android.support.v7.widget.SnapHelper.html#android.support.v7.widget.SnapHelper.createSnapScroller_added(android.support.v7.widget.RecyclerView.LayoutManager)" class="hiddenlink" target="rightframe"><b>createSnapScroller</b>
+(<code>LayoutManager</code>)</A></nobr><br>
+<!-- Method dismiss -->
+<A NAME="D"></A>
+<br><font size="+2">D</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.dismiss_changed()" class="hiddenlink" target="rightframe">dismiss
+()</A></nobr><br>
+<!-- Class DocumentFile -->
+<A HREF="android.support.v4.provider.DocumentFile.html" class="hiddenlink" target="rightframe">DocumentFile</A><br>
+<!-- Method enableProgressUpdating -->
+<A NAME="E"></A>
+<br><font size="+2">E</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.enableProgressUpdating_changed(boolean)" class="hiddenlink" target="rightframe">enableProgressUpdating
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method expandAction -->
+<i>expandAction</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html#android.support.v17.leanback.app.GuidedStepFragment.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>GuidedAction, boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepFragment
+</A></nobr><br>
+<!-- Method expandAction -->
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html#android.support.v17.leanback.app.GuidedStepSupportFragment.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>GuidedAction, boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepSupportFragment
+</A></nobr><br>
+<!-- Method expandAction -->
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>GuidedAction, boolean</code>)</b> in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<!-- Method findRowViewHolderByPosition -->
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>findRowViewHolderByPosition</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.html#android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter
+</A></nobr><br>
+<!-- Method findRowViewHolderByPosition -->
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.html#android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter
+</A></nobr><br>
+<!-- Method findRowViewHolderByPosition -->
+ <nobr><A HREF="android.support.v17.leanback.app.RowsFragment.html#android.support.v17.leanback.app.RowsFragment.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.RowsFragment
+</A></nobr><br>
+<!-- Method findRowViewHolderByPosition -->
+ <nobr><A HREF="android.support.v17.leanback.app.RowsSupportFragment.html#android.support.v17.leanback.app.RowsSupportFragment.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.RowsSupportFragment
+</A></nobr><br>
+<!-- Class Fragment -->
+<A HREF="android.support.v4.app.Fragment.html" class="hiddenlink" target="rightframe">Fragment</A><br>
+<!-- Class FragmentActivity -->
+<A HREF="android.support.v4.app.FragmentActivity.html" class="hiddenlink" target="rightframe">FragmentActivity</A><br>
+<!-- Class FragmentManager -->
+<A HREF="android.support.v4.app.FragmentManager.html" class="hiddenlink" target="rightframe">FragmentManager</A><br>
+<!-- Class FragmentManager.FragmentLifecycleCallbacks -->
+<A HREF="pkg_android.support.v4.app.html#FragmentManager.FragmentLifecycleCallbacks" class="hiddenlink" target="rightframe"><b>FragmentManager.FragmentLifecycleCallbacks</b></A><br>
+<!-- Class FragmentTransaction -->
+<A HREF="android.support.v4.app.FragmentTransaction.html" class="hiddenlink" target="rightframe">FragmentTransaction</A><br>
+<!-- Method getBluetoothRoute -->
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v7.media.MediaRouter.html#android.support.v7.media.MediaRouter.getBluetoothRoute_added()" class="hiddenlink" target="rightframe"><b>getBluetoothRoute</b>
+()</A></nobr><br>
+<!-- Method getBufferedProgressLong -->
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.getBufferedProgressLong_added()" class="hiddenlink" target="rightframe"><b>getBufferedProgressLong</b>
+()</A></nobr><br>
+<!-- Method getContext -->
+<i>getContext</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.getContext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method getContext -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getContext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Method getControlsRow -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getControlsRow_changed()" class="hiddenlink" target="rightframe">getControlsRow
+()</A></nobr><br>
+<!-- Method getCurrentPosition -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getCurrentPosition_changed()" class="hiddenlink" target="rightframe">getCurrentPosition
+()</A></nobr><br>
+<!-- Method getCurrentSpeedId -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getCurrentSpeedId_changed()" class="hiddenlink" target="rightframe">getCurrentSpeedId
+()</A></nobr><br>
+<!-- Method getCurrentTimeLong -->
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.getCurrentTimeLong_added()" class="hiddenlink" target="rightframe"><b>getCurrentTimeLong</b>
+()</A></nobr><br>
+<!-- Method getDefaultDimLayer -->
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.getDefaultDimLayer_changed()" class="hiddenlink" target="rightframe">getDefaultDimLayer
+()</A></nobr><br>
+<!-- Method getDescription -->
+<nobr><A HREF="android.support.v17.leanback.widget.HeaderItem.html#android.support.v17.leanback.widget.HeaderItem.getDescription_added()" class="hiddenlink" target="rightframe"><b>getDescription</b>
+()</A></nobr><br>
+<!-- Method getDimLayer -->
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.getDimLayer_changed()" class="hiddenlink" target="rightframe">getDimLayer
+()</A></nobr><br>
+<!-- Method getDuration -->
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.getDuration_changed()" class="hiddenlink" target="rightframe">getDuration
+()</A></nobr><br>
+<!-- Method getEventHandler -->
+<i>getEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.getEventHandler_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+<!-- Method getEventHandler -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.getEventHandler_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<!-- Method getExtraVisibility -->
+<nobr><A HREF="android.support.v17.leanback.widget.BaseCardView.html#android.support.v17.leanback.widget.BaseCardView.getExtraVisibility_changed()" class="hiddenlink" target="rightframe">getExtraVisibility
+()</A></nobr><br>
+<!-- Method getFastForwardSpeeds -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getFastForwardSpeeds_changed()" class="hiddenlink" target="rightframe">getFastForwardSpeeds
+()</A></nobr><br>
+<!-- Method getFragment -->
+<i>getFragment</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.getFragment_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method getFragment -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getFragment_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Method getGravity -->
+<nobr><A HREF="android.support.v7.widget.LinearLayoutCompat.html#android.support.v7.widget.LinearLayoutCompat.getGravity_added()" class="hiddenlink" target="rightframe"><b>getGravity</b>
+()</A></nobr><br>
+<!-- Method getInputEventHandler -->
+<i>getInputEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.getInputEventHandler_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+<!-- Method getInputEventHandler -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.getInputEventHandler_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<!-- Method getMainFragment -->
+<i>getMainFragment</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseFragment.html#android.support.v17.leanback.app.BrowseFragment.getMainFragment_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseFragment
+</A></nobr><br>
+<!-- Method getMainFragment -->
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.html#android.support.v17.leanback.app.BrowseSupportFragment.getMainFragment_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseSupportFragment
+</A></nobr><br>
+<!-- Method getMediaArt -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaArt_changed()" class="hiddenlink" target="rightframe">getMediaArt
+()</A></nobr><br>
+<!-- Method getMediaController -->
+<nobr><A HREF="android.support.v4.media.session.MediaControllerCompat.html#android.support.v4.media.session.MediaControllerCompat.getMediaController_added(android.app.Activity)" class="hiddenlink" target="rightframe"><b>getMediaController</b>
+(<code>Activity</code>)</A></nobr><br>
+<!-- Method getMediaDuration -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaDuration_changed()" class="hiddenlink" target="rightframe">getMediaDuration
+()</A></nobr><br>
+<!-- Method getMediaSubtitle -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaSubtitle_changed()" class="hiddenlink" target="rightframe">getMediaSubtitle
+()</A></nobr><br>
+<!-- Method getMediaTitle -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaTitle_changed()" class="hiddenlink" target="rightframe">getMediaTitle
+()</A></nobr><br>
+<!-- Method getOnItemViewClickedListener -->
+<i>getOnItemViewClickedListener</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.getOnItemViewClickedListener_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method getOnItemViewClickedListener -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getOnItemViewClickedListener_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Method getPreferenceComparisonCallback -->
+<nobr><A HREF="android.support.v7.preference.PreferenceManager.html#android.support.v7.preference.PreferenceManager.getPreferenceComparisonCallback_added()" class="hiddenlink" target="rightframe"><b>getPreferenceComparisonCallback</b>
+()</A></nobr><br>
+<!-- Method getRecycledViewCount -->
+<nobr><A HREF="android.support.v7.widget.RecyclerView.RecycledViewPool.html#android.support.v7.widget.RecyclerView.RecycledViewPool.getRecycledViewCount_added(int)" class="hiddenlink" target="rightframe"><b>getRecycledViewCount</b>
+(<code>int</code>)</A></nobr><br>
+<!-- Method getRewindSpeeds -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getRewindSpeeds_changed()" class="hiddenlink" target="rightframe">getRewindSpeeds
+()</A></nobr><br>
+<!-- Method getSelectedItem -->
+<nobr><A HREF="android.support.v17.leanback.widget.RowPresenter.ViewHolder.html#android.support.v17.leanback.widget.RowPresenter.ViewHolder.getSelectedItem_added()" class="hiddenlink" target="rightframe"><b>getSelectedItem</b>
+()</A></nobr><br>
+<!-- Method getSelectedItemViewHolder -->
+<nobr><A HREF="android.support.v17.leanback.widget.RowPresenter.ViewHolder.html#android.support.v17.leanback.widget.RowPresenter.ViewHolder.getSelectedItemViewHolder_added()" class="hiddenlink" target="rightframe"><b>getSelectedItemViewHolder</b>
+()</A></nobr><br>
+<!-- Method getSelectedRowViewHolder -->
+<i>getSelectedRowViewHolder</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseFragment.html#android.support.v17.leanback.app.BrowseFragment.getSelectedRowViewHolder_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseFragment
+</A></nobr><br>
+<!-- Method getSelectedRowViewHolder -->
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.html#android.support.v17.leanback.app.BrowseSupportFragment.getSelectedRowViewHolder_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseSupportFragment
+</A></nobr><br>
+<!-- Method getSupportedActions -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getSupportedActions_changed()" class="hiddenlink" target="rightframe">getSupportedActions
+()</A></nobr><br>
+<!-- Method getSupportMediaController -->
+<nobr><A HREF="android.support.v4.app.FragmentActivity.html#android.support.v4.app.FragmentActivity.getSupportMediaController_changed()" class="hiddenlink" target="rightframe">getSupportMediaController
+()</A></nobr><br>
+<!-- Method getTotalTimeLong -->
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.getTotalTimeLong_added()" class="hiddenlink" target="rightframe"><b>getTotalTimeLong</b>
+()</A></nobr><br>
+<!-- Method getUpdatePeriod -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getUpdatePeriod_changed()" class="hiddenlink" target="rightframe">getUpdatePeriod
+()</A></nobr><br>
+<!-- Method getVerticalGridView -->
+<i>getVerticalGridView</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BaseRowFragment.html#android.support.v17.leanback.app.BaseRowFragment.getVerticalGridView_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BaseRowFragment
+</A></nobr><br>
+<!-- Method getVerticalGridView -->
+ <nobr><A HREF="android.support.v17.leanback.app.BaseRowSupportFragment.html#android.support.v17.leanback.app.BaseRowSupportFragment.getVerticalGridView_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BaseRowSupportFragment
+</A></nobr><br>
+<!-- Method getView -->
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.getView_changed()" class="hiddenlink" target="rightframe">getView
+()</A></nobr><br>
+<!-- Class GuidedActionsStylist -->
+<A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html" class="hiddenlink" target="rightframe">GuidedActionsStylist</A><br>
+<!-- Class GuidedStepFragment -->
+<A HREF="android.support.v17.leanback.app.GuidedStepFragment.html" class="hiddenlink" target="rightframe">GuidedStepFragment</A><br>
+<!-- Class GuidedStepSupportFragment -->
+<A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html" class="hiddenlink" target="rightframe">GuidedStepSupportFragment</A><br>
+<!-- Method handleInputEvent -->
+<A NAME="H"></A>
+<br><font size="+2">H</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>handleInputEvent</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.html#android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.handleInputEvent_removed(android.view.InputEvent)" class="hiddenlink" target="rightframe">type <strike>
+(<code>InputEvent</code>)</strike> in android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler
+</A></nobr><br>
+<!-- Method handleInputEvent -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.handleInputEvent_removed(android.view.InputEvent)" class="hiddenlink" target="rightframe">type <strike>
+(<code>InputEvent</code>)</strike> in android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler
+</A></nobr><br>
+<!-- Method hasValidMedia -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.hasValidMedia_changed()" class="hiddenlink" target="rightframe">hasValidMedia
+()</A></nobr><br>
+<!-- Class HeaderItem -->
+<A HREF="android.support.v17.leanback.widget.HeaderItem.html" class="hiddenlink" target="rightframe">HeaderItem</A><br>
+<!-- Method isAtLeastO -->
+<A NAME="I"></A>
+<br><font size="+2">I</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.os.BuildCompat.html#android.support.v4.os.BuildCompat.isAtLeastO_added()" class="hiddenlink" target="rightframe"><b>isAtLeastO</b>
+()</A></nobr><br>
+<!-- Method isAutoReleaseOnStop -->
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.isAutoReleaseOnStop_added()" class="hiddenlink" target="rightframe"><b>isAutoReleaseOnStop</b>
+()</A></nobr><br>
+<!-- Method isBackKeyToCollapseActivatorView -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.isBackKeyToCollapseActivatorView_added()" class="hiddenlink" target="rightframe"><b>isBackKeyToCollapseActivatorView</b>
+()</A></nobr><br>
+<!-- Method isBackKeyToCollapseSubActions -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.isBackKeyToCollapseSubActions_added()" class="hiddenlink" target="rightframe"><b>isBackKeyToCollapseSubActions</b>
+()</A></nobr><br>
+<!-- Method isBluetooth -->
+<nobr><A HREF="android.support.v7.media.MediaRouter.RouteInfo.html#android.support.v7.media.MediaRouter.RouteInfo.isBluetooth_added()" class="hiddenlink" target="rightframe"><b>isBluetooth</b>
+()</A></nobr><br>
+<!-- Method isDeviceSpeaker -->
+<nobr><A HREF="android.support.v7.media.MediaRouter.RouteInfo.html#android.support.v7.media.MediaRouter.RouteInfo.isDeviceSpeaker_added()" class="hiddenlink" target="rightframe"><b>isDeviceSpeaker</b>
+()</A></nobr><br>
+<!-- Method isExpanded -->
+<i>isExpanded</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html#android.support.v17.leanback.app.GuidedStepFragment.isExpanded_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.GuidedStepFragment
+</A></nobr><br>
+<!-- Method isExpanded -->
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html#android.support.v17.leanback.app.GuidedStepSupportFragment.isExpanded_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.GuidedStepSupportFragment
+</A></nobr><br>
+<!-- Method isExpanded -->
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.isExpanded_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<!-- Method isFadingEnabled -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.isFadingEnabled_changed()" class="hiddenlink" target="rightframe">isFadingEnabled
+()</A></nobr><br>
+<!-- Method isMediaPlaying -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.isMediaPlaying_changed()" class="hiddenlink" target="rightframe">isMediaPlaying
+()</A></nobr><br>
+<!-- Method isShown -->
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.isShown_changed()" class="hiddenlink" target="rightframe">isShown
+()</A></nobr><br>
+<!-- Method isShownOrQueued -->
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.isShownOrQueued_changed()" class="hiddenlink" target="rightframe">isShownOrQueued
+()</A></nobr><br>
+<!-- Method isVirtual -->
+<nobr><A HREF="android.support.v4.provider.DocumentFile.html#android.support.v4.provider.DocumentFile.isVirtual_added()" class="hiddenlink" target="rightframe"><b>isVirtual</b>
+()</A></nobr><br>
+<!-- Class LeanbackPreferenceFragment -->
+<A NAME="L"></A>
+<br><font size="+2">L</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.preference.LeanbackPreferenceFragment.html" class="hiddenlink" target="rightframe">LeanbackPreferenceFragment</A><br>
+<!-- Class LinearLayoutCompat -->
+<A HREF="android.support.v7.widget.LinearLayoutCompat.html" class="hiddenlink" target="rightframe">LinearLayoutCompat</A><br>
+<!-- Class MediaControllerCompat -->
+<A NAME="M"></A>
+<br><font size="+2">M</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.media.session.MediaControllerCompat.html" class="hiddenlink" target="rightframe">MediaControllerCompat</A><br>
+<!-- Class MediaControllerGlue -->
+<i>MediaControllerGlue</i><br>
+ <A HREF="android.support.v17.leanback.app.MediaControllerGlue.html" class="hiddenlink" target="rightframe">android.support.v17.leanback.app</A><br>
+<!-- Constructor MediaControllerGlue -->
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.ctor_added(android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])" class="hiddenlink" target="rightframe"><b>MediaControllerGlue</b>
+(<code>Context, PlaybackGlueHost, int[], int[]</code>)</A></nobr> constructor<br>
+<!-- Constructor MediaControllerGlue -->
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[])" class="hiddenlink" target="rightframe">MediaControllerGlue
+(<code>Context, PlaybackOverlayFragment, int[]</code>)</A></nobr> constructor<br>
+<!-- Constructor MediaControllerGlue -->
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[])" class="hiddenlink" target="rightframe">MediaControllerGlue
+(<code>Context, PlaybackOverlayFragment, int[], int[]</code>)</A></nobr> constructor<br>
+<!-- Class MediaRouteChooserDialog -->
+<A HREF="android.support.v7.app.MediaRouteChooserDialog.html" class="hiddenlink" target="rightframe">MediaRouteChooserDialog</A><br>
+<!-- Class MediaRouter -->
+<A HREF="android.support.v7.media.MediaRouter.html" class="hiddenlink" target="rightframe">MediaRouter</A><br>
+<!-- Class MediaRouter.RouteInfo -->
+<A HREF="android.support.v7.media.MediaRouter.RouteInfo.html" class="hiddenlink" target="rightframe">MediaRouter.RouteInfo</A><br>
+<!-- Method notifyItemRangeChanged -->
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.widget.ObjectAdapter.html#android.support.v17.leanback.widget.ObjectAdapter.notifyItemRangeChanged_changed(int, int)" class="hiddenlink" target="rightframe">notifyItemRangeChanged
+(<code>int, int</code>)</A></nobr><br>
+<!-- Class ObjectAdapter -->
+<A NAME="O"></A>
+<br><font size="+2">O</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.widget.ObjectAdapter.html" class="hiddenlink" target="rightframe">ObjectAdapter</A><br>
+<!-- Method onActionClicked -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onActionClicked_changed(android.support.v17.leanback.widget.Action)" class="hiddenlink" target="rightframe">onActionClicked
+(<code>Action</code>)</A></nobr><br>
+<!-- Method onChildViewHolderSelectedAndPositioned -->
+<nobr><A HREF="android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.html#android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.onChildViewHolderSelectedAndPositioned_added(android.support.v7.widget.RecyclerView, android.support.v7.widget.RecyclerView.ViewHolder, int, int)" class="hiddenlink" target="rightframe"><b>onChildViewHolderSelectedAndPositioned</b>
+(<code>RecyclerView, ViewHolder, int, int</code>)</A></nobr><br>
+<!-- Class OnChildViewHolderSelectedListener -->
+<A HREF="android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.html" class="hiddenlink" target="rightframe">OnChildViewHolderSelectedListener</A><br>
+<!-- Method onEditingModeChange -->
+<i>onEditingModeChange</i><br>
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.onEditingModeChange_added(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>ViewHolder, boolean, boolean</code>)</b> in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<!-- Method onEditingModeChange -->
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.onEditingModeChange_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">type
+(<code>ViewHolder, GuidedAction, boolean</code>) in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<!-- Method onKey -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onKey_changed(android.view.View, int, android.view.KeyEvent)" class="hiddenlink" target="rightframe">onKey
+(<code>View, int, KeyEvent</code>)</A></nobr><br>
+<!-- Method onMetadataChanged -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onMetadataChanged_changed()" class="hiddenlink" target="rightframe">onMetadataChanged
+()</A></nobr><br>
+<!-- Method onRowChanged -->
+<i>onRowChanged</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.onRowChanged_changed(android.support.v17.leanback.widget.PlaybackControlsRow)" class="hiddenlink" target="rightframe">type
+(<code>PlaybackControlsRow</code>) in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method onRowChanged -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onRowChanged_changed(android.support.v17.leanback.widget.PlaybackControlsRow)" class="hiddenlink" target="rightframe">type
+(<code>PlaybackControlsRow</code>) in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Method onStateChanged -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onStateChanged_changed()" class="hiddenlink" target="rightframe">onStateChanged
+()</A></nobr><br>
+<!-- Class PagerSnapHelper -->
+<A NAME="P"></A>
+<br><font size="+2">P</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#PagerSnapHelper" class="hiddenlink" target="rightframe"><b>PagerSnapHelper</b></A><br>
+<!-- Method pausePlayback -->
+<i>pausePlayback</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.pausePlayback_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+<!-- Method pausePlayback -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.pausePlayback_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method pausePlayback -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.pausePlayback_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Class PlaybackControlGlue -->
+<i>PlaybackControlGlue</i><br>
+ <A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html" class="hiddenlink" target="rightframe">android.support.v17.leanback.app</A><br>
+<!-- Constructor PlaybackControlGlue -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.ctor_added(android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])" class="hiddenlink" target="rightframe"><b>PlaybackControlGlue</b>
+(<code>Context, PlaybackGlueHost, int[], int[]</code>)</A></nobr> constructor<br>
+<!-- Constructor PlaybackControlGlue -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[])" class="hiddenlink" target="rightframe">PlaybackControlGlue
+(<code>Context, PlaybackOverlayFragment, int[]</code>)</A></nobr> constructor<br>
+<!-- Constructor PlaybackControlGlue -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[])" class="hiddenlink" target="rightframe">PlaybackControlGlue
+(<code>Context, PlaybackOverlayFragment, int[], int[]</code>)</A></nobr> constructor<br>
+<!-- Class PlaybackControlGlue.InputEventHandler -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackControlGlue.InputEventHandler" class="hiddenlink" target="rightframe"><b><i>PlaybackControlGlue.InputEventHandler</i></b></A><br>
+<!-- Class PlaybackControlsRow -->
+<A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html" class="hiddenlink" target="rightframe">PlaybackControlsRow</A><br>
+<!-- Class PlaybackControlsRowPresenter -->
+<A HREF="android.support.v17.leanback.widget.PlaybackControlsRowPresenter.html" class="hiddenlink" target="rightframe">PlaybackControlsRowPresenter</A><br>
+<!-- Class PlaybackControlsRowPresenter.ViewHolder -->
+<A HREF="android.support.v17.leanback.widget.PlaybackControlsRowPresenter.ViewHolder.html" class="hiddenlink" target="rightframe">PlaybackControlsRowPresenter.ViewHolder</A><br>
+<!-- Class PlaybackControlSupportGlue -->
+<A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html" class="hiddenlink" target="rightframe">PlaybackControlSupportGlue</A><br>
+<!-- Class PlaybackFragment -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackFragment" class="hiddenlink" target="rightframe"><b>PlaybackFragment</b></A><br>
+<!-- Class PlaybackFragment.OnFadeCompleteListener -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackFragment.OnFadeCompleteListener" class="hiddenlink" target="rightframe"><b>PlaybackFragment.OnFadeCompleteListener</b></A><br>
+<!-- Class PlaybackFragmentGlueHost -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackFragmentGlueHost" class="hiddenlink" target="rightframe"><b>PlaybackFragmentGlueHost</b></A><br>
+<!-- Class PlaybackGlue -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue" class="hiddenlink" target="rightframe"><b>PlaybackGlue</b></A><br>
+<!-- Class PlaybackGlue.HostLifecycleCallback -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue.HostLifecycleCallback" class="hiddenlink" target="rightframe"><b>PlaybackGlue.HostLifecycleCallback</b></A><br>
+<!-- Class PlaybackGlue.PlaybackGlueHost -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue.PlaybackGlueHost" class="hiddenlink" target="rightframe"><b>PlaybackGlue.PlaybackGlueHost</b></A><br>
+<!-- Class PlaybackGlue.PlayerCallback -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue.PlayerCallback" class="hiddenlink" target="rightframe"><b>PlaybackGlue.PlayerCallback</b></A><br>
+<!-- Class PlaybackOverlayFragment -->
+<A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html" class="hiddenlink" target="rightframe">PlaybackOverlayFragment</A><br>
+<!-- Class PlaybackOverlayFragment.InputEventHandler -->
+<A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.html" class="hiddenlink" target="rightframe"><i>PlaybackOverlayFragment.InputEventHandler</i></A><br>
+<!-- Class PlaybackOverlaySupportFragment -->
+<A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html" class="hiddenlink" target="rightframe">PlaybackOverlaySupportFragment</A><br>
+<!-- Class PlaybackOverlaySupportFragment.InputEventHandler -->
+<A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.html" class="hiddenlink" target="rightframe"><i>PlaybackOverlaySupportFragment.InputEventHandler</i></A><br>
+<!-- Class PlaybackRowPresenter -->
+<A HREF="pkg_android.support.v17.leanback.widget.html#PlaybackRowPresenter" class="hiddenlink" target="rightframe"><b>PlaybackRowPresenter</b></A><br>
+<!-- Class PlaybackRowPresenter.ViewHolder -->
+<A HREF="pkg_android.support.v17.leanback.widget.html#PlaybackRowPresenter.ViewHolder" class="hiddenlink" target="rightframe"><b>PlaybackRowPresenter.ViewHolder</b></A><br>
+<!-- Class PlaybackSupportFragment -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackSupportFragment" class="hiddenlink" target="rightframe"><b>PlaybackSupportFragment</b></A><br>
+<!-- Class PlaybackSupportFragment.OnFadeCompleteListener -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackSupportFragment.OnFadeCompleteListener" class="hiddenlink" target="rightframe"><b>PlaybackSupportFragment.OnFadeCompleteListener</b></A><br>
+<!-- Class PlaybackSupportFragmentGlueHost -->
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackSupportFragmentGlueHost" class="hiddenlink" target="rightframe"><b>PlaybackSupportFragmentGlueHost</b></A><br>
+<!-- Method postponeEnterTransition -->
+<nobr><A HREF="android.support.v4.app.Fragment.html#android.support.v4.app.Fragment.postponeEnterTransition_added()" class="hiddenlink" target="rightframe"><b>postponeEnterTransition</b>
+()</A></nobr><br>
+<!-- Class PreferenceManager -->
+<A HREF="android.support.v7.preference.PreferenceManager.html" class="hiddenlink" target="rightframe">PreferenceManager</A><br>
+<!-- Class PreferenceManager.PreferenceComparisonCallback -->
+<A HREF="pkg_android.support.v7.preference.html#PreferenceManager.PreferenceComparisonCallback" class="hiddenlink" target="rightframe"><b>PreferenceManager.PreferenceComparisonCallback</b></A><br>
+<!-- Class PreferenceManager.SimplePreferenceComparisonCallback -->
+<A HREF="pkg_android.support.v7.preference.html#PreferenceManager.SimplePreferenceComparisonCallback" class="hiddenlink" target="rightframe"><b>PreferenceManager.SimplePreferenceComparisonCallback</b></A><br>
+<!-- Class RecyclerView -->
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v7.widget.RecyclerView.html" class="hiddenlink" target="rightframe">RecyclerView</A><br>
+<!-- Class RecyclerView.RecycledViewPool -->
+<A HREF="android.support.v7.widget.RecyclerView.RecycledViewPool.html" class="hiddenlink" target="rightframe">RecyclerView.RecycledViewPool</A><br>
+<!-- Method registerFragmentLifecycleCallbacks -->
+<nobr><A HREF="android.support.v4.app.FragmentManager.html#android.support.v4.app.FragmentManager.registerFragmentLifecycleCallbacks_added(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks, boolean)" class="hiddenlink" target="rightframe"><b>registerFragmentLifecycleCallbacks</b>
+(<code>FragmentLifecycleCallbacks, boolean</code>)</A></nobr><br>
+<!-- Class RowPresenter.ViewHolder -->
+<A HREF="android.support.v17.leanback.widget.RowPresenter.ViewHolder.html" class="hiddenlink" target="rightframe">RowPresenter.ViewHolder</A><br>
+<!-- Class RowsFragment -->
+<A HREF="android.support.v17.leanback.app.RowsFragment.html" class="hiddenlink" target="rightframe">RowsFragment</A><br>
+<!-- Class RowsSupportFragment -->
+<A HREF="android.support.v17.leanback.app.RowsSupportFragment.html" class="hiddenlink" target="rightframe">RowsSupportFragment</A><br>
+<!-- Class SearchBar -->
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.widget.SearchBar.html" class="hiddenlink" target="rightframe">SearchBar</A><br>
+<!-- Class SearchFragment -->
+<A HREF="android.support.v17.leanback.app.SearchFragment.html" class="hiddenlink" target="rightframe">SearchFragment</A><br>
+<!-- Class SearchSupportFragment -->
+<A HREF="android.support.v17.leanback.app.SearchSupportFragment.html" class="hiddenlink" target="rightframe">SearchSupportFragment</A><br>
+<!-- Class SeekBarPreference -->
+<A HREF="pkg_android.support.v7.preference.html#SeekBarPreference" class="hiddenlink" target="rightframe"><b>SeekBarPreference</b></A><br>
+<!-- Method setAllowOptimization -->
+<nobr><A HREF="android.support.v4.app.FragmentTransaction.html#android.support.v4.app.FragmentTransaction.setAllowOptimization_added(boolean)" class="hiddenlink" target="rightframe"><b>setAllowOptimization</b>
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method setAutoReleaseOnStop -->
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.setAutoReleaseOnStop_added(boolean)" class="hiddenlink" target="rightframe"><b>setAutoReleaseOnStop</b>
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method setBackKeyToCollapseActivatorView -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setBackKeyToCollapseActivatorView_added(boolean)" class="hiddenlink" target="rightframe"><b>setBackKeyToCollapseActivatorView</b>
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method setBackKeyToCollapseSubActions -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setBackKeyToCollapseSubActions_added(boolean)" class="hiddenlink" target="rightframe"><b>setBackKeyToCollapseSubActions</b>
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method setBufferedProgressLong -->
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.setBufferedProgressLong_added(long)" class="hiddenlink" target="rightframe"><b>setBufferedProgressLong</b>
+(<code>long</code>)</A></nobr><br>
+<!-- Method setCallback -->
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.setCallback_changed(android.support.design.widget.Snackbar.Callback)" class="hiddenlink" target="rightframe">setCallback
+(<code>Callback</code>)</A></nobr><br>
+<!-- Method setControlsRow -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.setControlsRow_changed(android.support.v17.leanback.widget.PlaybackControlsRow)" class="hiddenlink" target="rightframe">setControlsRow
+(<code>PlaybackControlsRow</code>)</A></nobr><br>
+<!-- Method setCurrentTimeLong -->
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.setCurrentTimeLong_added(long)" class="hiddenlink" target="rightframe"><b>setCurrentTimeLong</b>
+(<code>long</code>)</A></nobr><br>
+<!-- Method setDescription -->
+<nobr><A HREF="android.support.v17.leanback.widget.HeaderItem.html#android.support.v17.leanback.widget.HeaderItem.setDescription_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>setDescription</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<!-- Method setDimLayer -->
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.setDimLayer_changed(android.graphics.drawable.Drawable)" class="hiddenlink" target="rightframe">setDimLayer
+(<code>Drawable</code>)</A></nobr><br>
+<!-- Method setDuration -->
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.setDuration_changed(int)" class="hiddenlink" target="rightframe">setDuration
+(<code>int</code>)</A></nobr><br>
+<!-- Method setEditingMode -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setEditingMode_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">setEditingMode
+(<code>ViewHolder, GuidedAction, boolean</code>)</A></nobr><br>
+<!-- Method setErrorTextAppearance -->
+<nobr><A HREF="android.support.design.widget.TextInputLayout.html#android.support.design.widget.TextInputLayout.setErrorTextAppearance_added(int)" class="hiddenlink" target="rightframe"><b>setErrorTextAppearance</b>
+(<code>int</code>)</A></nobr><br>
+<!-- Method setEventHandler -->
+<i>setEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.setEventHandler_added(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)" class="hiddenlink" target="rightframe">type <b>
+(<code>InputEventHandler</code>)</b> in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+<!-- Method setEventHandler -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.setEventHandler_added(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)" class="hiddenlink" target="rightframe">type <b>
+(<code>InputEventHandler</code>)</b> in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<!-- Method setExpandedViewHolder -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setExpandedViewHolder_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder)" class="hiddenlink" target="rightframe">setExpandedViewHolder
+(<code>ViewHolder</code>)</A></nobr><br>
+<!-- Method setExtraVisibility -->
+<nobr><A HREF="android.support.v17.leanback.widget.BaseCardView.html#android.support.v17.leanback.widget.BaseCardView.setExtraVisibility_changed(int)" class="hiddenlink" target="rightframe">setExtraVisibility
+(<code>int</code>)</A></nobr><br>
+<!-- Method setFadingEnabled -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.setFadingEnabled_changed(boolean)" class="hiddenlink" target="rightframe">setFadingEnabled
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method setInputEventHandler -->
+<i>setInputEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.setInputEventHandler_changed(android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler)" class="hiddenlink" target="rightframe">type
+(<code>InputEventHandler</code>) in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+<!-- Method setInputEventHandler -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.setInputEventHandler_changed(android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler)" class="hiddenlink" target="rightframe">type
+(<code>InputEventHandler</code>) in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<!-- Method setListeningOrbColors -->
+<nobr><A HREF="android.support.v17.leanback.widget.SpeechOrbView.html#android.support.v17.leanback.widget.SpeechOrbView.setListeningOrbColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe"><b>setListeningOrbColors</b>
+(<code>Colors</code>)</A></nobr><br>
+<!-- Method setMediaController -->
+<nobr><A HREF="android.support.v4.media.session.MediaControllerCompat.html#android.support.v4.media.session.MediaControllerCompat.setMediaController_added(android.app.Activity, android.support.v4.media.session.MediaControllerCompat)" class="hiddenlink" target="rightframe"><b>setMediaController</b>
+(<code>Activity, MediaControllerCompat</code>)</A></nobr><br>
+<!-- Method setNotListeningOrbColors -->
+<nobr><A HREF="android.support.v17.leanback.widget.SpeechOrbView.html#android.support.v17.leanback.widget.SpeechOrbView.setNotListeningOrbColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe"><b>setNotListeningOrbColors</b>
+(<code>Colors</code>)</A></nobr><br>
+<!-- Method setOnDispatchKeyListener -->
+<nobr><A HREF="android.support.v17.leanback.widget.BrowseFrameLayout.html#android.support.v17.leanback.widget.BrowseFrameLayout.setOnDispatchKeyListener_added(android.view.View.OnKeyListener)" class="hiddenlink" target="rightframe"><b>setOnDispatchKeyListener</b>
+(<code>OnKeyListener</code>)</A></nobr><br>
+<!-- Method setOnItemViewClickedListener -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.setOnItemViewClickedListener_changed(android.support.v17.leanback.widget.OnItemViewClickedListener)" class="hiddenlink" target="rightframe">setOnItemViewClickedListener
+(<code>OnItemViewClickedListener</code>)</A></nobr><br>
+<!-- Method setPreferenceComparisonCallback -->
+<nobr><A HREF="android.support.v7.preference.PreferenceManager.html#android.support.v7.preference.PreferenceManager.setPreferenceComparisonCallback_added(android.support.v7.preference.PreferenceManager.PreferenceComparisonCallback)" class="hiddenlink" target="rightframe"><b>setPreferenceComparisonCallback</b>
+(<code>PreferenceComparisonCallback</code>)</A></nobr><br>
+<!-- Method setSearchAffordanceColors -->
+<i>setSearchAffordanceColors</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.SearchFragment.html#android.support.v17.leanback.app.SearchFragment.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchFragment
+</A></nobr><br>
+<!-- Method setSearchAffordanceColors -->
+ <nobr><A HREF="android.support.v17.leanback.app.SearchSupportFragment.html#android.support.v17.leanback.app.SearchSupportFragment.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchSupportFragment
+</A></nobr><br>
+<!-- Method setSearchAffordanceColors -->
+ <nobr><A HREF="android.support.v17.leanback.widget.SearchBar.html#android.support.v17.leanback.widget.SearchBar.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.widget.SearchBar
+</A></nobr><br>
+<!-- Method setSearchAffordanceColorsInListening -->
+<i>setSearchAffordanceColorsInListening</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.SearchFragment.html#android.support.v17.leanback.app.SearchFragment.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchFragment
+</A></nobr><br>
+<!-- Method setSearchAffordanceColorsInListening -->
+ <nobr><A HREF="android.support.v17.leanback.app.SearchSupportFragment.html#android.support.v17.leanback.app.SearchSupportFragment.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchSupportFragment
+</A></nobr><br>
+<!-- Method setSearchAffordanceColorsInListening -->
+ <nobr><A HREF="android.support.v17.leanback.widget.SearchBar.html#android.support.v17.leanback.widget.SearchBar.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.widget.SearchBar
+</A></nobr><br>
+<!-- Method setSupportMediaController -->
+<nobr><A HREF="android.support.v4.app.FragmentActivity.html#android.support.v4.app.FragmentActivity.setSupportMediaController_changed(android.support.v4.media.session.MediaControllerCompat)" class="hiddenlink" target="rightframe">setSupportMediaController
+(<code>MediaControllerCompat</code>)</A></nobr><br>
+<!-- Method setTitle -->
+<nobr><A HREF="android.support.v17.preference.LeanbackPreferenceFragment.html#android.support.v17.preference.LeanbackPreferenceFragment.setTitle_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>setTitle</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<!-- Method setTotalTimeLong -->
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.setTotalTimeLong_added(long)" class="hiddenlink" target="rightframe"><b>setTotalTimeLong</b>
+(<code>long</code>)</A></nobr><br>
+<!-- Method show -->
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.show_changed()" class="hiddenlink" target="rightframe">show
+()</A></nobr><br>
+<!-- Method skipToNext -->
+<i>skipToNext</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.skipToNext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+<!-- Method skipToNext -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.skipToNext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method skipToNext -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.skipToNext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Method skipToPrevious -->
+<i>skipToPrevious</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.skipToPrevious_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+<!-- Method skipToPrevious -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.skipToPrevious_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method skipToPrevious -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.skipToPrevious_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Method smoothScrollBy -->
+<nobr><A HREF="android.support.v7.widget.RecyclerView.html#android.support.v7.widget.RecyclerView.smoothScrollBy_added(int, int, android.view.animation.Interpolator)" class="hiddenlink" target="rightframe"><b>smoothScrollBy</b>
+(<code>int, int, Interpolator</code>)</A></nobr><br>
+<!-- Class Snackbar -->
+<A HREF="android.support.design.widget.Snackbar.html" class="hiddenlink" target="rightframe">Snackbar</A><br>
+<!-- Class Snackbar.Callback -->
+<A HREF="android.support.design.widget.Snackbar.Callback.html" class="hiddenlink" target="rightframe">Snackbar.Callback</A><br>
+<!-- Class SnapHelper -->
+<A HREF="android.support.v7.widget.SnapHelper.html" class="hiddenlink" target="rightframe">SnapHelper</A><br>
+<!-- Class SpeechOrbView -->
+<A HREF="android.support.v17.leanback.widget.SpeechOrbView.html" class="hiddenlink" target="rightframe">SpeechOrbView</A><br>
+<!-- Method startExpandedTransition -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.startExpandedTransition_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder)" class="hiddenlink" target="rightframe">startExpandedTransition
+(<code>ViewHolder</code>)</A></nobr><br>
+<!-- Method startPlayback -->
+<i>startPlayback</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.startPlayback_changed(int)" class="hiddenlink" target="rightframe">type
+(<code>int</code>) in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+<!-- Method startPlayback -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.startPlayback_changed(int)" class="hiddenlink" target="rightframe">type
+(<code>int</code>) in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method startPlayback -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.startPlayback_changed(int)" class="hiddenlink" target="rightframe">type
+(<code>int</code>) in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Method startPostponedEnterTransition -->
+<nobr><A HREF="android.support.v4.app.Fragment.html#android.support.v4.app.Fragment.startPostponedEnterTransition_added()" class="hiddenlink" target="rightframe"><b>startPostponedEnterTransition</b>
+()</A></nobr><br>
+<!-- Class SurfaceHolderGlueHost -->
+<A HREF="pkg_android.support.v17.leanback.app.html#SurfaceHolderGlueHost" class="hiddenlink" target="rightframe"><b><i>SurfaceHolderGlueHost</i></b></A><br>
+<!-- Class TextInputLayout -->
+<A NAME="T"></A>
+<br><font size="+2">T</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.design.widget.TextInputLayout.html" class="hiddenlink" target="rightframe">TextInputLayout</A><br>
+<!-- Method unregisterFragmentLifecycleCallbacks -->
+<A NAME="U"></A>
+<br><font size="+2">U</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.FragmentManager.html#android.support.v4.app.FragmentManager.unregisterFragmentLifecycleCallbacks_added(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks)" class="hiddenlink" target="rightframe"><b>unregisterFragmentLifecycleCallbacks</b>
+(<code>FragmentLifecycleCallbacks</code>)</A></nobr><br>
+<!-- Method updateProgress -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.updateProgress_changed()" class="hiddenlink" target="rightframe">updateProgress
+()</A></nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/alldiffs_index_changes.html b/docs/html/sdk/support_api_diff/25.1.0/changes/alldiffs_index_changes.html
new file mode 100644
index 0000000..3078b6a
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/alldiffs_index_changes.html
@@ -0,0 +1,804 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a>
+ <br>
+<A HREF="alldiffs_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<!-- Package android.support.design.widget -->
+<A NAME="A"></A>
+<A HREF="pkg_android.support.design.widget.html" class="hiddenlink" target="rightframe">android.support.design.widget</A><br>
+<!-- Package android.support.graphics.drawable -->
+<A HREF="pkg_android.support.graphics.drawable.html" class="hiddenlink" target="rightframe">android.support.graphics.drawable</A><br>
+<!-- Package android.support.v17.leanback.app -->
+<A HREF="pkg_android.support.v17.leanback.app.html" class="hiddenlink" target="rightframe">android.support.v17.leanback.app</A><br>
+<!-- Package android.support.v17.leanback.widget -->
+<A HREF="pkg_android.support.v17.leanback.widget.html" class="hiddenlink" target="rightframe">android.support.v17.leanback.widget</A><br>
+<!-- Package android.support.v17.preference -->
+<A HREF="pkg_android.support.v17.preference.html" class="hiddenlink" target="rightframe">android.support.v17.preference</A><br>
+<!-- Package android.support.v4.app -->
+<A HREF="pkg_android.support.v4.app.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<!-- Package android.support.v4.media.session -->
+<A HREF="pkg_android.support.v4.media.session.html" class="hiddenlink" target="rightframe">android.support.v4.media.session</A><br>
+<!-- Package android.support.v4.os -->
+<A HREF="pkg_android.support.v4.os.html" class="hiddenlink" target="rightframe">android.support.v4.os</A><br>
+<!-- Package android.support.v4.provider -->
+<A HREF="pkg_android.support.v4.provider.html" class="hiddenlink" target="rightframe">android.support.v4.provider</A><br>
+<!-- Package android.support.v4.util -->
+<A HREF="pkg_android.support.v4.util.html" class="hiddenlink" target="rightframe">android.support.v4.util</A><br>
+<!-- Package android.support.v7.app -->
+<A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
+<!-- Package android.support.v7.media -->
+<A HREF="pkg_android.support.v7.media.html" class="hiddenlink" target="rightframe">android.support.v7.media</A><br>
+<!-- Package android.support.v7.preference -->
+<A HREF="pkg_android.support.v7.preference.html" class="hiddenlink" target="rightframe">android.support.v7.preference</A><br>
+<!-- Package android.support.v7.widget -->
+<A HREF="pkg_android.support.v7.widget.html" class="hiddenlink" target="rightframe">android.support.v7.widget</A><br>
+<!-- Class BackgroundManager -->
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.app.BackgroundManager.html" class="hiddenlink" target="rightframe">BackgroundManager</A><br>
+<!-- Class BaseCardView -->
+<A HREF="android.support.v17.leanback.widget.BaseCardView.html" class="hiddenlink" target="rightframe">BaseCardView</A><br>
+<!-- Class BaseRowFragment -->
+<A HREF="android.support.v17.leanback.app.BaseRowFragment.html" class="hiddenlink" target="rightframe">BaseRowFragment</A><br>
+<!-- Class BaseRowSupportFragment -->
+<A HREF="android.support.v17.leanback.app.BaseRowSupportFragment.html" class="hiddenlink" target="rightframe">BaseRowSupportFragment</A><br>
+<!-- Class BrowseFragment -->
+<A HREF="android.support.v17.leanback.app.BrowseFragment.html" class="hiddenlink" target="rightframe">BrowseFragment</A><br>
+<!-- Class BrowseFragment.MainFragmentRowsAdapter -->
+<A HREF="android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.html" class="hiddenlink" target="rightframe">BrowseFragment.MainFragmentRowsAdapter</A><br>
+<!-- Class BrowseFrameLayout -->
+<A HREF="android.support.v17.leanback.widget.BrowseFrameLayout.html" class="hiddenlink" target="rightframe">BrowseFrameLayout</A><br>
+<!-- Class BrowseSupportFragment -->
+<A HREF="android.support.v17.leanback.app.BrowseSupportFragment.html" class="hiddenlink" target="rightframe">BrowseSupportFragment</A><br>
+<!-- Class BrowseSupportFragment.MainFragmentRowsAdapter -->
+<A HREF="android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.html" class="hiddenlink" target="rightframe">BrowseSupportFragment.MainFragmentRowsAdapter</A><br>
+<!-- Class BuildCompat -->
+<A HREF="android.support.v4.os.BuildCompat.html" class="hiddenlink" target="rightframe">BuildCompat</A><br>
+<!-- Method createControlsRowAndPresenter -->
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.createControlsRowAndPresenter_changed()" class="hiddenlink" target="rightframe">createControlsRowAndPresenter
+()</A></nobr><br>
+<!-- Method createPrimaryActionsAdapter -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.createPrimaryActionsAdapter_changed(android.support.v17.leanback.widget.PresenterSelector)" class="hiddenlink" target="rightframe">createPrimaryActionsAdapter
+(<code>PresenterSelector</code>)</A></nobr><br>
+<!-- Method dismiss -->
+<A NAME="D"></A>
+<br><font size="+2">D</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.dismiss_changed()" class="hiddenlink" target="rightframe">dismiss
+()</A></nobr><br>
+<!-- Class DocumentFile -->
+<A HREF="android.support.v4.provider.DocumentFile.html" class="hiddenlink" target="rightframe">DocumentFile</A><br>
+<!-- Method enableProgressUpdating -->
+<A NAME="E"></A>
+<br><font size="+2">E</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.enableProgressUpdating_changed(boolean)" class="hiddenlink" target="rightframe">enableProgressUpdating
+(<code>boolean</code>)</A></nobr><br>
+<!-- Class Fragment -->
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.app.Fragment.html" class="hiddenlink" target="rightframe">Fragment</A><br>
+<!-- Class FragmentActivity -->
+<A HREF="android.support.v4.app.FragmentActivity.html" class="hiddenlink" target="rightframe">FragmentActivity</A><br>
+<!-- Class FragmentManager -->
+<A HREF="android.support.v4.app.FragmentManager.html" class="hiddenlink" target="rightframe">FragmentManager</A><br>
+<!-- Class FragmentTransaction -->
+<A HREF="android.support.v4.app.FragmentTransaction.html" class="hiddenlink" target="rightframe">FragmentTransaction</A><br>
+<!-- Method getContext -->
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>getContext</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.getContext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method getContext -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getContext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Method getControlsRow -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getControlsRow_changed()" class="hiddenlink" target="rightframe">getControlsRow
+()</A></nobr><br>
+<!-- Method getCurrentPosition -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getCurrentPosition_changed()" class="hiddenlink" target="rightframe">getCurrentPosition
+()</A></nobr><br>
+<!-- Method getCurrentSpeedId -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getCurrentSpeedId_changed()" class="hiddenlink" target="rightframe">getCurrentSpeedId
+()</A></nobr><br>
+<!-- Method getDefaultDimLayer -->
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.getDefaultDimLayer_changed()" class="hiddenlink" target="rightframe">getDefaultDimLayer
+()</A></nobr><br>
+<!-- Method getDimLayer -->
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.getDimLayer_changed()" class="hiddenlink" target="rightframe">getDimLayer
+()</A></nobr><br>
+<!-- Method getDuration -->
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.getDuration_changed()" class="hiddenlink" target="rightframe">getDuration
+()</A></nobr><br>
+<!-- Method getExtraVisibility -->
+<nobr><A HREF="android.support.v17.leanback.widget.BaseCardView.html#android.support.v17.leanback.widget.BaseCardView.getExtraVisibility_changed()" class="hiddenlink" target="rightframe">getExtraVisibility
+()</A></nobr><br>
+<!-- Method getFastForwardSpeeds -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getFastForwardSpeeds_changed()" class="hiddenlink" target="rightframe">getFastForwardSpeeds
+()</A></nobr><br>
+<!-- Method getFragment -->
+<i>getFragment</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.getFragment_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method getFragment -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getFragment_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Method getInputEventHandler -->
+<i>getInputEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.getInputEventHandler_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+<!-- Method getInputEventHandler -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.getInputEventHandler_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<!-- Method getMediaArt -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaArt_changed()" class="hiddenlink" target="rightframe">getMediaArt
+()</A></nobr><br>
+<!-- Method getMediaDuration -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaDuration_changed()" class="hiddenlink" target="rightframe">getMediaDuration
+()</A></nobr><br>
+<!-- Method getMediaSubtitle -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaSubtitle_changed()" class="hiddenlink" target="rightframe">getMediaSubtitle
+()</A></nobr><br>
+<!-- Method getMediaTitle -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaTitle_changed()" class="hiddenlink" target="rightframe">getMediaTitle
+()</A></nobr><br>
+<!-- Method getOnItemViewClickedListener -->
+<i>getOnItemViewClickedListener</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.getOnItemViewClickedListener_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method getOnItemViewClickedListener -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getOnItemViewClickedListener_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Method getRewindSpeeds -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getRewindSpeeds_changed()" class="hiddenlink" target="rightframe">getRewindSpeeds
+()</A></nobr><br>
+<!-- Method getSupportedActions -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getSupportedActions_changed()" class="hiddenlink" target="rightframe">getSupportedActions
+()</A></nobr><br>
+<!-- Method getSupportMediaController -->
+<nobr><A HREF="android.support.v4.app.FragmentActivity.html#android.support.v4.app.FragmentActivity.getSupportMediaController_changed()" class="hiddenlink" target="rightframe">getSupportMediaController
+()</A></nobr><br>
+<!-- Method getUpdatePeriod -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getUpdatePeriod_changed()" class="hiddenlink" target="rightframe">getUpdatePeriod
+()</A></nobr><br>
+<!-- Method getView -->
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.getView_changed()" class="hiddenlink" target="rightframe">getView
+()</A></nobr><br>
+<!-- Class GuidedActionsStylist -->
+<A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html" class="hiddenlink" target="rightframe">GuidedActionsStylist</A><br>
+<!-- Class GuidedStepFragment -->
+<A HREF="android.support.v17.leanback.app.GuidedStepFragment.html" class="hiddenlink" target="rightframe">GuidedStepFragment</A><br>
+<!-- Class GuidedStepSupportFragment -->
+<A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html" class="hiddenlink" target="rightframe">GuidedStepSupportFragment</A><br>
+<!-- Method hasValidMedia -->
+<A NAME="H"></A>
+<br><font size="+2">H</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.hasValidMedia_changed()" class="hiddenlink" target="rightframe">hasValidMedia
+()</A></nobr><br>
+<!-- Class HeaderItem -->
+<A HREF="android.support.v17.leanback.widget.HeaderItem.html" class="hiddenlink" target="rightframe">HeaderItem</A><br>
+<!-- Method isFadingEnabled -->
+<A NAME="I"></A>
+<br><font size="+2">I</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.isFadingEnabled_changed()" class="hiddenlink" target="rightframe">isFadingEnabled
+()</A></nobr><br>
+<!-- Method isMediaPlaying -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.isMediaPlaying_changed()" class="hiddenlink" target="rightframe">isMediaPlaying
+()</A></nobr><br>
+<!-- Method isShown -->
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.isShown_changed()" class="hiddenlink" target="rightframe">isShown
+()</A></nobr><br>
+<!-- Method isShownOrQueued -->
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.isShownOrQueued_changed()" class="hiddenlink" target="rightframe">isShownOrQueued
+()</A></nobr><br>
+<!-- Class LeanbackPreferenceFragment -->
+<A NAME="L"></A>
+<br><font size="+2">L</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.preference.LeanbackPreferenceFragment.html" class="hiddenlink" target="rightframe">LeanbackPreferenceFragment</A><br>
+<!-- Class LinearLayoutCompat -->
+<A HREF="android.support.v7.widget.LinearLayoutCompat.html" class="hiddenlink" target="rightframe">LinearLayoutCompat</A><br>
+<!-- Class MediaControllerCompat -->
+<A NAME="M"></A>
+<br><font size="+2">M</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.media.session.MediaControllerCompat.html" class="hiddenlink" target="rightframe">MediaControllerCompat</A><br>
+<!-- Class MediaControllerGlue -->
+<i>MediaControllerGlue</i><br>
+ <A HREF="android.support.v17.leanback.app.MediaControllerGlue.html" class="hiddenlink" target="rightframe">android.support.v17.leanback.app</A><br>
+<!-- Constructor MediaControllerGlue -->
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[])" class="hiddenlink" target="rightframe">MediaControllerGlue
+(<code>Context, PlaybackOverlayFragment, int[]</code>)</A></nobr> constructor<br>
+<!-- Constructor MediaControllerGlue -->
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[])" class="hiddenlink" target="rightframe">MediaControllerGlue
+(<code>Context, PlaybackOverlayFragment, int[], int[]</code>)</A></nobr> constructor<br>
+<!-- Class MediaRouteChooserDialog -->
+<A HREF="android.support.v7.app.MediaRouteChooserDialog.html" class="hiddenlink" target="rightframe">MediaRouteChooserDialog</A><br>
+<!-- Class MediaRouter -->
+<A HREF="android.support.v7.media.MediaRouter.html" class="hiddenlink" target="rightframe">MediaRouter</A><br>
+<!-- Class MediaRouter.RouteInfo -->
+<A HREF="android.support.v7.media.MediaRouter.RouteInfo.html" class="hiddenlink" target="rightframe">MediaRouter.RouteInfo</A><br>
+<!-- Method notifyItemRangeChanged -->
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.widget.ObjectAdapter.html#android.support.v17.leanback.widget.ObjectAdapter.notifyItemRangeChanged_changed(int, int)" class="hiddenlink" target="rightframe">notifyItemRangeChanged
+(<code>int, int</code>)</A></nobr><br>
+<!-- Class ObjectAdapter -->
+<A NAME="O"></A>
+<br><font size="+2">O</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.widget.ObjectAdapter.html" class="hiddenlink" target="rightframe">ObjectAdapter</A><br>
+<!-- Method onActionClicked -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onActionClicked_changed(android.support.v17.leanback.widget.Action)" class="hiddenlink" target="rightframe">onActionClicked
+(<code>Action</code>)</A></nobr><br>
+<!-- Class OnChildViewHolderSelectedListener -->
+<A HREF="android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.html" class="hiddenlink" target="rightframe">OnChildViewHolderSelectedListener</A><br>
+<!-- Method onEditingModeChange -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.onEditingModeChange_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">onEditingModeChange
+(<code>ViewHolder, GuidedAction, boolean</code>)</A></nobr><br>
+<!-- Method onKey -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onKey_changed(android.view.View, int, android.view.KeyEvent)" class="hiddenlink" target="rightframe">onKey
+(<code>View, int, KeyEvent</code>)</A></nobr><br>
+<!-- Method onMetadataChanged -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onMetadataChanged_changed()" class="hiddenlink" target="rightframe">onMetadataChanged
+()</A></nobr><br>
+<!-- Method onRowChanged -->
+<i>onRowChanged</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.onRowChanged_changed(android.support.v17.leanback.widget.PlaybackControlsRow)" class="hiddenlink" target="rightframe">type
+(<code>PlaybackControlsRow</code>) in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method onRowChanged -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onRowChanged_changed(android.support.v17.leanback.widget.PlaybackControlsRow)" class="hiddenlink" target="rightframe">type
+(<code>PlaybackControlsRow</code>) in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Method onStateChanged -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onStateChanged_changed()" class="hiddenlink" target="rightframe">onStateChanged
+()</A></nobr><br>
+<!-- Method pausePlayback -->
+<A NAME="P"></A>
+<br><font size="+2">P</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>pausePlayback</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.pausePlayback_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+<!-- Method pausePlayback -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.pausePlayback_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method pausePlayback -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.pausePlayback_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Class PlaybackControlGlue -->
+<i>PlaybackControlGlue</i><br>
+ <A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html" class="hiddenlink" target="rightframe">android.support.v17.leanback.app</A><br>
+<!-- Constructor PlaybackControlGlue -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[])" class="hiddenlink" target="rightframe">PlaybackControlGlue
+(<code>Context, PlaybackOverlayFragment, int[]</code>)</A></nobr> constructor<br>
+<!-- Constructor PlaybackControlGlue -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[])" class="hiddenlink" target="rightframe">PlaybackControlGlue
+(<code>Context, PlaybackOverlayFragment, int[], int[]</code>)</A></nobr> constructor<br>
+<!-- Class PlaybackControlsRow -->
+<A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html" class="hiddenlink" target="rightframe">PlaybackControlsRow</A><br>
+<!-- Class PlaybackControlsRowPresenter -->
+<A HREF="android.support.v17.leanback.widget.PlaybackControlsRowPresenter.html" class="hiddenlink" target="rightframe">PlaybackControlsRowPresenter</A><br>
+<!-- Class PlaybackControlsRowPresenter.ViewHolder -->
+<A HREF="android.support.v17.leanback.widget.PlaybackControlsRowPresenter.ViewHolder.html" class="hiddenlink" target="rightframe">PlaybackControlsRowPresenter.ViewHolder</A><br>
+<!-- Class PlaybackControlSupportGlue -->
+<A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html" class="hiddenlink" target="rightframe">PlaybackControlSupportGlue</A><br>
+<!-- Class PlaybackOverlayFragment -->
+<A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html" class="hiddenlink" target="rightframe">PlaybackOverlayFragment</A><br>
+<!-- Class PlaybackOverlayFragment.InputEventHandler -->
+<A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.html" class="hiddenlink" target="rightframe"><i>PlaybackOverlayFragment.InputEventHandler</i></A><br>
+<!-- Class PlaybackOverlaySupportFragment -->
+<A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html" class="hiddenlink" target="rightframe">PlaybackOverlaySupportFragment</A><br>
+<!-- Class PlaybackOverlaySupportFragment.InputEventHandler -->
+<A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.html" class="hiddenlink" target="rightframe"><i>PlaybackOverlaySupportFragment.InputEventHandler</i></A><br>
+<!-- Class PreferenceManager -->
+<A HREF="android.support.v7.preference.PreferenceManager.html" class="hiddenlink" target="rightframe">PreferenceManager</A><br>
+<!-- Class RecyclerView -->
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v7.widget.RecyclerView.html" class="hiddenlink" target="rightframe">RecyclerView</A><br>
+<!-- Class RecyclerView.RecycledViewPool -->
+<A HREF="android.support.v7.widget.RecyclerView.RecycledViewPool.html" class="hiddenlink" target="rightframe">RecyclerView.RecycledViewPool</A><br>
+<!-- Class RowPresenter.ViewHolder -->
+<A HREF="android.support.v17.leanback.widget.RowPresenter.ViewHolder.html" class="hiddenlink" target="rightframe">RowPresenter.ViewHolder</A><br>
+<!-- Class RowsFragment -->
+<A HREF="android.support.v17.leanback.app.RowsFragment.html" class="hiddenlink" target="rightframe">RowsFragment</A><br>
+<!-- Class RowsSupportFragment -->
+<A HREF="android.support.v17.leanback.app.RowsSupportFragment.html" class="hiddenlink" target="rightframe">RowsSupportFragment</A><br>
+<!-- Class SearchBar -->
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#T"><font size="-2">T</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.widget.SearchBar.html" class="hiddenlink" target="rightframe">SearchBar</A><br>
+<!-- Class SearchFragment -->
+<A HREF="android.support.v17.leanback.app.SearchFragment.html" class="hiddenlink" target="rightframe">SearchFragment</A><br>
+<!-- Class SearchSupportFragment -->
+<A HREF="android.support.v17.leanback.app.SearchSupportFragment.html" class="hiddenlink" target="rightframe">SearchSupportFragment</A><br>
+<!-- Method setCallback -->
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.setCallback_changed(android.support.design.widget.Snackbar.Callback)" class="hiddenlink" target="rightframe">setCallback
+(<code>Callback</code>)</A></nobr><br>
+<!-- Method setControlsRow -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.setControlsRow_changed(android.support.v17.leanback.widget.PlaybackControlsRow)" class="hiddenlink" target="rightframe">setControlsRow
+(<code>PlaybackControlsRow</code>)</A></nobr><br>
+<!-- Method setDimLayer -->
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.setDimLayer_changed(android.graphics.drawable.Drawable)" class="hiddenlink" target="rightframe">setDimLayer
+(<code>Drawable</code>)</A></nobr><br>
+<!-- Method setDuration -->
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.setDuration_changed(int)" class="hiddenlink" target="rightframe">setDuration
+(<code>int</code>)</A></nobr><br>
+<!-- Method setEditingMode -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setEditingMode_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">setEditingMode
+(<code>ViewHolder, GuidedAction, boolean</code>)</A></nobr><br>
+<!-- Method setExpandedViewHolder -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setExpandedViewHolder_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder)" class="hiddenlink" target="rightframe">setExpandedViewHolder
+(<code>ViewHolder</code>)</A></nobr><br>
+<!-- Method setExtraVisibility -->
+<nobr><A HREF="android.support.v17.leanback.widget.BaseCardView.html#android.support.v17.leanback.widget.BaseCardView.setExtraVisibility_changed(int)" class="hiddenlink" target="rightframe">setExtraVisibility
+(<code>int</code>)</A></nobr><br>
+<!-- Method setFadingEnabled -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.setFadingEnabled_changed(boolean)" class="hiddenlink" target="rightframe">setFadingEnabled
+(<code>boolean</code>)</A></nobr><br>
+<!-- Method setInputEventHandler -->
+<i>setInputEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.setInputEventHandler_changed(android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler)" class="hiddenlink" target="rightframe">type
+(<code>InputEventHandler</code>) in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+<!-- Method setInputEventHandler -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.setInputEventHandler_changed(android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler)" class="hiddenlink" target="rightframe">type
+(<code>InputEventHandler</code>) in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<!-- Method setOnItemViewClickedListener -->
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.setOnItemViewClickedListener_changed(android.support.v17.leanback.widget.OnItemViewClickedListener)" class="hiddenlink" target="rightframe">setOnItemViewClickedListener
+(<code>OnItemViewClickedListener</code>)</A></nobr><br>
+<!-- Method setSupportMediaController -->
+<nobr><A HREF="android.support.v4.app.FragmentActivity.html#android.support.v4.app.FragmentActivity.setSupportMediaController_changed(android.support.v4.media.session.MediaControllerCompat)" class="hiddenlink" target="rightframe">setSupportMediaController
+(<code>MediaControllerCompat</code>)</A></nobr><br>
+<!-- Method show -->
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.show_changed()" class="hiddenlink" target="rightframe">show
+()</A></nobr><br>
+<!-- Method skipToNext -->
+<i>skipToNext</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.skipToNext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+<!-- Method skipToNext -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.skipToNext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method skipToNext -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.skipToNext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Method skipToPrevious -->
+<i>skipToPrevious</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.skipToPrevious_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+<!-- Method skipToPrevious -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.skipToPrevious_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method skipToPrevious -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.skipToPrevious_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Class Snackbar -->
+<A HREF="android.support.design.widget.Snackbar.html" class="hiddenlink" target="rightframe">Snackbar</A><br>
+<!-- Class Snackbar.Callback -->
+<A HREF="android.support.design.widget.Snackbar.Callback.html" class="hiddenlink" target="rightframe">Snackbar.Callback</A><br>
+<!-- Class SnapHelper -->
+<A HREF="android.support.v7.widget.SnapHelper.html" class="hiddenlink" target="rightframe">SnapHelper</A><br>
+<!-- Class SpeechOrbView -->
+<A HREF="android.support.v17.leanback.widget.SpeechOrbView.html" class="hiddenlink" target="rightframe">SpeechOrbView</A><br>
+<!-- Method startExpandedTransition -->
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.startExpandedTransition_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder)" class="hiddenlink" target="rightframe">startExpandedTransition
+(<code>ViewHolder</code>)</A></nobr><br>
+<!-- Method startPlayback -->
+<i>startPlayback</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.startPlayback_changed(int)" class="hiddenlink" target="rightframe">type
+(<code>int</code>) in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+<!-- Method startPlayback -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.startPlayback_changed(int)" class="hiddenlink" target="rightframe">type
+(<code>int</code>) in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+<!-- Method startPlayback -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.startPlayback_changed(int)" class="hiddenlink" target="rightframe">type
+(<code>int</code>) in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<!-- Class TextInputLayout -->
+<A NAME="T"></A>
+<br><font size="+2">T</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.design.widget.TextInputLayout.html" class="hiddenlink" target="rightframe">TextInputLayout</A><br>
+<!-- Method updateProgress -->
+<A NAME="U"></A>
+<br><font size="+2">U</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.updateProgress_changed()" class="hiddenlink" target="rightframe">updateProgress
+()</A></nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/alldiffs_index_removals.html b/docs/html/sdk/support_api_diff/25.1.0/changes/alldiffs_index_removals.html
new file mode 100644
index 0000000..4441614
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/alldiffs_index_removals.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+All Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for All Differences" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="alldiffs_index_all.html" xclass="hiddenlink">All Differences</a>
+ <br>
+<b>Removals</b>
+ <br>
+<A HREF="alldiffs_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="alldiffs_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<!-- Method handleInputEvent -->
+<A NAME="H"></A>
+<br><font size="+2">H</font>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>handleInputEvent</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.html#android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.handleInputEvent_removed(android.view.InputEvent)" class="hiddenlink" target="rightframe">type <strike>
+(<code>InputEvent</code>)</strike> in android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler
+</A></nobr><br>
+<!-- Method handleInputEvent -->
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.handleInputEvent_removed(android.view.InputEvent)" class="hiddenlink" target="rightframe">type <strike>
+(<code>InputEvent</code>)</strike> in android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler
+</A></nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.design.widget.Snackbar.Callback.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.design.widget.Snackbar.Callback.html
new file mode 100644
index 0000000..379adb4
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.design.widget.Snackbar.Callback.html
@@ -0,0 +1,109 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.design.widget.Snackbar.Callback
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.design.widget.<A HREF="../../../../reference/android/support/design/widget/Snackbar.Callback.html" target="_top"><font size="+2"><code>Snackbar.Callback</code></font></A>
+</H2>
+<p><font xsize="+1">The superclass changed from <code>java.lang.Object</code> to <code>android.support.design.widget.BaseTransientBottomBar.BaseCallback</code>.<br></font>
+<p>Changed from abstract to non-abstract.
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.design.widget.Snackbar.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.design.widget.Snackbar.html
new file mode 100644
index 0000000..2b64f06
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.design.widget.Snackbar.html
@@ -0,0 +1,197 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.design.widget.Snackbar
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.design.widget.<A HREF="../../../../reference/android/support/design/widget/Snackbar.html" target="_top"><font size="+2"><code>Snackbar</code></font></A>
+</H2>
+<p><font xsize="+1">The superclass changed from <code>java.lang.Object</code> to <code>android.support.design.widget.BaseTransientBottomBar</code>.<br></font>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.design.widget.Snackbar.dismiss_changed()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html#dismiss()" target="_top"><code>dismiss</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html#dismiss()" target="_top"><code>BaseTransientBottomBar</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.design.widget.Snackbar.getDuration_changed()"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html#getDuration()" target="_top"><code>getDuration</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html#getDuration()" target="_top"><code>BaseTransientBottomBar</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.design.widget.Snackbar.getView_changed()"></A>
+ <nobr><code>View</code> <A HREF="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html#getView()" target="_top"><code>getView</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html#getView()" target="_top"><code>BaseTransientBottomBar</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.design.widget.Snackbar.isShown_changed()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html#isShown()" target="_top"><code>isShown</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html#isShown()" target="_top"><code>BaseTransientBottomBar</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.design.widget.Snackbar.isShownOrQueued_changed()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html#isShownOrQueued()" target="_top"><code>isShownOrQueued</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html#isShownOrQueued()" target="_top"><code>BaseTransientBottomBar</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.design.widget.Snackbar.setCallback_changed(android.support.design.widget.Snackbar.Callback)"></A>
+ <nobr><code>Snackbar</code> <A HREF="../../../../reference/android/support/design/widget/Snackbar.html#setCallback(android.support.design.widget.Snackbar.Callback)" target="_top"><code>setCallback</code></A>(<code>Callback</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.design.widget.Snackbar.setDuration_changed(int)"></A>
+ <nobr><code>B</code> <A HREF="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html#setDuration(int)" target="_top"><code>setDuration</code></A>(<code>int</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Change in return type from <code>Snackbar</code> to <code>B</code>.<br>
+ Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html#setDuration(int)" target="_top"><code>BaseTransientBottomBar</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.design.widget.Snackbar.show_changed()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html#show()" target="_top"><code>show</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html#show()" target="_top"><code>BaseTransientBottomBar</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.design.widget.TextInputLayout.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.design.widget.TextInputLayout.html
new file mode 100644
index 0000000..67422f9
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.design.widget.TextInputLayout.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.design.widget.TextInputLayout
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.design.widget.<A HREF="../../../../reference/android/support/design/widget/TextInputLayout.html" target="_top"><font size="+2"><code>TextInputLayout</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.design.widget.TextInputLayout.setErrorTextAppearance_added(int)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/design/widget/TextInputLayout.html#setErrorTextAppearance(int)" target="_top"><code>setErrorTextAppearance</code></A>(<code>int</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BackgroundManager.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BackgroundManager.html
new file mode 100644
index 0000000..0a71e6a
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BackgroundManager.html
@@ -0,0 +1,181 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.BackgroundManager
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/BackgroundManager.html" target="_top"><font size="+2"><code>BackgroundManager</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BackgroundManager.attachToView_added(android.view.View)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BackgroundManager.html#attachToView(android.view.View)" target="_top"><code>attachToView</code></A>(<code>View</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BackgroundManager.clearDrawable_added()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BackgroundManager.html#clearDrawable()" target="_top"><code>clearDrawable</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BackgroundManager.isAutoReleaseOnStop_added()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BackgroundManager.html#isAutoReleaseOnStop()" target="_top"><code>isAutoReleaseOnStop</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BackgroundManager.setAutoReleaseOnStop_added(boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BackgroundManager.html#setAutoReleaseOnStop(boolean)" target="_top"><code>setAutoReleaseOnStop</code></A>(<code>boolean</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BackgroundManager.getDefaultDimLayer_changed()"></A>
+ <nobr><code>Drawable</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BackgroundManager.html#getDefaultDimLayer()" target="_top"><code>getDefaultDimLayer</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BackgroundManager.getDimLayer_changed()"></A>
+ <nobr><code>Drawable</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BackgroundManager.html#getDimLayer()" target="_top"><code>getDimLayer</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BackgroundManager.setDimLayer_changed(android.graphics.drawable.Drawable)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BackgroundManager.html#setDimLayer(android.graphics.drawable.Drawable)" target="_top"><code>setDimLayer</code></A>(<code>Drawable</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BaseRowFragment.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BaseRowFragment.html
new file mode 100644
index 0000000..c798e24
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BaseRowFragment.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.BaseRowFragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/BaseRowFragment.html" target="_top"><font size="+2"><code>BaseRowFragment</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BaseRowFragment.getVerticalGridView_added()"></A>
+ <nobr><code>VerticalGridView</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BaseRowFragment.html#getVerticalGridView()" target="_top"><code>getVerticalGridView</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BaseRowSupportFragment.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BaseRowSupportFragment.html
new file mode 100644
index 0000000..3487eff
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BaseRowSupportFragment.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.BaseRowSupportFragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/BaseRowSupportFragment.html" target="_top"><font size="+2"><code>BaseRowSupportFragment</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BaseRowSupportFragment.getVerticalGridView_added()"></A>
+ <nobr><code>VerticalGridView</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BaseRowSupportFragment.html#getVerticalGridView()" target="_top"><code>getVerticalGridView</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.html
new file mode 100644
index 0000000..c5f3718
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/BrowseFragment.MainFragmentRowsAdapter.html" target="_top"><font size="+2"><code>BrowseFragment.MainFragmentRowsAdapter</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.findRowViewHolderByPosition_added(int)"></A>
+ <nobr><code>ViewHolder</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BrowseFragment.MainFragmentRowsAdapter.html#findRowViewHolderByPosition(int)" target="_top"><code>findRowViewHolderByPosition</code></A>(<code>int</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BrowseFragment.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BrowseFragment.html
new file mode 100644
index 0000000..753fb6a
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BrowseFragment.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.BrowseFragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/BrowseFragment.html" target="_top"><font size="+2"><code>BrowseFragment</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BrowseFragment.getMainFragment_added()"></A>
+ <nobr><code>Fragment</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BrowseFragment.html#getMainFragment()" target="_top"><code>getMainFragment</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BrowseFragment.getSelectedRowViewHolder_added()"></A>
+ <nobr><code>ViewHolder</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BrowseFragment.html#getSelectedRowViewHolder()" target="_top"><code>getSelectedRowViewHolder</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.html
new file mode 100644
index 0000000..999b145
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/BrowseSupportFragment.MainFragmentRowsAdapter.html" target="_top"><font size="+2"><code>BrowseSupportFragment.MainFragmentRowsAdapter</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.findRowViewHolderByPosition_added(int)"></A>
+ <nobr><code>ViewHolder</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BrowseSupportFragment.MainFragmentRowsAdapter.html#findRowViewHolderByPosition(int)" target="_top"><code>findRowViewHolderByPosition</code></A>(<code>int</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BrowseSupportFragment.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BrowseSupportFragment.html
new file mode 100644
index 0000000..989a412
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.BrowseSupportFragment.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.BrowseSupportFragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/BrowseSupportFragment.html" target="_top"><font size="+2"><code>BrowseSupportFragment</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BrowseSupportFragment.getMainFragment_added()"></A>
+ <nobr><code>Fragment</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BrowseSupportFragment.html#getMainFragment()" target="_top"><code>getMainFragment</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.BrowseSupportFragment.getSelectedRowViewHolder_added()"></A>
+ <nobr><code>ViewHolder</code> <A HREF="../../../../reference/android/support/v17/leanback/app/BrowseSupportFragment.html#getSelectedRowViewHolder()" target="_top"><code>getSelectedRowViewHolder</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.GuidedStepFragment.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.GuidedStepFragment.html
new file mode 100644
index 0000000..3d40485
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.GuidedStepFragment.html
@@ -0,0 +1,136 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.GuidedStepFragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/GuidedStepFragment.html" target="_top"><font size="+2"><code>GuidedStepFragment</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.GuidedStepFragment.collapseAction_added(boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/GuidedStepFragment.html#collapseAction(boolean)" target="_top"><code>collapseAction</code></A>(<code>boolean</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.GuidedStepFragment.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/GuidedStepFragment.html#expandAction(android.support.v17.leanback.widget.GuidedAction, boolean)" target="_top"><code>expandAction</code></A>(<code>GuidedAction,</nobr> boolean<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.GuidedStepFragment.isExpanded_added()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v17/leanback/app/GuidedStepFragment.html#isExpanded()" target="_top"><code>isExpanded</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.GuidedStepSupportFragment.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.GuidedStepSupportFragment.html
new file mode 100644
index 0000000..bb7ec40
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.GuidedStepSupportFragment.html
@@ -0,0 +1,136 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.GuidedStepSupportFragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/GuidedStepSupportFragment.html" target="_top"><font size="+2"><code>GuidedStepSupportFragment</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.GuidedStepSupportFragment.collapseAction_added(boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/GuidedStepSupportFragment.html#collapseAction(boolean)" target="_top"><code>collapseAction</code></A>(<code>boolean</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.GuidedStepSupportFragment.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/GuidedStepSupportFragment.html#expandAction(android.support.v17.leanback.widget.GuidedAction, boolean)" target="_top"><code>expandAction</code></A>(<code>GuidedAction,</nobr> boolean<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.GuidedStepSupportFragment.isExpanded_added()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v17/leanback/app/GuidedStepSupportFragment.html#isExpanded()" target="_top"><code>isExpanded</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.MediaControllerGlue.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.MediaControllerGlue.html
new file mode 100644
index 0000000..c2711281
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.MediaControllerGlue.html
@@ -0,0 +1,198 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.MediaControllerGlue
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/MediaControllerGlue.html" target="_top"><font size="+2"><code>MediaControllerGlue</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Constructors" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Constructors</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.MediaControllerGlue.ctor_added(android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/MediaControllerGlue.html#MediaControllerGlue(android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])" target="_top"><code>MediaControllerGlue</code></A>(<code>Context,</nobr> PlaybackGlueHost<nobr>,</nobr> int[]<nobr>,</nobr> int[]<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Constructors" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Constructors</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.MediaControllerGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[])"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/MediaControllerGlue.html#MediaControllerGlue(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[])" target="_top"><code>MediaControllerGlue</code></A>(<code>Context,</nobr> PlaybackOverlayFragment<nobr>,</nobr> int[]<nobr><nobr></code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.MediaControllerGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[])"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/MediaControllerGlue.html#MediaControllerGlue(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[])" target="_top"><code>MediaControllerGlue</code></A>(<code>Context,</nobr> PlaybackOverlayFragment<nobr>,</nobr> int[]<nobr>,</nobr> int[]<nobr><nobr></code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="methods"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.MediaControllerGlue.pausePlayback_changed()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#pausePlayback()" target="_top"><code>pausePlayback</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#pausePlayback()" target="_top"><code>PlaybackControlGlue</code></a>. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.MediaControllerGlue.skipToNext_changed()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#skipToNext()" target="_top"><code>skipToNext</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#skipToNext()" target="_top"><code>PlaybackControlGlue</code></a>. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.MediaControllerGlue.skipToPrevious_changed()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#skipToPrevious()" target="_top"><code>skipToPrevious</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#skipToPrevious()" target="_top"><code>PlaybackControlGlue</code></a>. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.MediaControllerGlue.startPlayback_changed(int)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#startPlayback(int)" target="_top"><code>startPlayback</code></A>(<code>int</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#startPlayback(int)" target="_top"><code>PlaybackControlGlue</code></a>. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackControlGlue.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackControlGlue.html
new file mode 100644
index 0000000..0657ab0
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackControlGlue.html
@@ -0,0 +1,239 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.PlaybackControlGlue
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html" target="_top"><font size="+2"><code>PlaybackControlGlue</code></font></A>
+</H2>
+<p><font xsize="+1">The superclass changed from <code>java.lang.Object</code> to <code>android.support.v17.leanback.app.PlaybackGlue</code>.<br></font>
+<a NAME="constructors"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Constructors" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Constructors</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlGlue.ctor_added(android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#PlaybackControlGlue(android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])" target="_top"><code>PlaybackControlGlue</code></A>(<code>Context,</nobr> PlaybackGlueHost<nobr>,</nobr> int[]<nobr>,</nobr> int[]<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Constructors" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Constructors</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[])"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#PlaybackControlGlue(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[])" target="_top"><code>PlaybackControlGlue</code></A>(<code>Context,</nobr> PlaybackOverlayFragment<nobr>,</nobr> int[]<nobr><nobr></code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[])"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#PlaybackControlGlue(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[])" target="_top"><code>PlaybackControlGlue</code></A>(<code>Context,</nobr> PlaybackOverlayFragment<nobr>,</nobr> int[]<nobr>,</nobr> int[]<nobr><nobr></code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="methods"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlGlue.getContext_changed()"></A>
+ <nobr><code>Context</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackGlue.html#getContext()" target="_top"><code>getContext</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackGlue.html#getContext()" target="_top"><code>PlaybackGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlGlue.getFragment_changed()"></A>
+ <nobr><code>PlaybackOverlayFragment</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getFragment()" target="_top"><code>getFragment</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlGlue.getOnItemViewClickedListener_changed()"></A>
+ <nobr><code>OnItemViewClickedListener</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getOnItemViewClickedListener()" target="_top"><code>getOnItemViewClickedListener</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlGlue.onRowChanged_changed(android.support.v17.leanback.widget.PlaybackControlsRow)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#onRowChanged(android.support.v17.leanback.widget.PlaybackControlsRow)" target="_top"><code>onRowChanged</code></A>(<code>PlaybackControlsRow</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Changed from abstract to non-abstract. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlGlue.pausePlayback_changed()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#pausePlayback()" target="_top"><code>pausePlayback</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Changed from abstract to non-abstract. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlGlue.skipToNext_changed()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#skipToNext()" target="_top"><code>skipToNext</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Changed from abstract to non-abstract. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlGlue.skipToPrevious_changed()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#skipToPrevious()" target="_top"><code>skipToPrevious</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Changed from abstract to non-abstract. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlGlue.startPlayback_changed(int)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#startPlayback(int)" target="_top"><code>startPlayback</code></A>(<code>int</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Changed from abstract to non-abstract. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackControlSupportGlue.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackControlSupportGlue.html
new file mode 100644
index 0000000..a7bb4e8
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackControlSupportGlue.html
@@ -0,0 +1,448 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.PlaybackControlSupportGlue
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlSupportGlue.html" target="_top"><font size="+2"><code>PlaybackControlSupportGlue</code></font></A>
+</H2>
+<p><font xsize="+1">The superclass changed from <code>java.lang.Object</code> to <code>android.support.v17.leanback.app.PlaybackControlGlue</code>.<br> Removed interface <code>android.support.v17.leanback.widget.OnActionClickedListener</code>.<br></font>
+<p><b>Now deprecated</b>.<br>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.createControlsRowAndPresenter_changed()"></A>
+ <nobr><code>PlaybackControlsRowPresenter</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#createControlsRowAndPresenter()" target="_top"><code>createControlsRowAndPresenter</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#createControlsRowAndPresenter()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.createPrimaryActionsAdapter_changed(android.support.v17.leanback.widget.PresenterSelector)"></A>
+ <nobr><code>SparseArrayObjectAdapter</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#createPrimaryActionsAdapter(android.support.v17.leanback.widget.PresenterSelector)" target="_top"><code>createPrimaryActionsAdapter</code></A>(<code>PresenterSelector</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#createPrimaryActionsAdapter(android.support.v17.leanback.widget.PresenterSelector)" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.enableProgressUpdating_changed(boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#enableProgressUpdating(boolean)" target="_top"><code>enableProgressUpdating</code></A>(<code>boolean</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#enableProgressUpdating(boolean)" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.getContext_changed()"></A>
+ <nobr><code>Context</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackGlue.html#getContext()" target="_top"><code>getContext</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackGlue.html#getContext()" target="_top"><code>PlaybackGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.getControlsRow_changed()"></A>
+ <nobr><code>PlaybackControlsRow</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getControlsRow()" target="_top"><code>getControlsRow</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getControlsRow()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.getCurrentPosition_changed()"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getCurrentPosition()" target="_top"><code>getCurrentPosition</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getCurrentPosition()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.getCurrentSpeedId_changed()"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getCurrentSpeedId()" target="_top"><code>getCurrentSpeedId</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getCurrentSpeedId()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.getFastForwardSpeeds_changed()"></A>
+ <nobr><code>int[]</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getFastForwardSpeeds()" target="_top"><code>getFastForwardSpeeds</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getFastForwardSpeeds()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.getFragment_changed()"></A>
+ <nobr><code>PlaybackOverlayFragment</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getFragment()" target="_top"><code>getFragment</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Change in return type from <code>PlaybackOverlaySupportFragment</code> to <code>PlaybackOverlayFragment</code>.<br>
+ Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getFragment()" target="_top"><code>PlaybackControlGlue</code></a>. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaArt_changed()"></A>
+ <nobr><code>Drawable</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getMediaArt()" target="_top"><code>getMediaArt</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getMediaArt()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaDuration_changed()"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getMediaDuration()" target="_top"><code>getMediaDuration</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getMediaDuration()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaSubtitle_changed()"></A>
+ <nobr><code>CharSequence</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getMediaSubtitle()" target="_top"><code>getMediaSubtitle</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getMediaSubtitle()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaTitle_changed()"></A>
+ <nobr><code>CharSequence</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getMediaTitle()" target="_top"><code>getMediaTitle</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getMediaTitle()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.getOnItemViewClickedListener_changed()"></A>
+ <nobr><code>OnItemViewClickedListener</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getOnItemViewClickedListener()" target="_top"><code>getOnItemViewClickedListener</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getOnItemViewClickedListener()" target="_top"><code>PlaybackControlGlue</code></a>. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.getRewindSpeeds_changed()"></A>
+ <nobr><code>int[]</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getRewindSpeeds()" target="_top"><code>getRewindSpeeds</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getRewindSpeeds()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.getSupportedActions_changed()"></A>
+ <nobr><code>long</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getSupportedActions()" target="_top"><code>getSupportedActions</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getSupportedActions()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.getUpdatePeriod_changed()"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getUpdatePeriod()" target="_top"><code>getUpdatePeriod</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#getUpdatePeriod()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.hasValidMedia_changed()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#hasValidMedia()" target="_top"><code>hasValidMedia</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#hasValidMedia()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.isFadingEnabled_changed()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#isFadingEnabled()" target="_top"><code>isFadingEnabled</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#isFadingEnabled()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.isMediaPlaying_changed()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#isMediaPlaying()" target="_top"><code>isMediaPlaying</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#isMediaPlaying()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.onActionClicked_changed(android.support.v17.leanback.widget.Action)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#onActionClicked(android.support.v17.leanback.widget.Action)" target="_top"><code>onActionClicked</code></A>(<code>Action</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#onActionClicked(android.support.v17.leanback.widget.Action)" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.onKey_changed(android.view.View, int, android.view.KeyEvent)"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#onKey(android.view.View, int, android.view.KeyEvent)" target="_top"><code>onKey</code></A>(<code>View,</nobr> int<nobr>,</nobr> KeyEvent<nobr><nobr></code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#onKey(android.view.View, int, android.view.KeyEvent)" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.onMetadataChanged_changed()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#onMetadataChanged()" target="_top"><code>onMetadataChanged</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#onMetadataChanged()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.onRowChanged_changed(android.support.v17.leanback.widget.PlaybackControlsRow)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#onRowChanged(android.support.v17.leanback.widget.PlaybackControlsRow)" target="_top"><code>onRowChanged</code></A>(<code>PlaybackControlsRow</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#onRowChanged(android.support.v17.leanback.widget.PlaybackControlsRow)" target="_top"><code>PlaybackControlGlue</code></a>. Changed from abstract to non-abstract. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.onStateChanged_changed()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#onStateChanged()" target="_top"><code>onStateChanged</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#onStateChanged()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.pausePlayback_changed()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#pausePlayback()" target="_top"><code>pausePlayback</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#pausePlayback()" target="_top"><code>PlaybackControlGlue</code></a>. Changed from abstract to non-abstract. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.setControlsRow_changed(android.support.v17.leanback.widget.PlaybackControlsRow)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#setControlsRow(android.support.v17.leanback.widget.PlaybackControlsRow)" target="_top"><code>setControlsRow</code></A>(<code>PlaybackControlsRow</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#setControlsRow(android.support.v17.leanback.widget.PlaybackControlsRow)" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.setFadingEnabled_changed(boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#setFadingEnabled(boolean)" target="_top"><code>setFadingEnabled</code></A>(<code>boolean</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#setFadingEnabled(boolean)" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.setOnItemViewClickedListener_changed(android.support.v17.leanback.widget.OnItemViewClickedListener)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener)" target="_top"><code>setOnItemViewClickedListener</code></A>(<code>OnItemViewClickedListener</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#setOnItemViewClickedListener(android.support.v17.leanback.widget.OnItemViewClickedListener)" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.skipToNext_changed()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#skipToNext()" target="_top"><code>skipToNext</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#skipToNext()" target="_top"><code>PlaybackControlGlue</code></a>. Changed from abstract to non-abstract. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.skipToPrevious_changed()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#skipToPrevious()" target="_top"><code>skipToPrevious</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#skipToPrevious()" target="_top"><code>PlaybackControlGlue</code></a>. Changed from abstract to non-abstract. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.startPlayback_changed(int)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#startPlayback(int)" target="_top"><code>startPlayback</code></A>(<code>int</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#startPlayback(int)" target="_top"><code>PlaybackControlGlue</code></a>. Changed from abstract to non-abstract. <b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackControlSupportGlue.updateProgress_changed()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#updateProgress()" target="_top"><code>updateProgress</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Method was locally defined, but is now inherited from <a href="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.html#updateProgress()" target="_top"><code>PlaybackControlGlue</code></a>.
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.html
new file mode 100644
index 0000000..0cffcc3
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Interface android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackOverlayFragment.InputEventHandler.html" target="_top"><font size="+2"><code>PlaybackOverlayFragment.InputEventHandler</code></font></A>
+</H2>
+<p><font xsize="+1">Added interface <code>android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler</code>.<br></font>
+<p><b>Now deprecated</b>.<br>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Removed"></a>
+<TABLE summary="Removed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Removed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.handleInputEvent_removed(android.view.InputEvent)"></A>
+ <nobr><code>boolean</code> handleInputEvent(<code>InputEvent</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackOverlayFragment.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackOverlayFragment.html
new file mode 100644
index 0000000..5ee015c
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackOverlayFragment.html
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.PlaybackOverlayFragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackOverlayFragment.html" target="_top"><font size="+2"><code>PlaybackOverlayFragment</code></font></A>
+</H2>
+<p><b>Now deprecated</b>.<br>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackOverlayFragment.getEventHandler_added()"></A>
+ <nobr><code>InputEventHandler</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackOverlayFragment.html#getEventHandler()" target="_top"><code>getEventHandler</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackOverlayFragment.setEventHandler_added(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackOverlayFragment.html#setEventHandler(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)" target="_top"><code>setEventHandler</code></A>(<code>InputEventHandler</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackOverlayFragment.getInputEventHandler_changed()"></A>
+ <nobr><code>InputEventHandler</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackOverlayFragment.html#getInputEventHandler()" target="_top"><code>getInputEventHandler</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackOverlayFragment.setInputEventHandler_changed(android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackOverlayFragment.html#setInputEventHandler(android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler)" target="_top"><code>setInputEventHandler</code></A>(<code>InputEventHandler</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.html
new file mode 100644
index 0000000..74409a1
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Interface android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackOverlaySupportFragment.InputEventHandler.html" target="_top"><font size="+2"><code>PlaybackOverlaySupportFragment.InputEventHandler</code></font></A>
+</H2>
+<p><font xsize="+1">Added interface <code>android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler</code>.<br></font>
+<p><b>Now deprecated</b>.<br>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Removed"></a>
+<TABLE summary="Removed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Removed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.handleInputEvent_removed(android.view.InputEvent)"></A>
+ <nobr><code>boolean</code> handleInputEvent(<code>InputEvent</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html
new file mode 100644
index 0000000..567a011
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackOverlaySupportFragment.html" target="_top"><font size="+2"><code>PlaybackOverlaySupportFragment</code></font></A>
+</H2>
+<p><b>Now deprecated</b>.<br>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.getEventHandler_added()"></A>
+ <nobr><code>InputEventHandler</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackOverlaySupportFragment.html#getEventHandler()" target="_top"><code>getEventHandler</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.setEventHandler_added(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackOverlaySupportFragment.html#setEventHandler(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)" target="_top"><code>setEventHandler</code></A>(<code>InputEventHandler</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.getInputEventHandler_changed()"></A>
+ <nobr><code>InputEventHandler</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackOverlaySupportFragment.html#getInputEventHandler()" target="_top"><code>getInputEventHandler</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.setInputEventHandler_changed(android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackOverlaySupportFragment.html#setInputEventHandler(android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler)" target="_top"><code>setInputEventHandler</code></A>(<code>InputEventHandler</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.RowsFragment.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.RowsFragment.html
new file mode 100644
index 0000000..a11c9f8
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.RowsFragment.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.RowsFragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/RowsFragment.html" target="_top"><font size="+2"><code>RowsFragment</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.RowsFragment.findRowViewHolderByPosition_added(int)"></A>
+ <nobr><code>ViewHolder</code> <A HREF="../../../../reference/android/support/v17/leanback/app/RowsFragment.html#findRowViewHolderByPosition(int)" target="_top"><code>findRowViewHolderByPosition</code></A>(<code>int</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.RowsSupportFragment.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.RowsSupportFragment.html
new file mode 100644
index 0000000..6f39b91
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.RowsSupportFragment.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.RowsSupportFragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/RowsSupportFragment.html" target="_top"><font size="+2"><code>RowsSupportFragment</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.RowsSupportFragment.findRowViewHolderByPosition_added(int)"></A>
+ <nobr><code>ViewHolder</code> <A HREF="../../../../reference/android/support/v17/leanback/app/RowsSupportFragment.html#findRowViewHolderByPosition(int)" target="_top"><code>findRowViewHolderByPosition</code></A>(<code>int</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.SearchFragment.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.SearchFragment.html
new file mode 100644
index 0000000..14824ee
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.SearchFragment.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.SearchFragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/SearchFragment.html" target="_top"><font size="+2"><code>SearchFragment</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.SearchFragment.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/SearchFragment.html#setSearchAffordanceColors(android.support.v17.leanback.widget.SearchOrbView.Colors)" target="_top"><code>setSearchAffordanceColors</code></A>(<code>Colors</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.SearchFragment.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/SearchFragment.html#setSearchAffordanceColorsInListening(android.support.v17.leanback.widget.SearchOrbView.Colors)" target="_top"><code>setSearchAffordanceColorsInListening</code></A>(<code>Colors</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.SearchSupportFragment.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.SearchSupportFragment.html
new file mode 100644
index 0000000..6d904d2
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.app.SearchSupportFragment.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app.SearchSupportFragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.app.<A HREF="../../../../reference/android/support/v17/leanback/app/SearchSupportFragment.html" target="_top"><font size="+2"><code>SearchSupportFragment</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.SearchSupportFragment.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/SearchSupportFragment.html#setSearchAffordanceColors(android.support.v17.leanback.widget.SearchOrbView.Colors)" target="_top"><code>setSearchAffordanceColors</code></A>(<code>Colors</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app.SearchSupportFragment.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/app/SearchSupportFragment.html#setSearchAffordanceColorsInListening(android.support.v17.leanback.widget.SearchOrbView.Colors)" target="_top"><code>setSearchAffordanceColorsInListening</code></A>(<code>Colors</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.BaseCardView.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.BaseCardView.html
new file mode 100644
index 0000000..fb480bb
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.BaseCardView.html
@@ -0,0 +1,135 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.widget.BaseCardView
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.widget.<A HREF="../../../../reference/android/support/v17/leanback/widget/BaseCardView.html" target="_top"><font size="+2"><code>BaseCardView</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.BaseCardView.getExtraVisibility_changed()"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/BaseCardView.html#getExtraVisibility()" target="_top"><code>getExtraVisibility</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.BaseCardView.setExtraVisibility_changed(int)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/BaseCardView.html#setExtraVisibility(int)" target="_top"><code>setExtraVisibility</code></A>(<code>int</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.BrowseFrameLayout.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.BrowseFrameLayout.html
new file mode 100644
index 0000000..34409ff
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.BrowseFrameLayout.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.widget.BrowseFrameLayout
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.widget.<A HREF="../../../../reference/android/support/v17/leanback/widget/BrowseFrameLayout.html" target="_top"><font size="+2"><code>BrowseFrameLayout</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.BrowseFrameLayout.setOnDispatchKeyListener_added(android.view.View.OnKeyListener)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/BrowseFrameLayout.html#setOnDispatchKeyListener(android.view.View.OnKeyListener)" target="_top"><code>setOnDispatchKeyListener</code></A>(<code>OnKeyListener</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.html
new file mode 100644
index 0000000..2958388
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.GuidedActionsStylist.html
@@ -0,0 +1,219 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.widget.GuidedActionsStylist
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.widget.<A HREF="../../../../reference/android/support/v17/leanback/widget/GuidedActionsStylist.html" target="_top"><font size="+2"><code>GuidedActionsStylist</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.GuidedActionsStylist.collapseAction_added(boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/GuidedActionsStylist.html#collapseAction(boolean)" target="_top"><code>collapseAction</code></A>(<code>boolean</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.GuidedActionsStylist.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/GuidedActionsStylist.html#expandAction(android.support.v17.leanback.widget.GuidedAction, boolean)" target="_top"><code>expandAction</code></A>(<code>GuidedAction,</nobr> boolean<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.GuidedActionsStylist.isBackKeyToCollapseActivatorView_added()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/GuidedActionsStylist.html#isBackKeyToCollapseActivatorView()" target="_top"><code>isBackKeyToCollapseActivatorView</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.GuidedActionsStylist.isBackKeyToCollapseSubActions_added()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/GuidedActionsStylist.html#isBackKeyToCollapseSubActions()" target="_top"><code>isBackKeyToCollapseSubActions</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.GuidedActionsStylist.isExpanded_added()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/GuidedActionsStylist.html#isExpanded()" target="_top"><code>isExpanded</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.GuidedActionsStylist.onEditingModeChange_added(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean, boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/GuidedActionsStylist.html#onEditingModeChange(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean, boolean)" target="_top"><code>onEditingModeChange</code></A>(<code>ViewHolder,</nobr> boolean<nobr>,</nobr> boolean<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.GuidedActionsStylist.setBackKeyToCollapseActivatorView_added(boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/GuidedActionsStylist.html#setBackKeyToCollapseActivatorView(boolean)" target="_top"><code>setBackKeyToCollapseActivatorView</code></A>(<code>boolean</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.GuidedActionsStylist.setBackKeyToCollapseSubActions_added(boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/GuidedActionsStylist.html#setBackKeyToCollapseSubActions(boolean)" target="_top"><code>setBackKeyToCollapseSubActions</code></A>(<code>boolean</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.GuidedActionsStylist.setEditingMode_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/GuidedActionsStylist.html#setEditingMode(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean)" target="_top"><code>setEditingMode</code></A>(<code>ViewHolder,</nobr> GuidedAction<nobr>,</nobr> boolean<nobr><nobr></code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.GuidedActionsStylist.setExpandedViewHolder_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/GuidedActionsStylist.html#setExpandedViewHolder(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder)" target="_top"><code>setExpandedViewHolder</code></A>(<code>ViewHolder</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.GuidedActionsStylist.startExpandedTransition_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/GuidedActionsStylist.html#startExpandedTransition(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder)" target="_top"><code>startExpandedTransition</code></A>(<code>ViewHolder</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.GuidedActionsStylist.onEditingModeChange_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/GuidedActionsStylist.html#onEditingModeChange(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean)" target="_top"><code>onEditingModeChange</code></A>(<code>ViewHolder,</nobr> GuidedAction<nobr>,</nobr> boolean<nobr><nobr></code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.HeaderItem.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.HeaderItem.html
new file mode 100644
index 0000000..4050be5
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.HeaderItem.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.widget.HeaderItem
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.widget.<A HREF="../../../../reference/android/support/v17/leanback/widget/HeaderItem.html" target="_top"><font size="+2"><code>HeaderItem</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.HeaderItem.getDescription_added()"></A>
+ <nobr><code>CharSequence</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/HeaderItem.html#getDescription()" target="_top"><code>getDescription</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.HeaderItem.setDescription_added(java.lang.CharSequence)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/HeaderItem.html#setDescription(java.lang.CharSequence)" target="_top"><code>setDescription</code></A>(<code>CharSequence</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.ObjectAdapter.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.ObjectAdapter.html
new file mode 100644
index 0000000..1a9616a
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.ObjectAdapter.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.widget.ObjectAdapter
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.widget.<A HREF="../../../../reference/android/support/v17/leanback/widget/ObjectAdapter.html" target="_top"><font size="+2"><code>ObjectAdapter</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.ObjectAdapter.notifyItemRangeChanged_changed(int, int)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/ObjectAdapter.html#notifyItemRangeChanged(int, int)" target="_top"><code>notifyItemRangeChanged</code></A>(<code>int,</nobr> int<nobr><nobr></code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+Change of visibility from protected to public.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.html
new file mode 100644
index 0000000..a15728f
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.widget.OnChildViewHolderSelectedListener
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.widget.<A HREF="../../../../reference/android/support/v17/leanback/widget/OnChildViewHolderSelectedListener.html" target="_top"><font size="+2"><code>OnChildViewHolderSelectedListener</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.onChildViewHolderSelectedAndPositioned_added(android.support.v7.widget.RecyclerView, android.support.v7.widget.RecyclerView.ViewHolder, int, int)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/OnChildViewHolderSelectedListener.html#onChildViewHolderSelectedAndPositioned(android.support.v7.widget.RecyclerView, android.support.v7.widget.RecyclerView.ViewHolder, int, int)" target="_top"><code>onChildViewHolderSelectedAndPositioned</code></A>(<code>RecyclerView,</nobr> ViewHolder<nobr>,</nobr> int<nobr>,</nobr> int<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.PlaybackControlsRow.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.PlaybackControlsRow.html
new file mode 100644
index 0000000..6020029
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.PlaybackControlsRow.html
@@ -0,0 +1,157 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.widget.PlaybackControlsRow
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.widget.<A HREF="../../../../reference/android/support/v17/leanback/widget/PlaybackControlsRow.html" target="_top"><font size="+2"><code>PlaybackControlsRow</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.PlaybackControlsRow.getBufferedProgressLong_added()"></A>
+ <nobr><code>long</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/PlaybackControlsRow.html#getBufferedProgressLong()" target="_top"><code>getBufferedProgressLong</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.PlaybackControlsRow.getCurrentTimeLong_added()"></A>
+ <nobr><code>long</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/PlaybackControlsRow.html#getCurrentTimeLong()" target="_top"><code>getCurrentTimeLong</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.PlaybackControlsRow.getTotalTimeLong_added()"></A>
+ <nobr><code>long</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/PlaybackControlsRow.html#getTotalTimeLong()" target="_top"><code>getTotalTimeLong</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.PlaybackControlsRow.setBufferedProgressLong_added(long)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/PlaybackControlsRow.html#setBufferedProgressLong(long)" target="_top"><code>setBufferedProgressLong</code></A>(<code>long</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.PlaybackControlsRow.setCurrentTimeLong_added(long)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/PlaybackControlsRow.html#setCurrentTimeLong(long)" target="_top"><code>setCurrentTimeLong</code></A>(<code>long</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.PlaybackControlsRow.setTotalTimeLong_added(long)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/PlaybackControlsRow.html#setTotalTimeLong(long)" target="_top"><code>setTotalTimeLong</code></A>(<code>long</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.PlaybackControlsRowPresenter.ViewHolder.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.PlaybackControlsRowPresenter.ViewHolder.html
new file mode 100644
index 0000000..105b297
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.PlaybackControlsRowPresenter.ViewHolder.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.widget.PlaybackControlsRowPresenter.ViewHolder
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.widget.<A HREF="../../../../reference/android/support/v17/leanback/widget/PlaybackControlsRowPresenter.ViewHolder.html" target="_top"><font size="+2"><code>PlaybackControlsRowPresenter.ViewHolder</code></font></A>
+</H2>
+<p><font xsize="+1">The superclass changed from <code>android.support.v17.leanback.widget.RowPresenter.ViewHolder</code> to <code>android.support.v17.leanback.widget.PlaybackRowPresenter.ViewHolder</code>.<br></font>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.PlaybackControlsRowPresenter.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.PlaybackControlsRowPresenter.html
new file mode 100644
index 0000000..55f18ba
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.PlaybackControlsRowPresenter.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.widget.PlaybackControlsRowPresenter
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.widget.<A HREF="../../../../reference/android/support/v17/leanback/widget/PlaybackControlsRowPresenter.html" target="_top"><font size="+2"><code>PlaybackControlsRowPresenter</code></font></A>
+</H2>
+<p><font xsize="+1">The superclass changed from <code>android.support.v17.leanback.widget.RowPresenter</code> to <code>android.support.v17.leanback.widget.PlaybackRowPresenter</code>.<br></font>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.RowPresenter.ViewHolder.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.RowPresenter.ViewHolder.html
new file mode 100644
index 0000000..0585d72
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.RowPresenter.ViewHolder.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.widget.RowPresenter.ViewHolder
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.widget.<A HREF="../../../../reference/android/support/v17/leanback/widget/RowPresenter.ViewHolder.html" target="_top"><font size="+2"><code>RowPresenter.ViewHolder</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.RowPresenter.ViewHolder.getSelectedItem_added()"></A>
+ <nobr><code>Object</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/RowPresenter.ViewHolder.html#getSelectedItem()" target="_top"><code>getSelectedItem</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.RowPresenter.ViewHolder.getSelectedItemViewHolder_added()"></A>
+ <nobr><code>ViewHolder</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/RowPresenter.ViewHolder.html#getSelectedItemViewHolder()" target="_top"><code>getSelectedItemViewHolder</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.SearchBar.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.SearchBar.html
new file mode 100644
index 0000000..d98f101
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.SearchBar.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.widget.SearchBar
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.widget.<A HREF="../../../../reference/android/support/v17/leanback/widget/SearchBar.html" target="_top"><font size="+2"><code>SearchBar</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.SearchBar.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/SearchBar.html#setSearchAffordanceColors(android.support.v17.leanback.widget.SearchOrbView.Colors)" target="_top"><code>setSearchAffordanceColors</code></A>(<code>Colors</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.SearchBar.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/SearchBar.html#setSearchAffordanceColorsInListening(android.support.v17.leanback.widget.SearchOrbView.Colors)" target="_top"><code>setSearchAffordanceColorsInListening</code></A>(<code>Colors</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.SpeechOrbView.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.SpeechOrbView.html
new file mode 100644
index 0000000..8f71818
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.leanback.widget.SpeechOrbView.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.widget.SpeechOrbView
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.leanback.widget.<A HREF="../../../../reference/android/support/v17/leanback/widget/SpeechOrbView.html" target="_top"><font size="+2"><code>SpeechOrbView</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.SpeechOrbView.setListeningOrbColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/SpeechOrbView.html#setListeningOrbColors(android.support.v17.leanback.widget.SearchOrbView.Colors)" target="_top"><code>setListeningOrbColors</code></A>(<code>Colors</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget.SpeechOrbView.setNotListeningOrbColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/leanback/widget/SpeechOrbView.html#setNotListeningOrbColors(android.support.v17.leanback.widget.SearchOrbView.Colors)" target="_top"><code>setNotListeningOrbColors</code></A>(<code>Colors</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.preference.LeanbackPreferenceFragment.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.preference.LeanbackPreferenceFragment.html
new file mode 100644
index 0000000..ad5fd1c
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v17.preference.LeanbackPreferenceFragment.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.preference.LeanbackPreferenceFragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v17.preference.<A HREF="../../../../reference/android/support/v17/preference/LeanbackPreferenceFragment.html" target="_top"><font size="+2"><code>LeanbackPreferenceFragment</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.preference.LeanbackPreferenceFragment.setTitle_added(java.lang.CharSequence)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v17/preference/LeanbackPreferenceFragment.html#setTitle(java.lang.CharSequence)" target="_top"><code>setTitle</code></A>(<code>CharSequence</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.app.Fragment.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.app.Fragment.html
new file mode 100644
index 0000000..e5d0d8c
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.app.Fragment.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.app.Fragment
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.app.<A HREF="../../../../reference/android/support/v4/app/Fragment.html" target="_top"><font size="+2"><code>Fragment</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.Fragment.postponeEnterTransition_added()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v4/app/Fragment.html#postponeEnterTransition()" target="_top"><code>postponeEnterTransition</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.Fragment.startPostponedEnterTransition_added()"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v4/app/Fragment.html#startPostponedEnterTransition()" target="_top"><code>startPostponedEnterTransition</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.app.FragmentActivity.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.app.FragmentActivity.html
new file mode 100644
index 0000000..2e3e30b
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.app.FragmentActivity.html
@@ -0,0 +1,135 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.app.FragmentActivity
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.app.<A HREF="../../../../reference/android/support/v4/app/FragmentActivity.html" target="_top"><font size="+2"><code>FragmentActivity</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.FragmentActivity.getSupportMediaController_changed()"></A>
+ <nobr><code>MediaControllerCompat</code> <A HREF="../../../../reference/android/support/v4/app/FragmentActivity.html#getSupportMediaController()" target="_top"><code>getSupportMediaController</code></A>() </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.FragmentActivity.setSupportMediaController_changed(android.support.v4.media.session.MediaControllerCompat)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v4/app/FragmentActivity.html#setSupportMediaController(android.support.v4.media.session.MediaControllerCompat)" target="_top"><code>setSupportMediaController</code></A>(<code>MediaControllerCompat</code>) </nobr>
+ </TD>
+ <TD VALIGN="TOP" WIDTH="30%">
+<b>Now deprecated</b>.<br>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.app.FragmentManager.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.app.FragmentManager.html
new file mode 100644
index 0000000..9d40584
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.app.FragmentManager.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.app.FragmentManager
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.app.<A HREF="../../../../reference/android/support/v4/app/FragmentManager.html" target="_top"><font size="+2"><code>FragmentManager</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.FragmentManager.registerFragmentLifecycleCallbacks_added(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks, boolean)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v4/app/FragmentManager.html#registerFragmentLifecycleCallbacks(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks, boolean)" target="_top"><code>registerFragmentLifecycleCallbacks</code></A>(<code>FragmentLifecycleCallbacks,</nobr> boolean<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.FragmentManager.unregisterFragmentLifecycleCallbacks_added(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v4/app/FragmentManager.html#unregisterFragmentLifecycleCallbacks(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks)" target="_top"><code>unregisterFragmentLifecycleCallbacks</code></A>(<code>FragmentLifecycleCallbacks</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.app.FragmentTransaction.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.app.FragmentTransaction.html
new file mode 100644
index 0000000..9a8cb40
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.app.FragmentTransaction.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.app.FragmentTransaction
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.app.<A HREF="../../../../reference/android/support/v4/app/FragmentTransaction.html" target="_top"><font size="+2"><code>FragmentTransaction</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app.FragmentTransaction.setAllowOptimization_added(boolean)"></A>
+ <nobr><code>FragmentTransaction</code> <A HREF="../../../../reference/android/support/v4/app/FragmentTransaction.html#setAllowOptimization(boolean)" target="_top"><code>setAllowOptimization</code></A>(<code>boolean</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.media.session.MediaControllerCompat.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.media.session.MediaControllerCompat.html
new file mode 100644
index 0000000..6bb1866
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.media.session.MediaControllerCompat.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.media.session.MediaControllerCompat
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.media.session.<A HREF="../../../../reference/android/support/v4/media/session/MediaControllerCompat.html" target="_top"><font size="+2"><code>MediaControllerCompat</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.media.session.MediaControllerCompat.getMediaController_added(android.app.Activity)"></A>
+ <nobr><code>MediaControllerCompat</code> <A HREF="../../../../reference/android/support/v4/media/session/MediaControllerCompat.html#getMediaController(android.app.Activity)" target="_top"><code>getMediaController</code></A>(<code>Activity</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.media.session.MediaControllerCompat.setMediaController_added(android.app.Activity, android.support.v4.media.session.MediaControllerCompat)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v4/media/session/MediaControllerCompat.html#setMediaController(android.app.Activity, android.support.v4.media.session.MediaControllerCompat)" target="_top"><code>setMediaController</code></A>(<code>Activity,</nobr> MediaControllerCompat<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.os.BuildCompat.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.os.BuildCompat.html
new file mode 100644
index 0000000..a488cb6
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.os.BuildCompat.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.os.BuildCompat
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.os.<A HREF="../../../../reference/android/support/v4/os/BuildCompat.html" target="_top"><font size="+2"><code>BuildCompat</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.os.BuildCompat.isAtLeastO_added()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v4/os/BuildCompat.html#isAtLeastO()" target="_top"><code>isAtLeastO</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.provider.DocumentFile.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.provider.DocumentFile.html
new file mode 100644
index 0000000..ef149ce
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v4.provider.DocumentFile.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.provider.DocumentFile
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v4.provider.<A HREF="../../../../reference/android/support/v4/provider/DocumentFile.html" target="_top"><font size="+2"><code>DocumentFile</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.provider.DocumentFile.isVirtual_added()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v4/provider/DocumentFile.html#isVirtual()" target="_top"><code>isVirtual</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.app.MediaRouteChooserDialog.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.app.MediaRouteChooserDialog.html
new file mode 100644
index 0000000..c9423a4
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.app.MediaRouteChooserDialog.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.app.MediaRouteChooserDialog
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v7.app.<A HREF="../../../../reference/android/support/v7/app/MediaRouteChooserDialog.html" target="_top"><font size="+2"><code>MediaRouteChooserDialog</code></font></A>
+</H2>
+<p><font xsize="+1">The superclass changed from <code>android.app.Dialog</code> to <code>android.support.v7.app.AppCompatDialog</code>.<br></font>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.media.MediaRouter.RouteInfo.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.media.MediaRouter.RouteInfo.html
new file mode 100644
index 0000000..a43ca9f
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.media.MediaRouter.RouteInfo.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.media.MediaRouter.RouteInfo
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v7.media.<A HREF="../../../../reference/android/support/v7/media/MediaRouter.RouteInfo.html" target="_top"><font size="+2"><code>MediaRouter.RouteInfo</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.media.MediaRouter.RouteInfo.isBluetooth_added()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v7/media/MediaRouter.RouteInfo.html#isBluetooth()" target="_top"><code>isBluetooth</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.media.MediaRouter.RouteInfo.isDeviceSpeaker_added()"></A>
+ <nobr><code>boolean</code> <A HREF="../../../../reference/android/support/v7/media/MediaRouter.RouteInfo.html#isDeviceSpeaker()" target="_top"><code>isDeviceSpeaker</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.media.MediaRouter.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.media.MediaRouter.html
new file mode 100644
index 0000000..99cdb64
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.media.MediaRouter.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.media.MediaRouter
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v7.media.<A HREF="../../../../reference/android/support/v7/media/MediaRouter.html" target="_top"><font size="+2"><code>MediaRouter</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.media.MediaRouter.getBluetoothRoute_added()"></A>
+ <nobr><code>RouteInfo</code> <A HREF="../../../../reference/android/support/v7/media/MediaRouter.html#getBluetoothRoute()" target="_top"><code>getBluetoothRoute</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.preference.PreferenceManager.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.preference.PreferenceManager.html
new file mode 100644
index 0000000..dbbb24c
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.preference.PreferenceManager.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.preference.PreferenceManager
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v7.preference.<A HREF="../../../../reference/android/support/v7/preference/PreferenceManager.html" target="_top"><font size="+2"><code>PreferenceManager</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.preference.PreferenceManager.getPreferenceComparisonCallback_added()"></A>
+ <nobr><code>PreferenceComparisonCallback</code> <A HREF="../../../../reference/android/support/v7/preference/PreferenceManager.html#getPreferenceComparisonCallback()" target="_top"><code>getPreferenceComparisonCallback</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.preference.PreferenceManager.setPreferenceComparisonCallback_added(android.support.v7.preference.PreferenceManager.PreferenceComparisonCallback)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v7/preference/PreferenceManager.html#setPreferenceComparisonCallback(android.support.v7.preference.PreferenceManager.PreferenceComparisonCallback)" target="_top"><code>setPreferenceComparisonCallback</code></A>(<code>PreferenceComparisonCallback</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.widget.LinearLayoutCompat.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.widget.LinearLayoutCompat.html
new file mode 100644
index 0000000..bfad8d8
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.widget.LinearLayoutCompat.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.widget.LinearLayoutCompat
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v7.widget.<A HREF="../../../../reference/android/support/v7/widget/LinearLayoutCompat.html" target="_top"><font size="+2"><code>LinearLayoutCompat</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.widget.LinearLayoutCompat.getGravity_added()"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v7/widget/LinearLayoutCompat.html#getGravity()" target="_top"><code>getGravity</code></A>()</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.widget.RecyclerView.RecycledViewPool.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.widget.RecyclerView.RecycledViewPool.html
new file mode 100644
index 0000000..070d12c
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.widget.RecyclerView.RecycledViewPool.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.widget.RecyclerView.RecycledViewPool
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v7.widget.<A HREF="../../../../reference/android/support/v7/widget/RecyclerView.RecycledViewPool.html" target="_top"><font size="+2"><code>RecyclerView.RecycledViewPool</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.widget.RecyclerView.RecycledViewPool.getRecycledViewCount_added(int)"></A>
+ <nobr><code>int</code> <A HREF="../../../../reference/android/support/v7/widget/RecyclerView.RecycledViewPool.html#getRecycledViewCount(int)" target="_top"><code>getRecycledViewCount</code></A>(<code>int</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.widget.RecyclerView.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.widget.RecyclerView.html
new file mode 100644
index 0000000..712b113
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.widget.RecyclerView.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.widget.RecyclerView
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v7.widget.<A HREF="../../../../reference/android/support/v7/widget/RecyclerView.html" target="_top"><font size="+2"><code>RecyclerView</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.widget.RecyclerView.smoothScrollBy_added(int, int, android.view.animation.Interpolator)"></A>
+ <nobr><code>void</code> <A HREF="../../../../reference/android/support/v7/widget/RecyclerView.html#smoothScrollBy(int, int, android.view.animation.Interpolator)" target="_top"><code>smoothScrollBy</code></A>(<code>int,</nobr> int<nobr>,</nobr> Interpolator<nobr><nobr></code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.widget.SnapHelper.html b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.widget.SnapHelper.html
new file mode 100644
index 0000000..4db82da
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/android.support.v7.widget.SnapHelper.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.widget.SnapHelper
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Class android.support.v7.widget.<A HREF="../../../../reference/android/support/v7/widget/SnapHelper.html" target="_top"><font size="+2"><code>SnapHelper</code></font></A>
+</H2>
+<a NAME="constructors"></a>
+<a NAME="methods"></a>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Methods" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Methods</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.widget.SnapHelper.createSnapScroller_added(android.support.v7.widget.RecyclerView.LayoutManager)"></A>
+ <nobr><code>LinearSmoothScroller</code> <A HREF="../../../../reference/android/support/v7/widget/SnapHelper.html#createSnapScroller(android.support.v7.widget.RecyclerView.LayoutManager)" target="_top"><code>createSnapScroller</code></A>(<code>LayoutManager</code>)</nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<a NAME="fields"></a>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/changes-summary.html b/docs/html/sdk/support_api_diff/25.1.0/changes/changes-summary.html
new file mode 100644
index 0000000..1924404
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/changes-summary.html
@@ -0,0 +1,225 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Support Library API Differences Report
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<body class="gc-documentation">
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+ <div id="docTitleContainer">
+ <h1>Support Library API Differences Report</h1>
+<p>This report details the changes in the Android Support Library API between two versions.
+It shows additions, modifications, and removals for packages, classes, methods, and fields.
+The report also includes general statistics that characterize the extent and type of the differences.</p>
+<p>This report is based a comparison of the Support Library API specifications
+whose version level identifiers are given in the upper-right corner of this page. It compares a
+newer "to" version's API to an older "from" version's API, noting all changes relative to the
+older API. So, for example, API elements marked as removed are no longer present in the "to"
+API specification.</p>
+<p>To navigate the report, use the "Select a Diffs Index" and "Filter the Index"
+controls on the left. The report uses text formatting to indicate <em>interface names</em>,
+<a href= ><code>links to reference documentation</code></a>, and <a href= >links to change
+description</a>. The statistics are accessible from the "Statistics" link in the upper-right corner.</p>
+<p>For more information about the Android API and SDK,
+see the <a href="http://developer.android.com/index.html" target="_top">Android Developers site</a>.</p>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Packages" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=3>Changed Packages</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.design.widget"></A>
+ <nobr><A HREF="pkg_android.support.design.widget.html">android.support.design.widget</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.graphics.drawable"></A>
+ <nobr><A HREF="pkg_android.support.graphics.drawable.html">android.support.graphics.drawable</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.app"></A>
+ <nobr><A HREF="pkg_android.support.v17.leanback.app.html">android.support.v17.leanback.app</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.leanback.widget"></A>
+ <nobr><A HREF="pkg_android.support.v17.leanback.widget.html">android.support.v17.leanback.widget</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v17.preference"></A>
+ <nobr><A HREF="pkg_android.support.v17.preference.html">android.support.v17.preference</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.app"></A>
+ <nobr><A HREF="pkg_android.support.v4.app.html">android.support.v4.app</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.media.session"></A>
+ <nobr><A HREF="pkg_android.support.v4.media.session.html">android.support.v4.media.session</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.os"></A>
+ <nobr><A HREF="pkg_android.support.v4.os.html">android.support.v4.os</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.provider"></A>
+ <nobr><A HREF="pkg_android.support.v4.provider.html">android.support.v4.provider</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v4.util"></A>
+ <nobr><A HREF="pkg_android.support.v4.util.html">android.support.v4.util</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.app"></A>
+ <nobr><A HREF="pkg_android.support.v7.app.html">android.support.v7.app</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.media"></A>
+ <nobr><A HREF="pkg_android.support.v7.media.html">android.support.v7.media</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.preference"></A>
+ <nobr><A HREF="pkg_android.support.v7.preference.html">android.support.v7.preference</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="android.support.v7.widget"></A>
+ <nobr><A HREF="pkg_android.support.v7.widget.html">android.support.v7.widget</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<!-- End of API section -->
+<!-- Start of packages section -->
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/classes_index_additions.html b/docs/html/sdk/support_api_diff/25.1.0/changes/classes_index_additions.html
new file mode 100644
index 0000000..d47dee0
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/classes_index_additions.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="classes_index_all.html" class="staysblack">All Classes</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<b>Additions</b>
+ <br>
+<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.graphics.drawable.html#AnimatedVectorDrawableCompat" class="hiddenlink" target="rightframe"><b>AnimatedVectorDrawableCompat</b></A><br>
+<A HREF="pkg_android.support.v4.util.html#ArraySet" class="hiddenlink" target="rightframe"><b>ArraySet</b></A><br>
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.design.widget.html#BaseTransientBottomBar" class="hiddenlink" target="rightframe"><b>BaseTransientBottomBar</b></A><br>
+<A HREF="pkg_android.support.design.widget.html#BaseTransientBottomBar.BaseCallback" class="hiddenlink" target="rightframe"><b>BaseTransientBottomBar.BaseCallback</b></A><br>
+<A HREF="pkg_android.support.design.widget.html#BaseTransientBottomBar.ContentViewCallback" class="hiddenlink" target="rightframe"><b><i>BaseTransientBottomBar.ContentViewCallback</i></b></A><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v4.app.html#FragmentManager.FragmentLifecycleCallbacks" class="hiddenlink" target="rightframe"><b>FragmentManager.FragmentLifecycleCallbacks</b></A><br>
+<A NAME="P"></A>
+<br><font size="+2">P</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#PagerSnapHelper" class="hiddenlink" target="rightframe"><b>PagerSnapHelper</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackControlGlue.InputEventHandler" class="hiddenlink" target="rightframe"><b><i>PlaybackControlGlue.InputEventHandler</i></b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackFragment" class="hiddenlink" target="rightframe"><b>PlaybackFragment</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackFragment.OnFadeCompleteListener" class="hiddenlink" target="rightframe"><b>PlaybackFragment.OnFadeCompleteListener</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackFragmentGlueHost" class="hiddenlink" target="rightframe"><b>PlaybackFragmentGlueHost</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue" class="hiddenlink" target="rightframe"><b>PlaybackGlue</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue.HostLifecycleCallback" class="hiddenlink" target="rightframe"><b>PlaybackGlue.HostLifecycleCallback</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue.PlaybackGlueHost" class="hiddenlink" target="rightframe"><b>PlaybackGlue.PlaybackGlueHost</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue.PlayerCallback" class="hiddenlink" target="rightframe"><b>PlaybackGlue.PlayerCallback</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.widget.html#PlaybackRowPresenter" class="hiddenlink" target="rightframe"><b>PlaybackRowPresenter</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.widget.html#PlaybackRowPresenter.ViewHolder" class="hiddenlink" target="rightframe"><b>PlaybackRowPresenter.ViewHolder</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackSupportFragment" class="hiddenlink" target="rightframe"><b>PlaybackSupportFragment</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackSupportFragment.OnFadeCompleteListener" class="hiddenlink" target="rightframe"><b>PlaybackSupportFragment.OnFadeCompleteListener</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackSupportFragmentGlueHost" class="hiddenlink" target="rightframe"><b>PlaybackSupportFragmentGlueHost</b></A><br>
+<A HREF="pkg_android.support.v7.preference.html#PreferenceManager.PreferenceComparisonCallback" class="hiddenlink" target="rightframe"><b>PreferenceManager.PreferenceComparisonCallback</b></A><br>
+<A HREF="pkg_android.support.v7.preference.html#PreferenceManager.SimplePreferenceComparisonCallback" class="hiddenlink" target="rightframe"><b>PreferenceManager.SimplePreferenceComparisonCallback</b></A><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#P"><font size="-2">P</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.preference.html#SeekBarPreference" class="hiddenlink" target="rightframe"><b>SeekBarPreference</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#SurfaceHolderGlueHost" class="hiddenlink" target="rightframe"><b><i>SurfaceHolderGlueHost</i></b></A><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/classes_index_all.html b/docs/html/sdk/support_api_diff/25.1.0/changes/classes_index_all.html
new file mode 100644
index 0000000..1540eb8
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/classes_index_all.html
@@ -0,0 +1,344 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Classes</b>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.graphics.drawable.html#AnimatedVectorDrawableCompat" class="hiddenlink" target="rightframe"><b>AnimatedVectorDrawableCompat</b></A><br>
+<A HREF="pkg_android.support.v4.util.html#ArraySet" class="hiddenlink" target="rightframe"><b>ArraySet</b></A><br>
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.app.BackgroundManager.html" class="hiddenlink" target="rightframe">BackgroundManager</A><br>
+<A HREF="android.support.v17.leanback.widget.BaseCardView.html" class="hiddenlink" target="rightframe">BaseCardView</A><br>
+<A HREF="android.support.v17.leanback.app.BaseRowFragment.html" class="hiddenlink" target="rightframe">BaseRowFragment</A><br>
+<A HREF="android.support.v17.leanback.app.BaseRowSupportFragment.html" class="hiddenlink" target="rightframe">BaseRowSupportFragment</A><br>
+<A HREF="pkg_android.support.design.widget.html#BaseTransientBottomBar" class="hiddenlink" target="rightframe"><b>BaseTransientBottomBar</b></A><br>
+<A HREF="pkg_android.support.design.widget.html#BaseTransientBottomBar.BaseCallback" class="hiddenlink" target="rightframe"><b>BaseTransientBottomBar.BaseCallback</b></A><br>
+<A HREF="pkg_android.support.design.widget.html#BaseTransientBottomBar.ContentViewCallback" class="hiddenlink" target="rightframe"><b><i>BaseTransientBottomBar.ContentViewCallback</i></b></A><br>
+<A HREF="android.support.v17.leanback.app.BrowseFragment.html" class="hiddenlink" target="rightframe">BrowseFragment</A><br>
+<A HREF="android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.html" class="hiddenlink" target="rightframe">BrowseFragment.MainFragmentRowsAdapter</A><br>
+<A HREF="android.support.v17.leanback.widget.BrowseFrameLayout.html" class="hiddenlink" target="rightframe">BrowseFrameLayout</A><br>
+<A HREF="android.support.v17.leanback.app.BrowseSupportFragment.html" class="hiddenlink" target="rightframe">BrowseSupportFragment</A><br>
+<A HREF="android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.html" class="hiddenlink" target="rightframe">BrowseSupportFragment.MainFragmentRowsAdapter</A><br>
+<A HREF="android.support.v4.os.BuildCompat.html" class="hiddenlink" target="rightframe">BuildCompat</A><br>
+<A NAME="D"></A>
+<br><font size="+2">D</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.provider.DocumentFile.html" class="hiddenlink" target="rightframe">DocumentFile</A><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.app.Fragment.html" class="hiddenlink" target="rightframe">Fragment</A><br>
+<A HREF="android.support.v4.app.FragmentActivity.html" class="hiddenlink" target="rightframe">FragmentActivity</A><br>
+<A HREF="android.support.v4.app.FragmentManager.html" class="hiddenlink" target="rightframe">FragmentManager</A><br>
+<A HREF="pkg_android.support.v4.app.html#FragmentManager.FragmentLifecycleCallbacks" class="hiddenlink" target="rightframe"><b>FragmentManager.FragmentLifecycleCallbacks</b></A><br>
+<A HREF="android.support.v4.app.FragmentTransaction.html" class="hiddenlink" target="rightframe">FragmentTransaction</A><br>
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html" class="hiddenlink" target="rightframe">GuidedActionsStylist</A><br>
+<A HREF="android.support.v17.leanback.app.GuidedStepFragment.html" class="hiddenlink" target="rightframe">GuidedStepFragment</A><br>
+<A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html" class="hiddenlink" target="rightframe">GuidedStepSupportFragment</A><br>
+<A NAME="H"></A>
+<br><font size="+2">H</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.widget.HeaderItem.html" class="hiddenlink" target="rightframe">HeaderItem</A><br>
+<A NAME="L"></A>
+<br><font size="+2">L</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.preference.LeanbackPreferenceFragment.html" class="hiddenlink" target="rightframe">LeanbackPreferenceFragment</A><br>
+<A HREF="android.support.v7.widget.LinearLayoutCompat.html" class="hiddenlink" target="rightframe">LinearLayoutCompat</A><br>
+<A NAME="M"></A>
+<br><font size="+2">M</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.media.session.MediaControllerCompat.html" class="hiddenlink" target="rightframe">MediaControllerCompat</A><br>
+<A HREF="android.support.v17.leanback.app.MediaControllerGlue.html" class="hiddenlink" target="rightframe">MediaControllerGlue</A><br>
+<A HREF="android.support.v7.app.MediaRouteChooserDialog.html" class="hiddenlink" target="rightframe">MediaRouteChooserDialog</A><br>
+<A HREF="android.support.v7.media.MediaRouter.html" class="hiddenlink" target="rightframe">MediaRouter</A><br>
+<A HREF="android.support.v7.media.MediaRouter.RouteInfo.html" class="hiddenlink" target="rightframe">MediaRouter.RouteInfo</A><br>
+<A NAME="O"></A>
+<br><font size="+2">O</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.widget.ObjectAdapter.html" class="hiddenlink" target="rightframe">ObjectAdapter</A><br>
+<A HREF="android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.html" class="hiddenlink" target="rightframe">OnChildViewHolderSelectedListener</A><br>
+<A NAME="P"></A>
+<br><font size="+2">P</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="pkg_android.support.v7.widget.html#PagerSnapHelper" class="hiddenlink" target="rightframe"><b>PagerSnapHelper</b></A><br>
+<A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html" class="hiddenlink" target="rightframe">PlaybackControlGlue</A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackControlGlue.InputEventHandler" class="hiddenlink" target="rightframe"><b><i>PlaybackControlGlue.InputEventHandler</i></b></A><br>
+<A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html" class="hiddenlink" target="rightframe">PlaybackControlsRow</A><br>
+<A HREF="android.support.v17.leanback.widget.PlaybackControlsRowPresenter.html" class="hiddenlink" target="rightframe">PlaybackControlsRowPresenter</A><br>
+<A HREF="android.support.v17.leanback.widget.PlaybackControlsRowPresenter.ViewHolder.html" class="hiddenlink" target="rightframe">PlaybackControlsRowPresenter.ViewHolder</A><br>
+<A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html" class="hiddenlink" target="rightframe">PlaybackControlSupportGlue</A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackFragment" class="hiddenlink" target="rightframe"><b>PlaybackFragment</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackFragment.OnFadeCompleteListener" class="hiddenlink" target="rightframe"><b>PlaybackFragment.OnFadeCompleteListener</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackFragmentGlueHost" class="hiddenlink" target="rightframe"><b>PlaybackFragmentGlueHost</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue" class="hiddenlink" target="rightframe"><b>PlaybackGlue</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue.HostLifecycleCallback" class="hiddenlink" target="rightframe"><b>PlaybackGlue.HostLifecycleCallback</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue.PlaybackGlueHost" class="hiddenlink" target="rightframe"><b>PlaybackGlue.PlaybackGlueHost</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackGlue.PlayerCallback" class="hiddenlink" target="rightframe"><b>PlaybackGlue.PlayerCallback</b></A><br>
+<A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html" class="hiddenlink" target="rightframe">PlaybackOverlayFragment</A><br>
+<A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.html" class="hiddenlink" target="rightframe"><i>PlaybackOverlayFragment.InputEventHandler</i></A><br>
+<A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html" class="hiddenlink" target="rightframe">PlaybackOverlaySupportFragment</A><br>
+<A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.html" class="hiddenlink" target="rightframe"><i>PlaybackOverlaySupportFragment.InputEventHandler</i></A><br>
+<A HREF="pkg_android.support.v17.leanback.widget.html#PlaybackRowPresenter" class="hiddenlink" target="rightframe"><b>PlaybackRowPresenter</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.widget.html#PlaybackRowPresenter.ViewHolder" class="hiddenlink" target="rightframe"><b>PlaybackRowPresenter.ViewHolder</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackSupportFragment" class="hiddenlink" target="rightframe"><b>PlaybackSupportFragment</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackSupportFragment.OnFadeCompleteListener" class="hiddenlink" target="rightframe"><b>PlaybackSupportFragment.OnFadeCompleteListener</b></A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#PlaybackSupportFragmentGlueHost" class="hiddenlink" target="rightframe"><b>PlaybackSupportFragmentGlueHost</b></A><br>
+<A HREF="android.support.v7.preference.PreferenceManager.html" class="hiddenlink" target="rightframe">PreferenceManager</A><br>
+<A HREF="pkg_android.support.v7.preference.html#PreferenceManager.PreferenceComparisonCallback" class="hiddenlink" target="rightframe"><b>PreferenceManager.PreferenceComparisonCallback</b></A><br>
+<A HREF="pkg_android.support.v7.preference.html#PreferenceManager.SimplePreferenceComparisonCallback" class="hiddenlink" target="rightframe"><b>PreferenceManager.SimplePreferenceComparisonCallback</b></A><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v7.widget.RecyclerView.html" class="hiddenlink" target="rightframe">RecyclerView</A><br>
+<A HREF="android.support.v7.widget.RecyclerView.RecycledViewPool.html" class="hiddenlink" target="rightframe">RecyclerView.RecycledViewPool</A><br>
+<A HREF="android.support.v17.leanback.widget.RowPresenter.ViewHolder.html" class="hiddenlink" target="rightframe">RowPresenter.ViewHolder</A><br>
+<A HREF="android.support.v17.leanback.app.RowsFragment.html" class="hiddenlink" target="rightframe">RowsFragment</A><br>
+<A HREF="android.support.v17.leanback.app.RowsSupportFragment.html" class="hiddenlink" target="rightframe">RowsSupportFragment</A><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.widget.SearchBar.html" class="hiddenlink" target="rightframe">SearchBar</A><br>
+<A HREF="android.support.v17.leanback.app.SearchFragment.html" class="hiddenlink" target="rightframe">SearchFragment</A><br>
+<A HREF="android.support.v17.leanback.app.SearchSupportFragment.html" class="hiddenlink" target="rightframe">SearchSupportFragment</A><br>
+<A HREF="pkg_android.support.v7.preference.html#SeekBarPreference" class="hiddenlink" target="rightframe"><b>SeekBarPreference</b></A><br>
+<A HREF="android.support.design.widget.Snackbar.html" class="hiddenlink" target="rightframe">Snackbar</A><br>
+<A HREF="android.support.design.widget.Snackbar.Callback.html" class="hiddenlink" target="rightframe">Snackbar.Callback</A><br>
+<A HREF="android.support.v7.widget.SnapHelper.html" class="hiddenlink" target="rightframe">SnapHelper</A><br>
+<A HREF="android.support.v17.leanback.widget.SpeechOrbView.html" class="hiddenlink" target="rightframe">SpeechOrbView</A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html#SurfaceHolderGlueHost" class="hiddenlink" target="rightframe"><b><i>SurfaceHolderGlueHost</i></b></A><br>
+<A NAME="T"></A>
+<br><font size="+2">T</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.design.widget.TextInputLayout.html" class="hiddenlink" target="rightframe">TextInputLayout</A><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/classes_index_changes.html b/docs/html/sdk/support_api_diff/25.1.0/changes/classes_index_changes.html
new file mode 100644
index 0000000..8265878
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/classes_index_changes.html
@@ -0,0 +1,292 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="classes_index_all.html" class="staysblack">All Classes</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="B"></A>
+<br><font size="+2">B</font>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.app.BackgroundManager.html" class="hiddenlink" target="rightframe">BackgroundManager</A><br>
+<A HREF="android.support.v17.leanback.widget.BaseCardView.html" class="hiddenlink" target="rightframe">BaseCardView</A><br>
+<A HREF="android.support.v17.leanback.app.BaseRowFragment.html" class="hiddenlink" target="rightframe">BaseRowFragment</A><br>
+<A HREF="android.support.v17.leanback.app.BaseRowSupportFragment.html" class="hiddenlink" target="rightframe">BaseRowSupportFragment</A><br>
+<A HREF="android.support.v17.leanback.app.BrowseFragment.html" class="hiddenlink" target="rightframe">BrowseFragment</A><br>
+<A HREF="android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.html" class="hiddenlink" target="rightframe">BrowseFragment.MainFragmentRowsAdapter</A><br>
+<A HREF="android.support.v17.leanback.widget.BrowseFrameLayout.html" class="hiddenlink" target="rightframe">BrowseFrameLayout</A><br>
+<A HREF="android.support.v17.leanback.app.BrowseSupportFragment.html" class="hiddenlink" target="rightframe">BrowseSupportFragment</A><br>
+<A HREF="android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.html" class="hiddenlink" target="rightframe">BrowseSupportFragment.MainFragmentRowsAdapter</A><br>
+<A HREF="android.support.v4.os.BuildCompat.html" class="hiddenlink" target="rightframe">BuildCompat</A><br>
+<A NAME="D"></A>
+<br><font size="+2">D</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.provider.DocumentFile.html" class="hiddenlink" target="rightframe">DocumentFile</A><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.app.Fragment.html" class="hiddenlink" target="rightframe">Fragment</A><br>
+<A HREF="android.support.v4.app.FragmentActivity.html" class="hiddenlink" target="rightframe">FragmentActivity</A><br>
+<A HREF="android.support.v4.app.FragmentManager.html" class="hiddenlink" target="rightframe">FragmentManager</A><br>
+<A HREF="android.support.v4.app.FragmentTransaction.html" class="hiddenlink" target="rightframe">FragmentTransaction</A><br>
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html" class="hiddenlink" target="rightframe">GuidedActionsStylist</A><br>
+<A HREF="android.support.v17.leanback.app.GuidedStepFragment.html" class="hiddenlink" target="rightframe">GuidedStepFragment</A><br>
+<A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html" class="hiddenlink" target="rightframe">GuidedStepSupportFragment</A><br>
+<A NAME="H"></A>
+<br><font size="+2">H</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.widget.HeaderItem.html" class="hiddenlink" target="rightframe">HeaderItem</A><br>
+<A NAME="L"></A>
+<br><font size="+2">L</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.preference.LeanbackPreferenceFragment.html" class="hiddenlink" target="rightframe">LeanbackPreferenceFragment</A><br>
+<A HREF="android.support.v7.widget.LinearLayoutCompat.html" class="hiddenlink" target="rightframe">LinearLayoutCompat</A><br>
+<A NAME="M"></A>
+<br><font size="+2">M</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v4.media.session.MediaControllerCompat.html" class="hiddenlink" target="rightframe">MediaControllerCompat</A><br>
+<A HREF="android.support.v17.leanback.app.MediaControllerGlue.html" class="hiddenlink" target="rightframe">MediaControllerGlue</A><br>
+<A HREF="android.support.v7.app.MediaRouteChooserDialog.html" class="hiddenlink" target="rightframe">MediaRouteChooserDialog</A><br>
+<A HREF="android.support.v7.media.MediaRouter.html" class="hiddenlink" target="rightframe">MediaRouter</A><br>
+<A HREF="android.support.v7.media.MediaRouter.RouteInfo.html" class="hiddenlink" target="rightframe">MediaRouter.RouteInfo</A><br>
+<A NAME="O"></A>
+<br><font size="+2">O</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.widget.ObjectAdapter.html" class="hiddenlink" target="rightframe">ObjectAdapter</A><br>
+<A HREF="android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.html" class="hiddenlink" target="rightframe">OnChildViewHolderSelectedListener</A><br>
+<A NAME="P"></A>
+<br><font size="+2">P</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html" class="hiddenlink" target="rightframe">PlaybackControlGlue</A><br>
+<A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html" class="hiddenlink" target="rightframe">PlaybackControlsRow</A><br>
+<A HREF="android.support.v17.leanback.widget.PlaybackControlsRowPresenter.html" class="hiddenlink" target="rightframe">PlaybackControlsRowPresenter</A><br>
+<A HREF="android.support.v17.leanback.widget.PlaybackControlsRowPresenter.ViewHolder.html" class="hiddenlink" target="rightframe">PlaybackControlsRowPresenter.ViewHolder</A><br>
+<A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html" class="hiddenlink" target="rightframe">PlaybackControlSupportGlue</A><br>
+<A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html" class="hiddenlink" target="rightframe">PlaybackOverlayFragment</A><br>
+<A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.html" class="hiddenlink" target="rightframe"><i>PlaybackOverlayFragment.InputEventHandler</i></A><br>
+<A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html" class="hiddenlink" target="rightframe">PlaybackOverlaySupportFragment</A><br>
+<A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.html" class="hiddenlink" target="rightframe"><i>PlaybackOverlaySupportFragment.InputEventHandler</i></A><br>
+<A HREF="android.support.v7.preference.PreferenceManager.html" class="hiddenlink" target="rightframe">PreferenceManager</A><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v7.widget.RecyclerView.html" class="hiddenlink" target="rightframe">RecyclerView</A><br>
+<A HREF="android.support.v7.widget.RecyclerView.RecycledViewPool.html" class="hiddenlink" target="rightframe">RecyclerView.RecycledViewPool</A><br>
+<A HREF="android.support.v17.leanback.widget.RowPresenter.ViewHolder.html" class="hiddenlink" target="rightframe">RowPresenter.ViewHolder</A><br>
+<A HREF="android.support.v17.leanback.app.RowsFragment.html" class="hiddenlink" target="rightframe">RowsFragment</A><br>
+<A HREF="android.support.v17.leanback.app.RowsSupportFragment.html" class="hiddenlink" target="rightframe">RowsSupportFragment</A><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#T"><font size="-2">T</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.v17.leanback.widget.SearchBar.html" class="hiddenlink" target="rightframe">SearchBar</A><br>
+<A HREF="android.support.v17.leanback.app.SearchFragment.html" class="hiddenlink" target="rightframe">SearchFragment</A><br>
+<A HREF="android.support.v17.leanback.app.SearchSupportFragment.html" class="hiddenlink" target="rightframe">SearchSupportFragment</A><br>
+<A HREF="android.support.design.widget.Snackbar.html" class="hiddenlink" target="rightframe">Snackbar</A><br>
+<A HREF="android.support.design.widget.Snackbar.Callback.html" class="hiddenlink" target="rightframe">Snackbar.Callback</A><br>
+<A HREF="android.support.v7.widget.SnapHelper.html" class="hiddenlink" target="rightframe">SnapHelper</A><br>
+<A HREF="android.support.v17.leanback.widget.SpeechOrbView.html" class="hiddenlink" target="rightframe">SpeechOrbView</A><br>
+<A NAME="T"></A>
+<br><font size="+2">T</font>
+<a href="#B"><font size="-2">B</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#L"><font size="-2">L</font></a>
+<a href="#M"><font size="-2">M</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<A HREF="android.support.design.widget.TextInputLayout.html" class="hiddenlink" target="rightframe">TextInputLayout</A><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/classes_index_removals.html b/docs/html/sdk/support_api_diff/25.1.0/changes/classes_index_removals.html
new file mode 100644
index 0000000..e6da73f
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/classes_index_removals.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Class Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Classes" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="classes_index_all.html" class="staysblack">All Classes</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="classes_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="classes_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/constructors_index_additions.html b/docs/html/sdk/support_api_diff/25.1.0/changes/constructors_index_additions.html
new file mode 100644
index 0000000..dcd6a78
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/constructors_index_additions.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="constructors_index_all.html" class="staysblack">All Constructors</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<b>Additions</b>
+ <br>
+<A HREF="constructors_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="M"></A>
+<br><font size="+2">M</font>
+<a href="#P"><font size="-2">P</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.ctor_added(android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])" class="hiddenlink" target="rightframe"><b>MediaControllerGlue</b>
+(<code>Context, PlaybackGlueHost, int[], int[]</code>)</A></nobr> constructor<br>
+<A NAME="P"></A>
+<br><font size="+2">P</font>
+<a href="#M"><font size="-2">M</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.ctor_added(android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])" class="hiddenlink" target="rightframe"><b>PlaybackControlGlue</b>
+(<code>Context, PlaybackGlueHost, int[], int[]</code>)</A></nobr> constructor<br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/constructors_index_all.html b/docs/html/sdk/support_api_diff/25.1.0/changes/constructors_index_all.html
new file mode 100644
index 0000000..7bb3a5a
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/constructors_index_all.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Constructors</b>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="constructors_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="constructors_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="M"></A>
+<br><font size="+2">M</font>
+<a href="#P"><font size="-2">P</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>MediaControllerGlue</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.ctor_added(android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])" class="hiddenlink" target="rightframe"><b>MediaControllerGlue</b>
+(<code>Context, PlaybackGlueHost, int[], int[]</code>)</A></nobr> constructor<br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[])" class="hiddenlink" target="rightframe">MediaControllerGlue
+(<code>Context, PlaybackOverlayFragment, int[]</code>)</A></nobr> constructor<br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[])" class="hiddenlink" target="rightframe">MediaControllerGlue
+(<code>Context, PlaybackOverlayFragment, int[], int[]</code>)</A></nobr> constructor<br>
+<A NAME="P"></A>
+<br><font size="+2">P</font>
+<a href="#M"><font size="-2">M</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>PlaybackControlGlue</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.ctor_added(android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])" class="hiddenlink" target="rightframe"><b>PlaybackControlGlue</b>
+(<code>Context, PlaybackGlueHost, int[], int[]</code>)</A></nobr> constructor<br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[])" class="hiddenlink" target="rightframe">PlaybackControlGlue
+(<code>Context, PlaybackOverlayFragment, int[]</code>)</A></nobr> constructor<br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[])" class="hiddenlink" target="rightframe">PlaybackControlGlue
+(<code>Context, PlaybackOverlayFragment, int[], int[]</code>)</A></nobr> constructor<br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/constructors_index_changes.html b/docs/html/sdk/support_api_diff/25.1.0/changes/constructors_index_changes.html
new file mode 100644
index 0000000..24f5247
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/constructors_index_changes.html
@@ -0,0 +1,81 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="constructors_index_all.html" class="staysblack">All Constructors</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="constructors_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="M"></A>
+<br><font size="+2">M</font>
+<a href="#P"><font size="-2">P</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>MediaControllerGlue</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[])" class="hiddenlink" target="rightframe">MediaControllerGlue
+(<code>Context, PlaybackOverlayFragment, int[]</code>)</A></nobr> constructor<br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[])" class="hiddenlink" target="rightframe">MediaControllerGlue
+(<code>Context, PlaybackOverlayFragment, int[], int[]</code>)</A></nobr> constructor<br>
+<A NAME="P"></A>
+<br><font size="+2">P</font>
+<a href="#M"><font size="-2">M</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>PlaybackControlGlue</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[])" class="hiddenlink" target="rightframe">PlaybackControlGlue
+(<code>Context, PlaybackOverlayFragment, int[]</code>)</A></nobr> constructor<br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[])" class="hiddenlink" target="rightframe">PlaybackControlGlue
+(<code>Context, PlaybackOverlayFragment, int[], int[]</code>)</A></nobr> constructor<br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/constructors_index_removals.html b/docs/html/sdk/support_api_diff/25.1.0/changes/constructors_index_removals.html
new file mode 100644
index 0000000..f1a9952
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/constructors_index_removals.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Constructor Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Constructors" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="constructors_index_all.html" class="staysblack">All Constructors</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<A HREF="constructors_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="constructors_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/fields_index_additions.html b/docs/html/sdk/support_api_diff/25.1.0/changes/fields_index_additions.html
new file mode 100644
index 0000000..215cabf
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/fields_index_additions.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="fields_index_all.html" class="staysblack">All Fields</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<font color="#999999">Additions</font>
+ <br>
+<font color="#999999">Changes</font>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/fields_index_all.html b/docs/html/sdk/support_api_diff/25.1.0/changes/fields_index_all.html
new file mode 100644
index 0000000..ffe49f3
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/fields_index_all.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Fields</b>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<font color="#999999">Additions</font>
+ <br>
+<font color="#999999">Changes</font>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/fields_index_changes.html b/docs/html/sdk/support_api_diff/25.1.0/changes/fields_index_changes.html
new file mode 100644
index 0000000..72c26d9
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/fields_index_changes.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="fields_index_all.html" class="staysblack">All Fields</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<font color="#999999">Additions</font>
+ <br>
+<font color="#999999">Changes</font>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/fields_index_removals.html b/docs/html/sdk/support_api_diff/25.1.0/changes/fields_index_removals.html
new file mode 100644
index 0000000..259c00e
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/fields_index_removals.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Field Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Fields" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="fields_index_all.html" class="staysblack">All Fields</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<font color="#999999">Additions</font>
+ <br>
+<font color="#999999">Changes</font>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/jdiff_help.html b/docs/html/sdk/support_api_diff/25.1.0/changes/jdiff_help.html
new file mode 100644
index 0000000..6449baf
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/jdiff_help.html
@@ -0,0 +1,134 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+JDiff Help
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<TABLE summary="Navigation bar" BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+ <TABLE summary="Navigation bar" BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../../reference/index.html" target="_top"><FONT CLASS="NavBarFont1"><B><code>25.1.0</code></B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="changes-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT> </TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="jdiff_statistics.html"><FONT CLASS="NavBarFont1"><B>Statistics</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT> </TD>
+ </TR>
+ </TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM><b>Generated by<br><a href="http://www.jdiff.org" class="staysblack" target="_top">JDiff</a></b></EM></TD>
+</TR>
+<TR>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell2"><FONT SIZE="-2"></FONT>
+</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../changes.html" TARGET="_top"><B>FRAMES</B></A>
+ <A HREF="jdiff_help.html" TARGET="_top"><B>NO FRAMES</B></A></FONT></TD>
+</TR>
+</TABLE>
+<HR>
+<!-- End of nav bar -->
+<center>
+<H1>JDiff Documentation</H1>
+</center>
+<BLOCKQUOTE>
+JDiff is a <a href="http://java.sun.com/j2se/javadoc/" target="_top">Javadoc</a> doclet which generates a report of the API differences between two versions of a product. It does not report changes in Javadoc comments, or changes in what a class or method does.
+This help page describes the different parts of the output from JDiff.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+ See the reference page in the <a href="http://www.jdiff.org">source for JDiff</a> for information about how to generate a report like this one.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+The indexes shown in the top-left frame help show each type of change in more detail. The index "All Differences" contains all the differences between the APIs, in alphabetical order.
+These indexes all use the same format:
+<ul>
+<li>Removed packages, classes, constructors, methods and fields are <strike>struck through</strike>.</li>
+<li>Added packages, classes, constructors, methods and fields appear in <b>bold</b>.</li>
+<li>Changed packages, classes, constructors, methods and fields appear in normal text.</li>
+</ul>
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+You can always tell when you are reading a JDiff page, rather than a Javadoc page, by the color of the index bar and the color of the background.
+Links which take you to a Javadoc page are always in a <code>typewriter</code> font.
+Just like Javadoc, all interface names are in <i>italic</i>, and class names are not italicized. Where there are multiple entries in an index with the same name, the heading for them is also in italics, but is not a link.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3><b><code>Javadoc</code></b></H3>
+This is a link to the <a href="../../../../reference/index.html" target="_top">top-level</a> Javadoc page for the new version of the product.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Overview</H3>
+The <a href="changes-summary.html">overview</a> is the top-level summary of what was removed, added and changed between versions.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Package</H3>
+This is a link to the package containing the current changed class or interface.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Class</H3>
+This is highlighted when you are looking at the changed class or interface.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Text Changes</H3>
+This is a link to the top-level index of all documentation changes for the current package or class.
+If it is not present, then there are no documentation changes for the current package or class.
+This link can be removed entirely by not using the <code>-docchanges</code> option.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Statistics</H3>
+This is a link to a page which shows statistics about the changes between the two APIs.
+This link can be removed entirely by not using the <code>-stats</code> option.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Help</H3>
+A link to this Help page for JDiff.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Prev/Next</H3>
+These links take you to the previous and next changed package or class.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H3>Frames/No Frames</H3>
+These links show and hide the HTML frames. All pages are available with or without frames.
+</BLOCKQUOTE>
+<BLOCKQUOTE>
+<H2>Complex Changes</H2>
+There are some complex changes which can occur between versions, for example, when two or more methods with the same name change simultaneously, or when a method or field is moved into or from a superclass.
+In these cases, the change will be seen as a removal and an addition, rather than as a change. Unexpected removals or additions are often part of one of these type of changes.
+</BLOCKQUOTE>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/jdiff_statistics.html b/docs/html/sdk/support_api_diff/25.1.0/changes/jdiff_statistics.html
new file mode 100644
index 0000000..54510eb
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/jdiff_statistics.html
@@ -0,0 +1,504 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+API Change Statistics
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<body class="gc-documentation">
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;xborder-bottom:none;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="../changes.html" target="_top">Top of Report</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<h1>API Change Statistics</h1>
+<p>The overall difference between API Levels 25.0.0 and 25.1.0 is approximately <span style="color:222;font-weight:bold;">1.17%</span>.
+</p>
+<br>
+<a name="numbers"></a>
+<h2>Total of Differences, by Number and Type</h2>
+<p>
+The table below lists the numbers of program elements (packages, classes, constructors, methods, and fields) that were added, changed, or removed. The table includes only the highest-level program elements — that is, if a class with two methods was added, the number of methods added does not include those two methods, but the number of classes added does include that class.
+</p>
+<TABLE summary="Number of differences" WIDTH="100%">
+<TR>
+ <th>Type</th>
+ <TH ALIGN="center"><b>Additions</b></TH>
+ <TH ALIGN="center"><b>Changes</b></TH>
+ <TH ALIGN="center">Removals</TH>
+ <TH ALIGN="center"><b>Total</b></TH>
+</TR>
+<TR>
+ <TD>Packages</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">14</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">14</TD>
+</TR>
+<TR>
+ <TD>Classes and <i>Interfaces</i></TD>
+ <TD ALIGN="right">24</TD>
+ <TD ALIGN="right">51</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">75</TD>
+</TR>
+<TR>
+ <TD>Constructors</TD>
+ <TD ALIGN="right">2</TD>
+ <TD ALIGN="right">4</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">6</TD>
+</TR>
+<TR>
+ <TD>Methods</TD>
+ <TD ALIGN="right">72</TD>
+ <TD ALIGN="right">69</TD>
+ <TD ALIGN="right">2</TD>
+ <TD ALIGN="right">143</TD>
+</TR>
+<TR>
+ <TD>Fields</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">0</TD>
+ <TD ALIGN="right">0</TD>
+</TR>
+<TR>
+ <TD style="background-color:#FAFAFA"><b>Total</b></TD>
+ <TD style="background-color:#FAFAFA" ALIGN="right"><strong>98</strong></TD>
+ <TD style="background-color:#FAFAFA" ALIGN="right"><strong>138</strong></TD>
+ <TD style="background-color:#FAFAFA" ALIGN="right"><strong>2</strong></TD>
+ <TD style="background-color:#FAFAFA" ALIGN="right"><strong>238</strong></TD>
+</TR>
+</TABLE>
+<br>
+<a name="packages"></a>
+<h2>Changed Packages, Sorted by Percentage Difference</h2>
+<TABLE summary="Packages sorted by percentage difference" WIDTH="100%">
+<TR>
+ <TH WIDTH="10%">Percentage Difference*</TH>
+ <TH>Package</TH>
+</TR>
+<TR>
+ <TD ALIGN="center">20</TD>
+ <TD><A HREF="pkg_android.support.graphics.drawable.html">android.support.graphics.drawable</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">14</TD>
+ <TD><A HREF="pkg_android.support.v17.leanback.app.html">android.support.v17.leanback.app</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">5</TD>
+ <TD><A HREF="pkg_android.support.v7.preference.html">android.support.v7.preference</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">4</TD>
+ <TD><A HREF="pkg_android.support.design.widget.html">android.support.design.widget</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">3</TD>
+ <TD><A HREF="pkg_android.support.v17.preference.html">android.support.v17.preference</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">3</TD>
+ <TD><A HREF="pkg_android.support.v4.util.html">android.support.v4.util</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">2</TD>
+ <TD><A HREF="pkg_android.support.v4.provider.html">android.support.v4.provider</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">2</TD>
+ <TD><A HREF="pkg_android.support.v4.os.html">android.support.v4.os</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">1</TD>
+ <TD><A HREF="pkg_android.support.v17.leanback.widget.html">android.support.v17.leanback.widget</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.v4.app.html">android.support.v4.app</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.v7.widget.html">android.support.v7.widget</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.v4.media.session.html">android.support.v4.media.session</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.v7.app.html">android.support.v7.app</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="pkg_android.support.v7.media.html">android.support.v7.media</A></TD>
+</TR>
+</TABLE>
+<p style="font-size:10px">* See <a href="#calculation">Calculation of Change Percentages</a>, below.</p>
+<br>
+<a name="classes"></a>
+<h2>Changed Classes and <i>Interfaces</i>, Sorted by Percentage Difference</h2>
+<TABLE summary="Classes sorted by percentage difference" WIDTH="100%">
+<TR WIDTH="20%">
+ <TH WIDTH="10%">Percentage<br>Difference*</TH>
+ <TH><b>Class or <i>Interface</i></b></TH>
+</TR>
+<TR>
+ <TD ALIGN="center">100</TD>
+ <TD><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.html">
+<i>android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler</i></A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">100</TD>
+ <TD><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.html">
+<i>android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler</i></A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">50</TD>
+ <TD><A HREF="android.support.v17.leanback.widget.PlaybackControlsRowPresenter.ViewHolder.html">
+android.support.v17.leanback.widget.PlaybackControlsRowPresenter.ViewHolder</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">46</TD>
+ <TD><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html">
+android.support.v17.leanback.app.PlaybackControlSupportGlue</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">33</TD>
+ <TD><A HREF="android.support.v17.preference.LeanbackPreferenceFragment.html">
+android.support.v17.preference.LeanbackPreferenceFragment</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">27</TD>
+ <TD><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html">
+android.support.v17.leanback.app.MediaControllerGlue</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">25</TD>
+ <TD><A HREF="android.support.design.widget.Snackbar.html">
+android.support.design.widget.Snackbar</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">23</TD>
+ <TD><A HREF="android.support.v17.leanback.app.BackgroundManager.html">
+android.support.v17.leanback.app.BackgroundManager</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">20</TD>
+ <TD><A HREF="android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.html">
+android.support.v17.leanback.widget.OnChildViewHolderSelectedListener</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">20</TD>
+ <TD><A HREF="android.support.v4.os.BuildCompat.html">
+android.support.v4.os.BuildCompat</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">16</TD>
+ <TD><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html">
+android.support.v17.leanback.widget.GuidedActionsStylist</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">14</TD>
+ <TD><A HREF="android.support.v17.leanback.widget.HeaderItem.html">
+android.support.v17.leanback.widget.HeaderItem</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">14</TD>
+ <TD><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html">
+android.support.v17.leanback.widget.PlaybackControlsRow</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">14</TD>
+ <TD><A HREF="android.support.v17.leanback.widget.SpeechOrbView.html">
+android.support.v17.leanback.widget.SpeechOrbView</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">13</TD>
+ <TD><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html">
+android.support.v17.leanback.app.PlaybackOverlayFragment</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">13</TD>
+ <TD><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html">
+android.support.v17.leanback.app.PlaybackOverlaySupportFragment</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">12</TD>
+ <TD><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html">
+android.support.v17.leanback.app.PlaybackControlGlue</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">9</TD>
+ <TD><A HREF="android.support.v7.widget.RecyclerView.RecycledViewPool.html">
+android.support.v7.widget.RecyclerView.RecycledViewPool</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">7</TD>
+ <TD><A HREF="android.support.v7.app.MediaRouteChooserDialog.html">
+android.support.v7.app.MediaRouteChooserDialog</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">6</TD>
+ <TD><A HREF="android.support.v17.leanback.widget.BrowseFrameLayout.html">
+android.support.v17.leanback.widget.BrowseFrameLayout</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">6</TD>
+ <TD><A HREF="android.support.v7.widget.SnapHelper.html">
+android.support.v7.widget.SnapHelper</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">6</TD>
+ <TD><A HREF="android.support.design.widget.Snackbar.Callback.html">
+android.support.design.widget.Snackbar.Callback</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">5</TD>
+ <TD><A HREF="android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.html">
+android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">5</TD>
+ <TD><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.html">
+android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">5</TD>
+ <TD><A HREF="android.support.v17.leanback.widget.RowPresenter.ViewHolder.html">
+android.support.v17.leanback.widget.RowPresenter.ViewHolder</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">5</TD>
+ <TD><A HREF="android.support.v17.leanback.widget.BaseCardView.html">
+android.support.v17.leanback.widget.BaseCardView</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">5</TD>
+ <TD><A HREF="android.support.v17.leanback.app.SearchFragment.html">
+android.support.v17.leanback.app.SearchFragment</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">5</TD>
+ <TD><A HREF="android.support.v17.leanback.app.SearchSupportFragment.html">
+android.support.v17.leanback.app.SearchSupportFragment</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">5</TD>
+ <TD><A HREF="android.support.v17.leanback.widget.SearchBar.html">
+android.support.v17.leanback.widget.SearchBar</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">5</TD>
+ <TD><A HREF="android.support.v4.app.FragmentActivity.html">
+android.support.v4.app.FragmentActivity</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">4</TD>
+ <TD><A HREF="android.support.v17.leanback.app.BaseRowFragment.html">
+android.support.v17.leanback.app.BaseRowFragment</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">4</TD>
+ <TD><A HREF="android.support.v17.leanback.app.BaseRowSupportFragment.html">
+android.support.v17.leanback.app.BaseRowSupportFragment</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">4</TD>
+ <TD><A HREF="android.support.v4.app.FragmentManager.html">
+android.support.v4.app.FragmentManager</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">4</TD>
+ <TD><A HREF="android.support.v4.media.session.MediaControllerCompat.html">
+android.support.v4.media.session.MediaControllerCompat</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">3</TD>
+ <TD><A HREF="android.support.v17.leanback.widget.PlaybackControlsRowPresenter.html">
+android.support.v17.leanback.widget.PlaybackControlsRowPresenter</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">3</TD>
+ <TD><A HREF="android.support.v7.preference.PreferenceManager.html">
+android.support.v7.preference.PreferenceManager</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">3</TD>
+ <TD><A HREF="android.support.v17.leanback.app.RowsFragment.html">
+android.support.v17.leanback.app.RowsFragment</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">3</TD>
+ <TD><A HREF="android.support.v17.leanback.app.RowsSupportFragment.html">
+android.support.v17.leanback.app.RowsSupportFragment</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">2</TD>
+ <TD><A HREF="android.support.v17.leanback.app.BrowseFragment.html">
+android.support.v17.leanback.app.BrowseFragment</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">2</TD>
+ <TD><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.html">
+android.support.v17.leanback.app.BrowseSupportFragment</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">2</TD>
+ <TD><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html">
+android.support.v17.leanback.app.GuidedStepFragment</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">2</TD>
+ <TD><A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html">
+android.support.v17.leanback.app.GuidedStepSupportFragment</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">2</TD>
+ <TD><A HREF="android.support.v7.media.MediaRouter.RouteInfo.html">
+android.support.v7.media.MediaRouter.RouteInfo</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">2</TD>
+ <TD><A HREF="android.support.v4.provider.DocumentFile.html">
+android.support.v4.provider.DocumentFile</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">2</TD>
+ <TD><A HREF="android.support.v17.leanback.widget.ObjectAdapter.html">
+android.support.v17.leanback.widget.ObjectAdapter</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">1</TD>
+ <TD><A HREF="android.support.v7.media.MediaRouter.html">
+android.support.v7.media.MediaRouter</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">1</TD>
+ <TD><A HREF="android.support.v7.widget.LinearLayoutCompat.html">
+android.support.v7.widget.LinearLayoutCompat</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">1</TD>
+ <TD><A HREF="android.support.design.widget.TextInputLayout.html">
+android.support.design.widget.TextInputLayout</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">1</TD>
+ <TD><A HREF="android.support.v4.app.FragmentTransaction.html">
+android.support.v4.app.FragmentTransaction</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center">1</TD>
+ <TD><A HREF="android.support.v4.app.Fragment.html">
+android.support.v4.app.Fragment</A></TD>
+</TR>
+<TR>
+ <TD ALIGN="center"><1</TD>
+ <TD><A HREF="android.support.v7.widget.RecyclerView.html">
+android.support.v7.widget.RecyclerView</A></TD>
+</TR>
+</TABLE>
+<p style="font-size:10px">* See <a href="#calculation">Calculation of Change Percentages</a>, below.</p>
+<br>
+<h2 id="calculation">Calculation of Change Percentages</h2>
+<p>
+The percent change statistic reported for all elements in the "to" API Level specification is defined recursively as follows:</p>
+<pre>
+Percentage difference = 100 * (added + removed + 2*changed)
+ -----------------------------------
+ sum of public elements in BOTH APIs
+</pre>
+<p>where <code>added</code> is the number of packages added, <code>removed</code> is the number of packages removed, and <code>changed</code> is the number of packages changed.
+This definition is applied recursively for the classes and their program elements, so the value for a changed package will be less than 1, unless every class in that package has changed.
+The definition ensures that if all packages are removed and all new packages are
+added, the change will be 100%.</p>
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY></HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/jdiff_topleftframe.html b/docs/html/sdk/support_api_diff/25.1.0/changes/jdiff_topleftframe.html
new file mode 100644
index 0000000..36f9836
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/jdiff_topleftframe.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Android API Version Differences
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<table class="jdiffIndex" summary="Links to diff index files" BORDER="0" WIDTH="100%" cellspacing="0" cellpadding="0" style="margin:0">
+<TR>
+ <th class="indexHeader" nowrap>
+ Select a Diffs Index:</th>
+</TR>
+<TR>
+ <TD><FONT CLASS="indexText" size="-2"><A HREF="alldiffs_index_all.html" TARGET="bottomleftframe">All Differences</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="packages_index_all.html" TARGET="bottomleftframe">By Package</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="classes_index_all.html" TARGET="bottomleftframe">By Class</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="constructors_index_all.html" TARGET="bottomleftframe">By Constructor</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="methods_index_all.html" TARGET="bottomleftframe">By Method</A></FONT><br></TD>
+</TR>
+<TR>
+ <TD NOWRAP><FONT CLASS="indexText" size="-2"><A HREF="fields_index_all.html" TARGET="bottomleftframe">By Field</A></FONT><br></TD>
+</TR>
+</TABLE>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/methods_index_additions.html b/docs/html/sdk/support_api_diff/25.1.0/changes/methods_index_additions.html
new file mode 100644
index 0000000..61e22fee
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/methods_index_additions.html
@@ -0,0 +1,399 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="methods_index_all.html" class="staysblack">All Methods</a>
+ <br>
+<A HREF="methods_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<b>Additions</b>
+ <br>
+<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.attachToView_added(android.view.View)" class="hiddenlink" target="rightframe"><b>attachToView</b>
+(<code>View</code>)</A></nobr><br>
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.clearDrawable_added()" class="hiddenlink" target="rightframe"><b>clearDrawable</b>
+()</A></nobr><br>
+<i>collapseAction</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html#android.support.v17.leanback.app.GuidedStepFragment.collapseAction_added(boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html#android.support.v17.leanback.app.GuidedStepSupportFragment.collapseAction_added(boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepSupportFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.collapseAction_added(boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>boolean</code>)</b> in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.SnapHelper.html#android.support.v7.widget.SnapHelper.createSnapScroller_added(android.support.v7.widget.RecyclerView.LayoutManager)" class="hiddenlink" target="rightframe"><b>createSnapScroller</b>
+(<code>LayoutManager</code>)</A></nobr><br>
+<A NAME="E"></A>
+<br><font size="+2">E</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>expandAction</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html#android.support.v17.leanback.app.GuidedStepFragment.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>GuidedAction, boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html#android.support.v17.leanback.app.GuidedStepSupportFragment.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>GuidedAction, boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepSupportFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>GuidedAction, boolean</code>)</b> in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>findRowViewHolderByPosition</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.html#android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.html#android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.RowsFragment.html#android.support.v17.leanback.app.RowsFragment.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.RowsFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.RowsSupportFragment.html#android.support.v17.leanback.app.RowsSupportFragment.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.RowsSupportFragment
+</A></nobr><br>
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v7.media.MediaRouter.html#android.support.v7.media.MediaRouter.getBluetoothRoute_added()" class="hiddenlink" target="rightframe"><b>getBluetoothRoute</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.getBufferedProgressLong_added()" class="hiddenlink" target="rightframe"><b>getBufferedProgressLong</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.getCurrentTimeLong_added()" class="hiddenlink" target="rightframe"><b>getCurrentTimeLong</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.HeaderItem.html#android.support.v17.leanback.widget.HeaderItem.getDescription_added()" class="hiddenlink" target="rightframe"><b>getDescription</b>
+()</A></nobr><br>
+<i>getEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.getEventHandler_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.getEventHandler_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.LinearLayoutCompat.html#android.support.v7.widget.LinearLayoutCompat.getGravity_added()" class="hiddenlink" target="rightframe"><b>getGravity</b>
+()</A></nobr><br>
+<i>getMainFragment</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseFragment.html#android.support.v17.leanback.app.BrowseFragment.getMainFragment_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.html#android.support.v17.leanback.app.BrowseSupportFragment.getMainFragment_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseSupportFragment
+</A></nobr><br>
+<nobr><A HREF="android.support.v4.media.session.MediaControllerCompat.html#android.support.v4.media.session.MediaControllerCompat.getMediaController_added(android.app.Activity)" class="hiddenlink" target="rightframe"><b>getMediaController</b>
+(<code>Activity</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v7.preference.PreferenceManager.html#android.support.v7.preference.PreferenceManager.getPreferenceComparisonCallback_added()" class="hiddenlink" target="rightframe"><b>getPreferenceComparisonCallback</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.RecyclerView.RecycledViewPool.html#android.support.v7.widget.RecyclerView.RecycledViewPool.getRecycledViewCount_added(int)" class="hiddenlink" target="rightframe"><b>getRecycledViewCount</b>
+(<code>int</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.RowPresenter.ViewHolder.html#android.support.v17.leanback.widget.RowPresenter.ViewHolder.getSelectedItem_added()" class="hiddenlink" target="rightframe"><b>getSelectedItem</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.RowPresenter.ViewHolder.html#android.support.v17.leanback.widget.RowPresenter.ViewHolder.getSelectedItemViewHolder_added()" class="hiddenlink" target="rightframe"><b>getSelectedItemViewHolder</b>
+()</A></nobr><br>
+<i>getSelectedRowViewHolder</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseFragment.html#android.support.v17.leanback.app.BrowseFragment.getSelectedRowViewHolder_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.html#android.support.v17.leanback.app.BrowseSupportFragment.getSelectedRowViewHolder_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseSupportFragment
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.getTotalTimeLong_added()" class="hiddenlink" target="rightframe"><b>getTotalTimeLong</b>
+()</A></nobr><br>
+<i>getVerticalGridView</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BaseRowFragment.html#android.support.v17.leanback.app.BaseRowFragment.getVerticalGridView_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BaseRowFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BaseRowSupportFragment.html#android.support.v17.leanback.app.BaseRowSupportFragment.getVerticalGridView_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BaseRowSupportFragment
+</A></nobr><br>
+<A NAME="I"></A>
+<br><font size="+2">I</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.os.BuildCompat.html#android.support.v4.os.BuildCompat.isAtLeastO_added()" class="hiddenlink" target="rightframe"><b>isAtLeastO</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.isAutoReleaseOnStop_added()" class="hiddenlink" target="rightframe"><b>isAutoReleaseOnStop</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.isBackKeyToCollapseActivatorView_added()" class="hiddenlink" target="rightframe"><b>isBackKeyToCollapseActivatorView</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.isBackKeyToCollapseSubActions_added()" class="hiddenlink" target="rightframe"><b>isBackKeyToCollapseSubActions</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v7.media.MediaRouter.RouteInfo.html#android.support.v7.media.MediaRouter.RouteInfo.isBluetooth_added()" class="hiddenlink" target="rightframe"><b>isBluetooth</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v7.media.MediaRouter.RouteInfo.html#android.support.v7.media.MediaRouter.RouteInfo.isDeviceSpeaker_added()" class="hiddenlink" target="rightframe"><b>isDeviceSpeaker</b>
+()</A></nobr><br>
+<i>isExpanded</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html#android.support.v17.leanback.app.GuidedStepFragment.isExpanded_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.GuidedStepFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html#android.support.v17.leanback.app.GuidedStepSupportFragment.isExpanded_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.GuidedStepSupportFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.isExpanded_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<nobr><A HREF="android.support.v4.provider.DocumentFile.html#android.support.v4.provider.DocumentFile.isVirtual_added()" class="hiddenlink" target="rightframe"><b>isVirtual</b>
+()</A></nobr><br>
+<A NAME="O"></A>
+<br><font size="+2">O</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.html#android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.onChildViewHolderSelectedAndPositioned_added(android.support.v7.widget.RecyclerView, android.support.v7.widget.RecyclerView.ViewHolder, int, int)" class="hiddenlink" target="rightframe"><b>onChildViewHolderSelectedAndPositioned</b>
+(<code>RecyclerView, ViewHolder, int, int</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.onEditingModeChange_added(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean, boolean)" class="hiddenlink" target="rightframe"><b>onEditingModeChange</b>
+(<code>ViewHolder, boolean, boolean</code>)</A></nobr><br>
+<A NAME="P"></A>
+<br><font size="+2">P</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.Fragment.html#android.support.v4.app.Fragment.postponeEnterTransition_added()" class="hiddenlink" target="rightframe"><b>postponeEnterTransition</b>
+()</A></nobr><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.FragmentManager.html#android.support.v4.app.FragmentManager.registerFragmentLifecycleCallbacks_added(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks, boolean)" class="hiddenlink" target="rightframe"><b>registerFragmentLifecycleCallbacks</b>
+(<code>FragmentLifecycleCallbacks, boolean</code>)</A></nobr><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.FragmentTransaction.html#android.support.v4.app.FragmentTransaction.setAllowOptimization_added(boolean)" class="hiddenlink" target="rightframe"><b>setAllowOptimization</b>
+(<code>boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.setAutoReleaseOnStop_added(boolean)" class="hiddenlink" target="rightframe"><b>setAutoReleaseOnStop</b>
+(<code>boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setBackKeyToCollapseActivatorView_added(boolean)" class="hiddenlink" target="rightframe"><b>setBackKeyToCollapseActivatorView</b>
+(<code>boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setBackKeyToCollapseSubActions_added(boolean)" class="hiddenlink" target="rightframe"><b>setBackKeyToCollapseSubActions</b>
+(<code>boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.setBufferedProgressLong_added(long)" class="hiddenlink" target="rightframe"><b>setBufferedProgressLong</b>
+(<code>long</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.setCurrentTimeLong_added(long)" class="hiddenlink" target="rightframe"><b>setCurrentTimeLong</b>
+(<code>long</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.HeaderItem.html#android.support.v17.leanback.widget.HeaderItem.setDescription_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>setDescription</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.TextInputLayout.html#android.support.design.widget.TextInputLayout.setErrorTextAppearance_added(int)" class="hiddenlink" target="rightframe"><b>setErrorTextAppearance</b>
+(<code>int</code>)</A></nobr><br>
+<i>setEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.setEventHandler_added(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)" class="hiddenlink" target="rightframe">type <b>
+(<code>InputEventHandler</code>)</b> in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.setEventHandler_added(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)" class="hiddenlink" target="rightframe">type <b>
+(<code>InputEventHandler</code>)</b> in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.SpeechOrbView.html#android.support.v17.leanback.widget.SpeechOrbView.setListeningOrbColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe"><b>setListeningOrbColors</b>
+(<code>Colors</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.media.session.MediaControllerCompat.html#android.support.v4.media.session.MediaControllerCompat.setMediaController_added(android.app.Activity, android.support.v4.media.session.MediaControllerCompat)" class="hiddenlink" target="rightframe"><b>setMediaController</b>
+(<code>Activity, MediaControllerCompat</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.SpeechOrbView.html#android.support.v17.leanback.widget.SpeechOrbView.setNotListeningOrbColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe"><b>setNotListeningOrbColors</b>
+(<code>Colors</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.BrowseFrameLayout.html#android.support.v17.leanback.widget.BrowseFrameLayout.setOnDispatchKeyListener_added(android.view.View.OnKeyListener)" class="hiddenlink" target="rightframe"><b>setOnDispatchKeyListener</b>
+(<code>OnKeyListener</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v7.preference.PreferenceManager.html#android.support.v7.preference.PreferenceManager.setPreferenceComparisonCallback_added(android.support.v7.preference.PreferenceManager.PreferenceComparisonCallback)" class="hiddenlink" target="rightframe"><b>setPreferenceComparisonCallback</b>
+(<code>PreferenceComparisonCallback</code>)</A></nobr><br>
+<i>setSearchAffordanceColors</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.SearchFragment.html#android.support.v17.leanback.app.SearchFragment.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.SearchSupportFragment.html#android.support.v17.leanback.app.SearchSupportFragment.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchSupportFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.widget.SearchBar.html#android.support.v17.leanback.widget.SearchBar.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.widget.SearchBar
+</A></nobr><br>
+<i>setSearchAffordanceColorsInListening</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.SearchFragment.html#android.support.v17.leanback.app.SearchFragment.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.SearchSupportFragment.html#android.support.v17.leanback.app.SearchSupportFragment.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchSupportFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.widget.SearchBar.html#android.support.v17.leanback.widget.SearchBar.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.widget.SearchBar
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.preference.LeanbackPreferenceFragment.html#android.support.v17.preference.LeanbackPreferenceFragment.setTitle_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>setTitle</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.setTotalTimeLong_added(long)" class="hiddenlink" target="rightframe"><b>setTotalTimeLong</b>
+(<code>long</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.RecyclerView.html#android.support.v7.widget.RecyclerView.smoothScrollBy_added(int, int, android.view.animation.Interpolator)" class="hiddenlink" target="rightframe"><b>smoothScrollBy</b>
+(<code>int, int, Interpolator</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.app.Fragment.html#android.support.v4.app.Fragment.startPostponedEnterTransition_added()" class="hiddenlink" target="rightframe"><b>startPostponedEnterTransition</b>
+()</A></nobr><br>
+<A NAME="U"></A>
+<br><font size="+2">U</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.FragmentManager.html#android.support.v4.app.FragmentManager.unregisterFragmentLifecycleCallbacks_added(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks)" class="hiddenlink" target="rightframe"><b>unregisterFragmentLifecycleCallbacks</b>
+(<code>FragmentLifecycleCallbacks</code>)</A></nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/methods_index_all.html b/docs/html/sdk/support_api_diff/25.1.0/changes/methods_index_all.html
new file mode 100644
index 0000000..2f522da
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/methods_index_all.html
@@ -0,0 +1,665 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Methods</b>
+ <br>
+<A HREF="methods_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="A"></A>
+<br><font size="+2">A</font>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.attachToView_added(android.view.View)" class="hiddenlink" target="rightframe"><b>attachToView</b>
+(<code>View</code>)</A></nobr><br>
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.clearDrawable_added()" class="hiddenlink" target="rightframe"><b>clearDrawable</b>
+()</A></nobr><br>
+<i>collapseAction</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html#android.support.v17.leanback.app.GuidedStepFragment.collapseAction_added(boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html#android.support.v17.leanback.app.GuidedStepSupportFragment.collapseAction_added(boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepSupportFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.collapseAction_added(boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>boolean</code>)</b> in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.createControlsRowAndPresenter_changed()" class="hiddenlink" target="rightframe">createControlsRowAndPresenter
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.createPrimaryActionsAdapter_changed(android.support.v17.leanback.widget.PresenterSelector)" class="hiddenlink" target="rightframe">createPrimaryActionsAdapter
+(<code>PresenterSelector</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.SnapHelper.html#android.support.v7.widget.SnapHelper.createSnapScroller_added(android.support.v7.widget.RecyclerView.LayoutManager)" class="hiddenlink" target="rightframe"><b>createSnapScroller</b>
+(<code>LayoutManager</code>)</A></nobr><br>
+<A NAME="D"></A>
+<br><font size="+2">D</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.dismiss_changed()" class="hiddenlink" target="rightframe">dismiss
+()</A></nobr><br>
+<A NAME="E"></A>
+<br><font size="+2">E</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.enableProgressUpdating_changed(boolean)" class="hiddenlink" target="rightframe">enableProgressUpdating
+(<code>boolean</code>)</A></nobr><br>
+<i>expandAction</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html#android.support.v17.leanback.app.GuidedStepFragment.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>GuidedAction, boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html#android.support.v17.leanback.app.GuidedStepSupportFragment.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>GuidedAction, boolean</code>)</b> in android.support.v17.leanback.app.GuidedStepSupportFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>GuidedAction, boolean</code>)</b> in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<A NAME="F"></A>
+<br><font size="+2">F</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>findRowViewHolderByPosition</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.html#android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.html#android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.RowsFragment.html#android.support.v17.leanback.app.RowsFragment.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.RowsFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.RowsSupportFragment.html#android.support.v17.leanback.app.RowsSupportFragment.findRowViewHolderByPosition_added(int)" class="hiddenlink" target="rightframe">type <b>
+(<code>int</code>)</b> in android.support.v17.leanback.app.RowsSupportFragment
+</A></nobr><br>
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v7.media.MediaRouter.html#android.support.v7.media.MediaRouter.getBluetoothRoute_added()" class="hiddenlink" target="rightframe"><b>getBluetoothRoute</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.getBufferedProgressLong_added()" class="hiddenlink" target="rightframe"><b>getBufferedProgressLong</b>
+()</A></nobr><br>
+<i>getContext</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.getContext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getContext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getControlsRow_changed()" class="hiddenlink" target="rightframe">getControlsRow
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getCurrentPosition_changed()" class="hiddenlink" target="rightframe">getCurrentPosition
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getCurrentSpeedId_changed()" class="hiddenlink" target="rightframe">getCurrentSpeedId
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.getCurrentTimeLong_added()" class="hiddenlink" target="rightframe"><b>getCurrentTimeLong</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.getDefaultDimLayer_changed()" class="hiddenlink" target="rightframe">getDefaultDimLayer
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.HeaderItem.html#android.support.v17.leanback.widget.HeaderItem.getDescription_added()" class="hiddenlink" target="rightframe"><b>getDescription</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.getDimLayer_changed()" class="hiddenlink" target="rightframe">getDimLayer
+()</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.getDuration_changed()" class="hiddenlink" target="rightframe">getDuration
+()</A></nobr><br>
+<i>getEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.getEventHandler_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.getEventHandler_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.BaseCardView.html#android.support.v17.leanback.widget.BaseCardView.getExtraVisibility_changed()" class="hiddenlink" target="rightframe">getExtraVisibility
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getFastForwardSpeeds_changed()" class="hiddenlink" target="rightframe">getFastForwardSpeeds
+()</A></nobr><br>
+<i>getFragment</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.getFragment_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getFragment_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.LinearLayoutCompat.html#android.support.v7.widget.LinearLayoutCompat.getGravity_added()" class="hiddenlink" target="rightframe"><b>getGravity</b>
+()</A></nobr><br>
+<i>getInputEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.getInputEventHandler_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.getInputEventHandler_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<i>getMainFragment</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseFragment.html#android.support.v17.leanback.app.BrowseFragment.getMainFragment_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.html#android.support.v17.leanback.app.BrowseSupportFragment.getMainFragment_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseSupportFragment
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaArt_changed()" class="hiddenlink" target="rightframe">getMediaArt
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.media.session.MediaControllerCompat.html#android.support.v4.media.session.MediaControllerCompat.getMediaController_added(android.app.Activity)" class="hiddenlink" target="rightframe"><b>getMediaController</b>
+(<code>Activity</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaDuration_changed()" class="hiddenlink" target="rightframe">getMediaDuration
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaSubtitle_changed()" class="hiddenlink" target="rightframe">getMediaSubtitle
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaTitle_changed()" class="hiddenlink" target="rightframe">getMediaTitle
+()</A></nobr><br>
+<i>getOnItemViewClickedListener</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.getOnItemViewClickedListener_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getOnItemViewClickedListener_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<nobr><A HREF="android.support.v7.preference.PreferenceManager.html#android.support.v7.preference.PreferenceManager.getPreferenceComparisonCallback_added()" class="hiddenlink" target="rightframe"><b>getPreferenceComparisonCallback</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.RecyclerView.RecycledViewPool.html#android.support.v7.widget.RecyclerView.RecycledViewPool.getRecycledViewCount_added(int)" class="hiddenlink" target="rightframe"><b>getRecycledViewCount</b>
+(<code>int</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getRewindSpeeds_changed()" class="hiddenlink" target="rightframe">getRewindSpeeds
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.RowPresenter.ViewHolder.html#android.support.v17.leanback.widget.RowPresenter.ViewHolder.getSelectedItem_added()" class="hiddenlink" target="rightframe"><b>getSelectedItem</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.RowPresenter.ViewHolder.html#android.support.v17.leanback.widget.RowPresenter.ViewHolder.getSelectedItemViewHolder_added()" class="hiddenlink" target="rightframe"><b>getSelectedItemViewHolder</b>
+()</A></nobr><br>
+<i>getSelectedRowViewHolder</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseFragment.html#android.support.v17.leanback.app.BrowseFragment.getSelectedRowViewHolder_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.html#android.support.v17.leanback.app.BrowseSupportFragment.getSelectedRowViewHolder_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BrowseSupportFragment
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getSupportedActions_changed()" class="hiddenlink" target="rightframe">getSupportedActions
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.app.FragmentActivity.html#android.support.v4.app.FragmentActivity.getSupportMediaController_changed()" class="hiddenlink" target="rightframe">getSupportMediaController
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.getTotalTimeLong_added()" class="hiddenlink" target="rightframe"><b>getTotalTimeLong</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getUpdatePeriod_changed()" class="hiddenlink" target="rightframe">getUpdatePeriod
+()</A></nobr><br>
+<i>getVerticalGridView</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BaseRowFragment.html#android.support.v17.leanback.app.BaseRowFragment.getVerticalGridView_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BaseRowFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.BaseRowSupportFragment.html#android.support.v17.leanback.app.BaseRowSupportFragment.getVerticalGridView_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.BaseRowSupportFragment
+</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.getView_changed()" class="hiddenlink" target="rightframe">getView
+()</A></nobr><br>
+<A NAME="H"></A>
+<br><font size="+2">H</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>handleInputEvent</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.html#android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.handleInputEvent_removed(android.view.InputEvent)" class="hiddenlink" target="rightframe">type <strike>
+(<code>InputEvent</code>)</strike> in android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.handleInputEvent_removed(android.view.InputEvent)" class="hiddenlink" target="rightframe">type <strike>
+(<code>InputEvent</code>)</strike> in android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.hasValidMedia_changed()" class="hiddenlink" target="rightframe">hasValidMedia
+()</A></nobr><br>
+<A NAME="I"></A>
+<br><font size="+2">I</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.os.BuildCompat.html#android.support.v4.os.BuildCompat.isAtLeastO_added()" class="hiddenlink" target="rightframe"><b>isAtLeastO</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.isAutoReleaseOnStop_added()" class="hiddenlink" target="rightframe"><b>isAutoReleaseOnStop</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.isBackKeyToCollapseActivatorView_added()" class="hiddenlink" target="rightframe"><b>isBackKeyToCollapseActivatorView</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.isBackKeyToCollapseSubActions_added()" class="hiddenlink" target="rightframe"><b>isBackKeyToCollapseSubActions</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v7.media.MediaRouter.RouteInfo.html#android.support.v7.media.MediaRouter.RouteInfo.isBluetooth_added()" class="hiddenlink" target="rightframe"><b>isBluetooth</b>
+()</A></nobr><br>
+<nobr><A HREF="android.support.v7.media.MediaRouter.RouteInfo.html#android.support.v7.media.MediaRouter.RouteInfo.isDeviceSpeaker_added()" class="hiddenlink" target="rightframe"><b>isDeviceSpeaker</b>
+()</A></nobr><br>
+<i>isExpanded</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html#android.support.v17.leanback.app.GuidedStepFragment.isExpanded_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.GuidedStepFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html#android.support.v17.leanback.app.GuidedStepSupportFragment.isExpanded_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.app.GuidedStepSupportFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.isExpanded_added()" class="hiddenlink" target="rightframe">type <b>
+()</b> in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.isFadingEnabled_changed()" class="hiddenlink" target="rightframe">isFadingEnabled
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.isMediaPlaying_changed()" class="hiddenlink" target="rightframe">isMediaPlaying
+()</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.isShown_changed()" class="hiddenlink" target="rightframe">isShown
+()</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.isShownOrQueued_changed()" class="hiddenlink" target="rightframe">isShownOrQueued
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.provider.DocumentFile.html#android.support.v4.provider.DocumentFile.isVirtual_added()" class="hiddenlink" target="rightframe"><b>isVirtual</b>
+()</A></nobr><br>
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.widget.ObjectAdapter.html#android.support.v17.leanback.widget.ObjectAdapter.notifyItemRangeChanged_changed(int, int)" class="hiddenlink" target="rightframe">notifyItemRangeChanged
+(<code>int, int</code>)</A></nobr><br>
+<A NAME="O"></A>
+<br><font size="+2">O</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onActionClicked_changed(android.support.v17.leanback.widget.Action)" class="hiddenlink" target="rightframe">onActionClicked
+(<code>Action</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.html#android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.onChildViewHolderSelectedAndPositioned_added(android.support.v7.widget.RecyclerView, android.support.v7.widget.RecyclerView.ViewHolder, int, int)" class="hiddenlink" target="rightframe"><b>onChildViewHolderSelectedAndPositioned</b>
+(<code>RecyclerView, ViewHolder, int, int</code>)</A></nobr><br>
+<i>onEditingModeChange</i><br>
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.onEditingModeChange_added(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean, boolean)" class="hiddenlink" target="rightframe">type <b>
+(<code>ViewHolder, boolean, boolean</code>)</b> in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.onEditingModeChange_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">type
+(<code>ViewHolder, GuidedAction, boolean</code>) in android.support.v17.leanback.widget.GuidedActionsStylist
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onKey_changed(android.view.View, int, android.view.KeyEvent)" class="hiddenlink" target="rightframe">onKey
+(<code>View, int, KeyEvent</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onMetadataChanged_changed()" class="hiddenlink" target="rightframe">onMetadataChanged
+()</A></nobr><br>
+<i>onRowChanged</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.onRowChanged_changed(android.support.v17.leanback.widget.PlaybackControlsRow)" class="hiddenlink" target="rightframe">type
+(<code>PlaybackControlsRow</code>) in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onRowChanged_changed(android.support.v17.leanback.widget.PlaybackControlsRow)" class="hiddenlink" target="rightframe">type
+(<code>PlaybackControlsRow</code>) in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onStateChanged_changed()" class="hiddenlink" target="rightframe">onStateChanged
+()</A></nobr><br>
+<A NAME="P"></A>
+<br><font size="+2">P</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>pausePlayback</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.pausePlayback_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.pausePlayback_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.pausePlayback_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<nobr><A HREF="android.support.v4.app.Fragment.html#android.support.v4.app.Fragment.postponeEnterTransition_added()" class="hiddenlink" target="rightframe"><b>postponeEnterTransition</b>
+()</A></nobr><br>
+<A NAME="R"></A>
+<br><font size="+2">R</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.FragmentManager.html#android.support.v4.app.FragmentManager.registerFragmentLifecycleCallbacks_added(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks, boolean)" class="hiddenlink" target="rightframe"><b>registerFragmentLifecycleCallbacks</b>
+(<code>FragmentLifecycleCallbacks, boolean</code>)</A></nobr><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.FragmentTransaction.html#android.support.v4.app.FragmentTransaction.setAllowOptimization_added(boolean)" class="hiddenlink" target="rightframe"><b>setAllowOptimization</b>
+(<code>boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.setAutoReleaseOnStop_added(boolean)" class="hiddenlink" target="rightframe"><b>setAutoReleaseOnStop</b>
+(<code>boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setBackKeyToCollapseActivatorView_added(boolean)" class="hiddenlink" target="rightframe"><b>setBackKeyToCollapseActivatorView</b>
+(<code>boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setBackKeyToCollapseSubActions_added(boolean)" class="hiddenlink" target="rightframe"><b>setBackKeyToCollapseSubActions</b>
+(<code>boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.setBufferedProgressLong_added(long)" class="hiddenlink" target="rightframe"><b>setBufferedProgressLong</b>
+(<code>long</code>)</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.setCallback_changed(android.support.design.widget.Snackbar.Callback)" class="hiddenlink" target="rightframe">setCallback
+(<code>Callback</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.setControlsRow_changed(android.support.v17.leanback.widget.PlaybackControlsRow)" class="hiddenlink" target="rightframe">setControlsRow
+(<code>PlaybackControlsRow</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.setCurrentTimeLong_added(long)" class="hiddenlink" target="rightframe"><b>setCurrentTimeLong</b>
+(<code>long</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.HeaderItem.html#android.support.v17.leanback.widget.HeaderItem.setDescription_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>setDescription</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.setDimLayer_changed(android.graphics.drawable.Drawable)" class="hiddenlink" target="rightframe">setDimLayer
+(<code>Drawable</code>)</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.setDuration_changed(int)" class="hiddenlink" target="rightframe">setDuration
+(<code>int</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setEditingMode_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">setEditingMode
+(<code>ViewHolder, GuidedAction, boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.TextInputLayout.html#android.support.design.widget.TextInputLayout.setErrorTextAppearance_added(int)" class="hiddenlink" target="rightframe"><b>setErrorTextAppearance</b>
+(<code>int</code>)</A></nobr><br>
+<i>setEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.setEventHandler_added(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)" class="hiddenlink" target="rightframe">type <b>
+(<code>InputEventHandler</code>)</b> in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.setEventHandler_added(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)" class="hiddenlink" target="rightframe">type <b>
+(<code>InputEventHandler</code>)</b> in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setExpandedViewHolder_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder)" class="hiddenlink" target="rightframe">setExpandedViewHolder
+(<code>ViewHolder</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.BaseCardView.html#android.support.v17.leanback.widget.BaseCardView.setExtraVisibility_changed(int)" class="hiddenlink" target="rightframe">setExtraVisibility
+(<code>int</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.setFadingEnabled_changed(boolean)" class="hiddenlink" target="rightframe">setFadingEnabled
+(<code>boolean</code>)</A></nobr><br>
+<i>setInputEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.setInputEventHandler_changed(android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler)" class="hiddenlink" target="rightframe">type
+(<code>InputEventHandler</code>) in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.setInputEventHandler_changed(android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler)" class="hiddenlink" target="rightframe">type
+(<code>InputEventHandler</code>) in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.SpeechOrbView.html#android.support.v17.leanback.widget.SpeechOrbView.setListeningOrbColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe"><b>setListeningOrbColors</b>
+(<code>Colors</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.media.session.MediaControllerCompat.html#android.support.v4.media.session.MediaControllerCompat.setMediaController_added(android.app.Activity, android.support.v4.media.session.MediaControllerCompat)" class="hiddenlink" target="rightframe"><b>setMediaController</b>
+(<code>Activity, MediaControllerCompat</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.SpeechOrbView.html#android.support.v17.leanback.widget.SpeechOrbView.setNotListeningOrbColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe"><b>setNotListeningOrbColors</b>
+(<code>Colors</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.BrowseFrameLayout.html#android.support.v17.leanback.widget.BrowseFrameLayout.setOnDispatchKeyListener_added(android.view.View.OnKeyListener)" class="hiddenlink" target="rightframe"><b>setOnDispatchKeyListener</b>
+(<code>OnKeyListener</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.setOnItemViewClickedListener_changed(android.support.v17.leanback.widget.OnItemViewClickedListener)" class="hiddenlink" target="rightframe">setOnItemViewClickedListener
+(<code>OnItemViewClickedListener</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v7.preference.PreferenceManager.html#android.support.v7.preference.PreferenceManager.setPreferenceComparisonCallback_added(android.support.v7.preference.PreferenceManager.PreferenceComparisonCallback)" class="hiddenlink" target="rightframe"><b>setPreferenceComparisonCallback</b>
+(<code>PreferenceComparisonCallback</code>)</A></nobr><br>
+<i>setSearchAffordanceColors</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.SearchFragment.html#android.support.v17.leanback.app.SearchFragment.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.SearchSupportFragment.html#android.support.v17.leanback.app.SearchSupportFragment.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchSupportFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.widget.SearchBar.html#android.support.v17.leanback.widget.SearchBar.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.widget.SearchBar
+</A></nobr><br>
+<i>setSearchAffordanceColorsInListening</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.SearchFragment.html#android.support.v17.leanback.app.SearchFragment.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.SearchSupportFragment.html#android.support.v17.leanback.app.SearchSupportFragment.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.app.SearchSupportFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.widget.SearchBar.html#android.support.v17.leanback.widget.SearchBar.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)" class="hiddenlink" target="rightframe">type <b>
+(<code>Colors</code>)</b> in android.support.v17.leanback.widget.SearchBar
+</A></nobr><br>
+<nobr><A HREF="android.support.v4.app.FragmentActivity.html#android.support.v4.app.FragmentActivity.setSupportMediaController_changed(android.support.v4.media.session.MediaControllerCompat)" class="hiddenlink" target="rightframe">setSupportMediaController
+(<code>MediaControllerCompat</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.preference.LeanbackPreferenceFragment.html#android.support.v17.preference.LeanbackPreferenceFragment.setTitle_added(java.lang.CharSequence)" class="hiddenlink" target="rightframe"><b>setTitle</b>
+(<code>CharSequence</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html#android.support.v17.leanback.widget.PlaybackControlsRow.setTotalTimeLong_added(long)" class="hiddenlink" target="rightframe"><b>setTotalTimeLong</b>
+(<code>long</code>)</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.show_changed()" class="hiddenlink" target="rightframe">show
+()</A></nobr><br>
+<i>skipToNext</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.skipToNext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.skipToNext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.skipToNext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<i>skipToPrevious</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.skipToPrevious_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.skipToPrevious_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.skipToPrevious_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<nobr><A HREF="android.support.v7.widget.RecyclerView.html#android.support.v7.widget.RecyclerView.smoothScrollBy_added(int, int, android.view.animation.Interpolator)" class="hiddenlink" target="rightframe"><b>smoothScrollBy</b>
+(<code>int, int, Interpolator</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.startExpandedTransition_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder)" class="hiddenlink" target="rightframe">startExpandedTransition
+(<code>ViewHolder</code>)</A></nobr><br>
+<i>startPlayback</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.startPlayback_changed(int)" class="hiddenlink" target="rightframe">type
+(<code>int</code>) in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.startPlayback_changed(int)" class="hiddenlink" target="rightframe">type
+(<code>int</code>) in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.startPlayback_changed(int)" class="hiddenlink" target="rightframe">type
+(<code>int</code>) in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<nobr><A HREF="android.support.v4.app.Fragment.html#android.support.v4.app.Fragment.startPostponedEnterTransition_added()" class="hiddenlink" target="rightframe"><b>startPostponedEnterTransition</b>
+()</A></nobr><br>
+<A NAME="U"></A>
+<br><font size="+2">U</font>
+<a href="#A"><font size="-2">A</font></a>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#F"><font size="-2">F</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#R"><font size="-2">R</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v4.app.FragmentManager.html#android.support.v4.app.FragmentManager.unregisterFragmentLifecycleCallbacks_added(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks)" class="hiddenlink" target="rightframe"><b>unregisterFragmentLifecycleCallbacks</b>
+(<code>FragmentLifecycleCallbacks</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.updateProgress_changed()" class="hiddenlink" target="rightframe">updateProgress
+()</A></nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/methods_index_changes.html b/docs/html/sdk/support_api_diff/25.1.0/changes/methods_index_changes.html
new file mode 100644
index 0000000..c3228f9
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/methods_index_changes.html
@@ -0,0 +1,387 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="methods_index_all.html" class="staysblack">All Methods</a>
+ <br>
+<A HREF="methods_index_removals.html" xclass="hiddenlink">Removals</A>
+ <br>
+<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="C"></A>
+<br><font size="+2">C</font>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.createControlsRowAndPresenter_changed()" class="hiddenlink" target="rightframe">createControlsRowAndPresenter
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.createPrimaryActionsAdapter_changed(android.support.v17.leanback.widget.PresenterSelector)" class="hiddenlink" target="rightframe">createPrimaryActionsAdapter
+(<code>PresenterSelector</code>)</A></nobr><br>
+<A NAME="D"></A>
+<br><font size="+2">D</font>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.dismiss_changed()" class="hiddenlink" target="rightframe">dismiss
+()</A></nobr><br>
+<A NAME="E"></A>
+<br><font size="+2">E</font>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.enableProgressUpdating_changed(boolean)" class="hiddenlink" target="rightframe">enableProgressUpdating
+(<code>boolean</code>)</A></nobr><br>
+<A NAME="G"></A>
+<br><font size="+2">G</font>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>getContext</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.getContext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getContext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getControlsRow_changed()" class="hiddenlink" target="rightframe">getControlsRow
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getCurrentPosition_changed()" class="hiddenlink" target="rightframe">getCurrentPosition
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getCurrentSpeedId_changed()" class="hiddenlink" target="rightframe">getCurrentSpeedId
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.getDefaultDimLayer_changed()" class="hiddenlink" target="rightframe">getDefaultDimLayer
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.getDimLayer_changed()" class="hiddenlink" target="rightframe">getDimLayer
+()</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.getDuration_changed()" class="hiddenlink" target="rightframe">getDuration
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.BaseCardView.html#android.support.v17.leanback.widget.BaseCardView.getExtraVisibility_changed()" class="hiddenlink" target="rightframe">getExtraVisibility
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getFastForwardSpeeds_changed()" class="hiddenlink" target="rightframe">getFastForwardSpeeds
+()</A></nobr><br>
+<i>getFragment</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.getFragment_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getFragment_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<i>getInputEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.getInputEventHandler_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.getInputEventHandler_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaArt_changed()" class="hiddenlink" target="rightframe">getMediaArt
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaDuration_changed()" class="hiddenlink" target="rightframe">getMediaDuration
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaSubtitle_changed()" class="hiddenlink" target="rightframe">getMediaSubtitle
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getMediaTitle_changed()" class="hiddenlink" target="rightframe">getMediaTitle
+()</A></nobr><br>
+<i>getOnItemViewClickedListener</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.getOnItemViewClickedListener_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getOnItemViewClickedListener_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getRewindSpeeds_changed()" class="hiddenlink" target="rightframe">getRewindSpeeds
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getSupportedActions_changed()" class="hiddenlink" target="rightframe">getSupportedActions
+()</A></nobr><br>
+<nobr><A HREF="android.support.v4.app.FragmentActivity.html#android.support.v4.app.FragmentActivity.getSupportMediaController_changed()" class="hiddenlink" target="rightframe">getSupportMediaController
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.getUpdatePeriod_changed()" class="hiddenlink" target="rightframe">getUpdatePeriod
+()</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.getView_changed()" class="hiddenlink" target="rightframe">getView
+()</A></nobr><br>
+<A NAME="H"></A>
+<br><font size="+2">H</font>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.hasValidMedia_changed()" class="hiddenlink" target="rightframe">hasValidMedia
+()</A></nobr><br>
+<A NAME="I"></A>
+<br><font size="+2">I</font>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.isFadingEnabled_changed()" class="hiddenlink" target="rightframe">isFadingEnabled
+()</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.isMediaPlaying_changed()" class="hiddenlink" target="rightframe">isMediaPlaying
+()</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.isShown_changed()" class="hiddenlink" target="rightframe">isShown
+()</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.isShownOrQueued_changed()" class="hiddenlink" target="rightframe">isShownOrQueued
+()</A></nobr><br>
+<A NAME="N"></A>
+<br><font size="+2">N</font>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.widget.ObjectAdapter.html#android.support.v17.leanback.widget.ObjectAdapter.notifyItemRangeChanged_changed(int, int)" class="hiddenlink" target="rightframe">notifyItemRangeChanged
+(<code>int, int</code>)</A></nobr><br>
+<A NAME="O"></A>
+<br><font size="+2">O</font>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onActionClicked_changed(android.support.v17.leanback.widget.Action)" class="hiddenlink" target="rightframe">onActionClicked
+(<code>Action</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.onEditingModeChange_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">onEditingModeChange
+(<code>ViewHolder, GuidedAction, boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onKey_changed(android.view.View, int, android.view.KeyEvent)" class="hiddenlink" target="rightframe">onKey
+(<code>View, int, KeyEvent</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onMetadataChanged_changed()" class="hiddenlink" target="rightframe">onMetadataChanged
+()</A></nobr><br>
+<i>onRowChanged</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.onRowChanged_changed(android.support.v17.leanback.widget.PlaybackControlsRow)" class="hiddenlink" target="rightframe">type
+(<code>PlaybackControlsRow</code>) in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onRowChanged_changed(android.support.v17.leanback.widget.PlaybackControlsRow)" class="hiddenlink" target="rightframe">type
+(<code>PlaybackControlsRow</code>) in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.onStateChanged_changed()" class="hiddenlink" target="rightframe">onStateChanged
+()</A></nobr><br>
+<A NAME="P"></A>
+<br><font size="+2">P</font>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#S"><font size="-2">S</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>pausePlayback</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.pausePlayback_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.pausePlayback_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.pausePlayback_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<A NAME="S"></A>
+<br><font size="+2">S</font>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#U"><font size="-2">U</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.setCallback_changed(android.support.design.widget.Snackbar.Callback)" class="hiddenlink" target="rightframe">setCallback
+(<code>Callback</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.setControlsRow_changed(android.support.v17.leanback.widget.PlaybackControlsRow)" class="hiddenlink" target="rightframe">setControlsRow
+(<code>PlaybackControlsRow</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html#android.support.v17.leanback.app.BackgroundManager.setDimLayer_changed(android.graphics.drawable.Drawable)" class="hiddenlink" target="rightframe">setDimLayer
+(<code>Drawable</code>)</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.setDuration_changed(int)" class="hiddenlink" target="rightframe">setDuration
+(<code>int</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setEditingMode_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean)" class="hiddenlink" target="rightframe">setEditingMode
+(<code>ViewHolder, GuidedAction, boolean</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.setExpandedViewHolder_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder)" class="hiddenlink" target="rightframe">setExpandedViewHolder
+(<code>ViewHolder</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.BaseCardView.html#android.support.v17.leanback.widget.BaseCardView.setExtraVisibility_changed(int)" class="hiddenlink" target="rightframe">setExtraVisibility
+(<code>int</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.setFadingEnabled_changed(boolean)" class="hiddenlink" target="rightframe">setFadingEnabled
+(<code>boolean</code>)</A></nobr><br>
+<i>setInputEventHandler</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html#android.support.v17.leanback.app.PlaybackOverlayFragment.setInputEventHandler_changed(android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler)" class="hiddenlink" target="rightframe">type
+(<code>InputEventHandler</code>) in android.support.v17.leanback.app.PlaybackOverlayFragment
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.setInputEventHandler_changed(android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler)" class="hiddenlink" target="rightframe">type
+(<code>InputEventHandler</code>) in android.support.v17.leanback.app.PlaybackOverlaySupportFragment
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.setOnItemViewClickedListener_changed(android.support.v17.leanback.widget.OnItemViewClickedListener)" class="hiddenlink" target="rightframe">setOnItemViewClickedListener
+(<code>OnItemViewClickedListener</code>)</A></nobr><br>
+<nobr><A HREF="android.support.v4.app.FragmentActivity.html#android.support.v4.app.FragmentActivity.setSupportMediaController_changed(android.support.v4.media.session.MediaControllerCompat)" class="hiddenlink" target="rightframe">setSupportMediaController
+(<code>MediaControllerCompat</code>)</A></nobr><br>
+<nobr><A HREF="android.support.design.widget.Snackbar.html#android.support.design.widget.Snackbar.show_changed()" class="hiddenlink" target="rightframe">show
+()</A></nobr><br>
+<i>skipToNext</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.skipToNext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.skipToNext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.skipToNext_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<i>skipToPrevious</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.skipToPrevious_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.skipToPrevious_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.skipToPrevious_changed()" class="hiddenlink" target="rightframe">type
+() in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html#android.support.v17.leanback.widget.GuidedActionsStylist.startExpandedTransition_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder)" class="hiddenlink" target="rightframe">startExpandedTransition
+(<code>ViewHolder</code>)</A></nobr><br>
+<i>startPlayback</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html#android.support.v17.leanback.app.MediaControllerGlue.startPlayback_changed(int)" class="hiddenlink" target="rightframe">type
+(<code>int</code>) in android.support.v17.leanback.app.MediaControllerGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html#android.support.v17.leanback.app.PlaybackControlGlue.startPlayback_changed(int)" class="hiddenlink" target="rightframe">type
+(<code>int</code>) in android.support.v17.leanback.app.PlaybackControlGlue
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.startPlayback_changed(int)" class="hiddenlink" target="rightframe">type
+(<code>int</code>) in android.support.v17.leanback.app.PlaybackControlSupportGlue
+</A></nobr><br>
+<A NAME="U"></A>
+<br><font size="+2">U</font>
+<a href="#C"><font size="-2">C</font></a>
+<a href="#D"><font size="-2">D</font></a>
+<a href="#E"><font size="-2">E</font></a>
+<a href="#G"><font size="-2">G</font></a>
+<a href="#H"><font size="-2">H</font></a>
+<a href="#I"><font size="-2">I</font></a>
+<a href="#N"><font size="-2">N</font></a>
+<a href="#O"><font size="-2">O</font></a>
+<a href="#P"><font size="-2">P</font></a>
+<a href="#S"><font size="-2">S</font></a>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html#android.support.v17.leanback.app.PlaybackControlSupportGlue.updateProgress_changed()" class="hiddenlink" target="rightframe">updateProgress
+()</A></nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/methods_index_removals.html b/docs/html/sdk/support_api_diff/25.1.0/changes/methods_index_removals.html
new file mode 100644
index 0000000..76fb90c
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/methods_index_removals.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Method Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Methods" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="methods_index_all.html" class="staysblack">All Methods</a>
+ <br>
+<b>Removals</b>
+ <br>
+<A HREF="methods_index_additions.html"xclass="hiddenlink">Additions</A>
+ <br>
+<A HREF="methods_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<A NAME="H"></A>
+<br><font size="+2">H</font>
+ <a href="#topheader"><font size="-2">TOP</font></a>
+<p><div style="line-height:1.5em;color:black">
+<i>handleInputEvent</i><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.html#android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.handleInputEvent_removed(android.view.InputEvent)" class="hiddenlink" target="rightframe">type <strike>
+(<code>InputEvent</code>)</strike> in android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler
+</A></nobr><br>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.html#android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.handleInputEvent_removed(android.view.InputEvent)" class="hiddenlink" target="rightframe">type <strike>
+(<code>InputEvent</code>)</strike> in android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler
+</A></nobr><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/packages_index_additions.html b/docs/html/sdk/support_api_diff/25.1.0/changes/packages_index_additions.html
new file mode 100644
index 0000000..1776064
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/packages_index_additions.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Additions Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="packages_index_all.html" class="staysblack">All Packages</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<font color="#999999">Additions</font>
+ <br>
+<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/packages_index_all.html b/docs/html/sdk/support_api_diff/25.1.0/changes/packages_index_all.html
new file mode 100644
index 0000000..d849651
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/packages_index_all.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Differences Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<b>Packages</b>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<font color="#999999">Additions</font>
+ <br>
+<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<A NAME="A"></A>
+<A HREF="pkg_android.support.design.widget.html" class="hiddenlink" target="rightframe">android.support.design.widget</A><br>
+<A HREF="pkg_android.support.graphics.drawable.html" class="hiddenlink" target="rightframe">android.support.graphics.drawable</A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html" class="hiddenlink" target="rightframe">android.support.v17.leanback.app</A><br>
+<A HREF="pkg_android.support.v17.leanback.widget.html" class="hiddenlink" target="rightframe">android.support.v17.leanback.widget</A><br>
+<A HREF="pkg_android.support.v17.preference.html" class="hiddenlink" target="rightframe">android.support.v17.preference</A><br>
+<A HREF="pkg_android.support.v4.app.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<A HREF="pkg_android.support.v4.media.session.html" class="hiddenlink" target="rightframe">android.support.v4.media.session</A><br>
+<A HREF="pkg_android.support.v4.os.html" class="hiddenlink" target="rightframe">android.support.v4.os</A><br>
+<A HREF="pkg_android.support.v4.provider.html" class="hiddenlink" target="rightframe">android.support.v4.provider</A><br>
+<A HREF="pkg_android.support.v4.util.html" class="hiddenlink" target="rightframe">android.support.v4.util</A><br>
+<A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
+<A HREF="pkg_android.support.v7.media.html" class="hiddenlink" target="rightframe">android.support.v7.media</A><br>
+<A HREF="pkg_android.support.v7.preference.html" class="hiddenlink" target="rightframe">android.support.v7.preference</A><br>
+<A HREF="pkg_android.support.v7.widget.html" class="hiddenlink" target="rightframe">android.support.v7.widget</A><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/packages_index_changes.html b/docs/html/sdk/support_api_diff/25.1.0/changes/packages_index_changes.html
new file mode 100644
index 0000000..82a9399
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/packages_index_changes.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Changes Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="packages_index_all.html" class="staysblack">All Packages</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<font color="#999999">Additions</font>
+ <br>
+<b>Changes</b>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<A NAME="A"></A>
+<A HREF="pkg_android.support.design.widget.html" class="hiddenlink" target="rightframe">android.support.design.widget</A><br>
+<A HREF="pkg_android.support.graphics.drawable.html" class="hiddenlink" target="rightframe">android.support.graphics.drawable</A><br>
+<A HREF="pkg_android.support.v17.leanback.app.html" class="hiddenlink" target="rightframe">android.support.v17.leanback.app</A><br>
+<A HREF="pkg_android.support.v17.leanback.widget.html" class="hiddenlink" target="rightframe">android.support.v17.leanback.widget</A><br>
+<A HREF="pkg_android.support.v17.preference.html" class="hiddenlink" target="rightframe">android.support.v17.preference</A><br>
+<A HREF="pkg_android.support.v4.app.html" class="hiddenlink" target="rightframe">android.support.v4.app</A><br>
+<A HREF="pkg_android.support.v4.media.session.html" class="hiddenlink" target="rightframe">android.support.v4.media.session</A><br>
+<A HREF="pkg_android.support.v4.os.html" class="hiddenlink" target="rightframe">android.support.v4.os</A><br>
+<A HREF="pkg_android.support.v4.provider.html" class="hiddenlink" target="rightframe">android.support.v4.provider</A><br>
+<A HREF="pkg_android.support.v4.util.html" class="hiddenlink" target="rightframe">android.support.v4.util</A><br>
+<A HREF="pkg_android.support.v7.app.html" class="hiddenlink" target="rightframe">android.support.v7.app</A><br>
+<A HREF="pkg_android.support.v7.media.html" class="hiddenlink" target="rightframe">android.support.v7.media</A><br>
+<A HREF="pkg_android.support.v7.preference.html" class="hiddenlink" target="rightframe">android.support.v7.preference</A><br>
+<A HREF="pkg_android.support.v7.widget.html" class="hiddenlink" target="rightframe">android.support.v7.widget</A><br>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/packages_index_removals.html b/docs/html/sdk/support_api_diff/25.1.0/changes/packages_index_removals.html
new file mode 100644
index 0000000..9fd0f7e
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/packages_index_removals.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+Package Removals Index
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY class="gc-documentation" style="padding:12px;">
+<a NAME="topheader"></a>
+<table summary="Index for Packages" width="100%" class="jdiffIndex" border="0" cellspacing="0" cellpadding="0" style="padding-bottom:0;margin-bottom:0;">
+ <tr>
+ <th class="indexHeader">
+ Filter the Index:
+ </th>
+ </tr>
+ <tr>
+ <td class="indexText" style="line-height:1.3em;padding-left:2em;">
+<a href="packages_index_all.html" class="staysblack">All Packages</a>
+ <br>
+<font color="#999999">Removals</font>
+ <br>
+<font color="#999999">Additions</font>
+ <br>
+<A HREF="packages_index_changes.html"xclass="hiddenlink">Changes</A>
+ </td>
+ </tr>
+</table>
+<div id="indexTableCaption" style="background-color:#eee;padding:0 4px 0 4px;font-size:11px;margin-bottom:1em;">
+Listed as: <span style="color:#069"><strong>Added</strong></span>, <span style="color:#069"><strike>Removed</strike></span>, <span style="color:#069">Changed</span></font>
+</div>
+<br>
+<div id="indexTableEntries">
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.design.widget.html b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.design.widget.html
new file mode 100644
index 0000000..f59e04d
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.design.widget.html
@@ -0,0 +1,162 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.design.widget
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/design/widget/package-summary.html" target="_top"><font size="+1"><code>android.support.design.widget</code></font></A>
+</H2>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes and Interfaces" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Classes and Interfaces</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BaseTransientBottomBar"></A>
+ <nobr><A HREF="../../../../reference/android/support/design/widget/BaseTransientBottomBar.html" target="_top"><code>BaseTransientBottomBar</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BaseTransientBottomBar.BaseCallback"></A>
+ <nobr><A HREF="../../../../reference/android/support/design/widget/BaseTransientBottomBar.BaseCallback.html" target="_top"><code>BaseTransientBottomBar.<br>BaseCallback</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BaseTransientBottomBar.ContentViewCallback"></A>
+ <nobr><A HREF="../../../../reference/android/support/design/widget/BaseTransientBottomBar.ContentViewCallback.html" target="_top"><code><I>BaseTransientBottomBar.<br>ContentViewCallback</I></code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="Snackbar"></A>
+ <nobr><A HREF="android.support.design.widget.Snackbar.html">Snackbar</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="Snackbar.Callback"></A>
+ <nobr><A HREF="android.support.design.widget.Snackbar.Callback.html">Snackbar.Callback</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="TextInputLayout"></A>
+ <nobr><A HREF="android.support.design.widget.TextInputLayout.html">TextInputLayout</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.graphics.drawable.html b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.graphics.drawable.html
new file mode 100644
index 0000000..75a6568
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.graphics.drawable.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.graphics.drawable
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/graphics/drawable/package-summary.html" target="_top"><font size="+1"><code>android.support.graphics.drawable</code></font></A>
+</H2>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="AnimatedVectorDrawableCompat"></A>
+ <nobr><A HREF="../../../../reference/android/support/graphics/drawable/AnimatedVectorDrawableCompat.html" target="_top"><code>AnimatedVectorDrawableCompat</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v17.leanback.app.html b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v17.leanback.app.html
new file mode 100644
index 0000000..5fdcd94
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v17.leanback.app.html
@@ -0,0 +1,344 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.app
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v17/leanback/app/package-summary.html" target="_top"><font size="+1"><code>android.support.v17.leanback.app</code></font></A>
+</H2>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes and Interfaces" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Classes and Interfaces</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackControlGlue.InputEventHandler"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackControlGlue.InputEventHandler.html" target="_top"><code><I>PlaybackControlGlue.InputEventHandler</I></code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackFragment"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackFragment.html" target="_top"><code>PlaybackFragment</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackFragment.OnFadeCompleteListener"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackFragment.OnFadeCompleteListener.html" target="_top"><code>PlaybackFragment.OnFadeCompleteListener</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackFragmentGlueHost"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackFragmentGlueHost.html" target="_top"><code>PlaybackFragmentGlueHost</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackGlue"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackGlue.html" target="_top"><code>PlaybackGlue</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackGlue.HostLifecycleCallback"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackGlue.HostLifecycleCallback.html" target="_top"><code>PlaybackGlue.HostLifecycleCallback</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackGlue.PlaybackGlueHost"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackGlue.PlaybackGlueHost.html" target="_top"><code>PlaybackGlue.PlaybackGlueHost</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackGlue.PlayerCallback"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackGlue.PlayerCallback.html" target="_top"><code>PlaybackGlue.PlayerCallback</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackSupportFragment"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackSupportFragment.html" target="_top"><code>PlaybackSupportFragment</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackSupportFragment.OnFadeCompleteListener"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackSupportFragment.OnFadeCompleteListener.html" target="_top"><code>PlaybackSupportFragment.<br>OnFadeCompleteListener</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackSupportFragmentGlueHost"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/PlaybackSupportFragmentGlueHost.html" target="_top"><code>PlaybackSupportFragmentGlueHost</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="SurfaceHolderGlueHost"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/app/SurfaceHolderGlueHost.html" target="_top"><code><I>SurfaceHolderGlueHost</I></code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes and Interfaces" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes and Interfaces</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BackgroundManager"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.BackgroundManager.html">BackgroundManager</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BaseRowFragment"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.BaseRowFragment.html">BaseRowFragment</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BaseRowSupportFragment"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.BaseRowSupportFragment.html">BaseRowSupportFragment</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BrowseFragment"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseFragment.html">BrowseFragment</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BrowseFragment.MainFragmentRowsAdapter"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.html">BrowseFragment.MainFragmentRowsAdapter</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BrowseSupportFragment"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.html">BrowseSupportFragment</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BrowseSupportFragment.MainFragmentRowsAdapter"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.html">BrowseSupportFragment.<br>MainFragmentRowsAdapter</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="GuidedStepFragment"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepFragment.html">GuidedStepFragment</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="GuidedStepSupportFragment"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.GuidedStepSupportFragment.html">GuidedStepSupportFragment</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="MediaControllerGlue"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.MediaControllerGlue.html">MediaControllerGlue</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackControlGlue"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlGlue.html">PlaybackControlGlue</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackControlSupportGlue"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackControlSupportGlue.html">PlaybackControlSupportGlue</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackOverlayFragment"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.html">PlaybackOverlayFragment</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackOverlayFragment.InputEventHandler"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.html"><I>PlaybackOverlayFragment.<br>InputEventHandler</I></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackOverlaySupportFragment"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.html">PlaybackOverlaySupportFragment</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackOverlaySupportFragment.InputEventHandler"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.html"><I>PlaybackOverlaySupportFragment.<br>InputEventHandler</I></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="RowsFragment"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.RowsFragment.html">RowsFragment</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="RowsSupportFragment"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.RowsSupportFragment.html">RowsSupportFragment</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="SearchFragment"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.SearchFragment.html">SearchFragment</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="SearchSupportFragment"></A>
+ <nobr><A HREF="android.support.v17.leanback.app.SearchSupportFragment.html">SearchSupportFragment</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v17.leanback.widget.html b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v17.leanback.widget.html
new file mode 100644
index 0000000..328fb78
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v17.leanback.widget.html
@@ -0,0 +1,218 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.leanback.widget
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v17/leanback/widget/package-summary.html" target="_top"><font size="+1"><code>android.support.v17.leanback.widget</code></font></A>
+</H2>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackRowPresenter"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/widget/PlaybackRowPresenter.html" target="_top"><code>PlaybackRowPresenter</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackRowPresenter.ViewHolder"></A>
+ <nobr><A HREF="../../../../reference/android/support/v17/leanback/widget/PlaybackRowPresenter.ViewHolder.html" target="_top"><code>PlaybackRowPresenter.<br>ViewHolder</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BaseCardView"></A>
+ <nobr><A HREF="android.support.v17.leanback.widget.BaseCardView.html">BaseCardView</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BrowseFrameLayout"></A>
+ <nobr><A HREF="android.support.v17.leanback.widget.BrowseFrameLayout.html">BrowseFrameLayout</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="GuidedActionsStylist"></A>
+ <nobr><A HREF="android.support.v17.leanback.widget.GuidedActionsStylist.html">GuidedActionsStylist</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="HeaderItem"></A>
+ <nobr><A HREF="android.support.v17.leanback.widget.HeaderItem.html">HeaderItem</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="ObjectAdapter"></A>
+ <nobr><A HREF="android.support.v17.leanback.widget.ObjectAdapter.html">ObjectAdapter</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="OnChildViewHolderSelectedListener"></A>
+ <nobr><A HREF="android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.html">OnChildViewHolderSelectedListener</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackControlsRow"></A>
+ <nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRow.html">PlaybackControlsRow</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackControlsRowPresenter"></A>
+ <nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRowPresenter.html">PlaybackControlsRowPresenter</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PlaybackControlsRowPresenter.ViewHolder"></A>
+ <nobr><A HREF="android.support.v17.leanback.widget.PlaybackControlsRowPresenter.ViewHolder.html">PlaybackControlsRowPresenter.<br>ViewHolder</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="RowPresenter.ViewHolder"></A>
+ <nobr><A HREF="android.support.v17.leanback.widget.RowPresenter.ViewHolder.html">RowPresenter.ViewHolder</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="SearchBar"></A>
+ <nobr><A HREF="android.support.v17.leanback.widget.SearchBar.html">SearchBar</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="SpeechOrbView"></A>
+ <nobr><A HREF="android.support.v17.leanback.widget.SpeechOrbView.html">SpeechOrbView</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v17.preference.html b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v17.preference.html
new file mode 100644
index 0000000..6fef890
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v17.preference.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v17.preference
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v17/preference/package-summary.html" target="_top"><font size="+1"><code>android.support.v17.preference</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="LeanbackPreferenceFragment"></A>
+ <nobr><A HREF="android.support.v17.preference.LeanbackPreferenceFragment.html">LeanbackPreferenceFragment</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.app.html b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.app.html
new file mode 100644
index 0000000..11fdf22
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.app.html
@@ -0,0 +1,155 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.app
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/app/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.app</code></font></A>
+</H2>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="FragmentManager.FragmentLifecycleCallbacks"></A>
+ <nobr><A HREF="../../../../reference/android/support/v4/app/FragmentManager.FragmentLifecycleCallbacks.html" target="_top"><code>FragmentManager.FragmentLifecycleCallbacks</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="Fragment"></A>
+ <nobr><A HREF="android.support.v4.app.Fragment.html">Fragment</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="FragmentActivity"></A>
+ <nobr><A HREF="android.support.v4.app.FragmentActivity.html">FragmentActivity</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="FragmentManager"></A>
+ <nobr><A HREF="android.support.v4.app.FragmentManager.html">FragmentManager</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="FragmentTransaction"></A>
+ <nobr><A HREF="android.support.v4.app.FragmentTransaction.html">FragmentTransaction</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.media.session.html b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.media.session.html
new file mode 100644
index 0000000..a8a5cef
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.media.session.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.media.session
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/media/session/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.media.session</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="MediaControllerCompat"></A>
+ <nobr><A HREF="android.support.v4.media.session.MediaControllerCompat.html">MediaControllerCompat</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.os.html b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.os.html
new file mode 100644
index 0000000..33a5f1c
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.os.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.os
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/os/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.os</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="BuildCompat"></A>
+ <nobr><A HREF="android.support.v4.os.BuildCompat.html">BuildCompat</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.provider.html b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.provider.html
new file mode 100644
index 0000000..6c3acd5
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.provider.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.provider
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/provider/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.provider</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="DocumentFile"></A>
+ <nobr><A HREF="android.support.v4.provider.DocumentFile.html">DocumentFile</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.util.html b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.util.html
new file mode 100644
index 0000000..144adda
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v4.util.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v4.util
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v4/util/package-summary.html" target="_top"><font size="+1"><code>android.support.v4.util</code></font></A>
+</H2>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="ArraySet"></A>
+ <nobr><A HREF="../../../../reference/android/support/v4/util/ArraySet.html" target="_top"><code>ArraySet</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v7.app.html b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v7.app.html
new file mode 100644
index 0000000..83e0d6b
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v7.app.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.app
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v7/app/package-summary.html" target="_top"><font size="+1"><code>android.support.v7.app</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="MediaRouteChooserDialog"></A>
+ <nobr><A HREF="android.support.v7.app.MediaRouteChooserDialog.html">MediaRouteChooserDialog</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v7.media.html b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v7.media.html
new file mode 100644
index 0000000..efb3815
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v7.media.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.media
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v7/media/package-summary.html" target="_top"><font size="+1"><code>android.support.v7.media</code></font></A>
+</H2>
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="MediaRouter"></A>
+ <nobr><A HREF="android.support.v7.media.MediaRouter.html">MediaRouter</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="MediaRouter.RouteInfo"></A>
+ <nobr><A HREF="android.support.v7.media.MediaRouter.RouteInfo.html">MediaRouter.RouteInfo</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v7.preference.html b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v7.preference.html
new file mode 100644
index 0000000..0bbdc1e
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v7.preference.html
@@ -0,0 +1,148 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.preference
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v7/preference/package-summary.html" target="_top"><font size="+1"><code>android.support.v7.preference</code></font></A>
+</H2>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PreferenceManager.PreferenceComparisonCallback"></A>
+ <nobr><A HREF="../../../../reference/android/support/v7/preference/PreferenceManager.PreferenceComparisonCallback.html" target="_top"><code>PreferenceManager.PreferenceComparisonCallback</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PreferenceManager.SimplePreferenceComparisonCallback"></A>
+ <nobr><A HREF="../../../../reference/android/support/v7/preference/PreferenceManager.SimplePreferenceComparisonCallback.html" target="_top"><code>PreferenceManager.SimplePreferenceComparisonCallback</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="SeekBarPreference"></A>
+ <nobr><A HREF="../../../../reference/android/support/v7/preference/SeekBarPreference.html" target="_top"><code>SeekBarPreference</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PreferenceManager"></A>
+ <nobr><A HREF="android.support.v7.preference.PreferenceManager.html">PreferenceManager</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v7.widget.html b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v7.widget.html
new file mode 100644
index 0000000..e4fcc86
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/changes/pkg_android.support.v7.widget.html
@@ -0,0 +1,155 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML style="overflow:auto;">
+<HEAD>
+<meta name="generator" content="JDiff v1.1.0">
+<!-- Generated by the JDiff Javadoc doclet -->
+<!-- (http://www.jdiff.org) -->
+<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
+<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
+<TITLE>
+android.support.v7.widget
+</TITLE>
+<link href="../../../../assets/android-developer-docs.css" rel="stylesheet" type="text/css" />
+<link href="../stylesheet-jdiff.css" rel="stylesheet" type="text/css" />
+<noscript>
+<style type="text/css">
+body{overflow:auto;}
+#body-content{position:relative; top:0;}
+#doc-content{overflow:visible;border-left:3px solid #666;}
+#side-nav{padding:0;}
+#side-nav .toggle-list ul {display:block;}
+#resize-packages-nav{border-bottom:3px solid #666;}
+</style>
+</noscript>
+<style type="text/css">
+</style>
+</HEAD>
+<BODY>
+<!-- Start of nav bar -->
+<a name="top"></a>
+<div id="header" style="margin-bottom:0;padding-bottom:0;">
+<div id="headerLeft">
+<a href="../../../../index.html" tabindex="-1" target="_top"><img src="../../../../assets/images/bg_logo.png" alt="Android Developers" /></a>
+</div>
+ <div id="headerRight">
+ <div id="headerLinks">
+<!-- <img src="/assets/images/icon_world.jpg" alt="" /> -->
+<span class="text">
+<!-- <a href="#">English</a> | -->
+<nobr><a href="http://developer.android.com" target="_top">Android Developers</a> | <a href="http://www.android.com" target="_top">Android.com</a></nobr>
+</span>
+</div>
+ <div class="and-diff-id" style="margin-top:6px;margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td colspan="2" class="diffspechead">API Diff Specification</td>
+ </tr>
+ <tr>
+ <td class="diffspec" style="padding-top:.25em">To Level:</td>
+ <td class="diffvaluenew" style="padding-top:.25em">25.1.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">From Level:</td>
+ <td class="diffvalueold">25.0.0</td>
+ </tr>
+ <tr>
+ <td class="diffspec">Generated</td>
+ <td class="diffvalue">2016.12.08 16:29</td>
+ </tr>
+ </table>
+ </div><!-- End and-diff-id -->
+ <div class="and-diff-id" style="margin-right:8px;">
+ <table class="diffspectable">
+ <tr>
+ <td class="diffspec" colspan="2"><a href="jdiff_statistics.html">Statistics</a>
+ </tr>
+ </table>
+ </div> <!-- End and-diff-id -->
+ </div> <!-- End headerRight -->
+ </div> <!-- End header -->
+<div id="body-content" xstyle="padding:12px;padding-right:18px;">
+<div id="doc-content" style="position:relative;">
+<div id="mainBodyFluid">
+<H2>
+Package <A HREF="../../../../reference/android/support/v7/widget/package-summary.html" target="_top"><font size="+1"><code>android.support.v7.widget</code></font></A>
+</H2>
+<p>
+<a NAME="Added"></a>
+<TABLE summary="Added Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Added Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="PagerSnapHelper"></A>
+ <nobr><A HREF="../../../../reference/android/support/v7/widget/PagerSnapHelper.html" target="_top"><code>PagerSnapHelper</code></A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+<p>
+<a NAME="Changed"></a>
+<TABLE summary="Changed Classes" WIDTH="100%">
+<TR>
+ <TH VALIGN="TOP" COLSPAN=2>Changed Classes</FONT></TD>
+</TH>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="LinearLayoutCompat"></A>
+ <nobr><A HREF="android.support.v7.widget.LinearLayoutCompat.html">LinearLayoutCompat</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="RecyclerView"></A>
+ <nobr><A HREF="android.support.v7.widget.RecyclerView.html">RecyclerView</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="RecyclerView.RecycledViewPool"></A>
+ <nobr><A HREF="android.support.v7.widget.RecyclerView.RecycledViewPool.html">RecyclerView.RecycledViewPool</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+<TR BGCOLOR="#FFFFFF" CLASS="TableRowColor">
+ <TD VALIGN="TOP" WIDTH="25%">
+ <A NAME="SnapHelper"></A>
+ <nobr><A HREF="android.support.v7.widget.SnapHelper.html">SnapHelper</A></nobr>
+ </TD>
+ <TD> </TD>
+</TR>
+</TABLE>
+
+ </div>
+ <div id="footer">
+ <div id="copyright">
+ Except as noted, this content is licensed under
+ <a href="http://creativecommons.org/licenses/by/2.5/"> Creative Commons Attribution 2.5</a>.
+ For details and restrictions, see the <a href="/license.html">Content License</a>.
+ </div>
+ <div id="footerlinks">
+ <p>
+ <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
+ <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
+ <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+ </p>
+ </div>
+ </div> <!-- end footer -->
+ </div><!-- end doc-content -->
+ </div> <!-- end body-content -->
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("UA-5831155-1");
+ pageTracker._setAllowAnchor(true);
+ pageTracker._initData();
+ pageTracker._trackPageview();
+ } catch(e) {}
+</script>
+</BODY>
+</HTML>
diff --git a/docs/html/sdk/support_api_diff/25.1.0/missingSinces.txt b/docs/html/sdk/support_api_diff/25.1.0/missingSinces.txt
new file mode 100644
index 0000000..e0e20f1
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/missingSinces.txt
@@ -0,0 +1,98 @@
+NO DOC BLOCK: android.support.graphics.drawable.AnimatedVectorDrawableCompat Class
+NO DOC BLOCK: android.support.v4.util.ArraySet Class
+NO DOC BLOCK: android.support.design.widget.BaseTransientBottomBar Class
+NO DOC BLOCK: android.support.design.widget.BaseTransientBottomBar.BaseCallback Class
+NO DOC BLOCK: android.support.design.widget.BaseTransientBottomBar.ContentViewCallback Interface
+NO DOC BLOCK: android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks Class
+NO DOC BLOCK: android.support.v7.widget.PagerSnapHelper Class
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler Interface
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackFragment Class
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackFragment.OnFadeCompleteListener Class
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackFragmentGlueHost Class
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackGlue Class
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackGlue.HostLifecycleCallback Class
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost Class
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackGlue.PlayerCallback Class
+NO DOC BLOCK: android.support.v17.leanback.widget.PlaybackRowPresenter Class
+NO DOC BLOCK: android.support.v17.leanback.widget.PlaybackRowPresenter.ViewHolder Class
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackSupportFragment Class
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackSupportFragment.OnFadeCompleteListener Class
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackSupportFragmentGlueHost Class
+NO DOC BLOCK: android.support.v7.preference.PreferenceManager.PreferenceComparisonCallback Class
+NO DOC BLOCK: android.support.v7.preference.PreferenceManager.SimplePreferenceComparisonCallback Class
+NO DOC BLOCK: android.support.v7.preference.SeekBarPreference Class
+NO DOC BLOCK: android.support.v17.leanback.app.SurfaceHolderGlueHost Interface
+NO DOC BLOCK: android.support.v17.leanback.app.MediaControllerGlue Constructor (android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackControlGlue Constructor (android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])
+NO DOC BLOCK: android.support.v17.leanback.app.BackgroundManager Method attachToView(android.view.View)
+NO DOC BLOCK: android.support.v17.leanback.app.BackgroundManager Method clearDrawable()
+NO DOC BLOCK: android.support.v17.leanback.app.GuidedStepFragment Method collapseAction(boolean)
+NO DOC BLOCK: android.support.v17.leanback.app.GuidedStepSupportFragment Method collapseAction(boolean)
+NO DOC BLOCK: android.support.v17.leanback.widget.GuidedActionsStylist Method collapseAction(boolean)
+NO DOC BLOCK: android.support.v7.widget.SnapHelper Method createSnapScroller(android.support.v7.widget.RecyclerView.LayoutManager)
+NO DOC BLOCK: android.support.v17.leanback.app.GuidedStepFragment Method expandAction(android.support.v17.leanback.widget.GuidedAction, boolean)
+NO DOC BLOCK: android.support.v17.leanback.app.GuidedStepSupportFragment Method expandAction(android.support.v17.leanback.widget.GuidedAction, boolean)
+NO DOC BLOCK: android.support.v17.leanback.widget.GuidedActionsStylist Method expandAction(android.support.v17.leanback.widget.GuidedAction, boolean)
+NO DOC BLOCK: android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter Method findRowViewHolderByPosition(int)
+NO DOC BLOCK: android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter Method findRowViewHolderByPosition(int)
+NO DOC BLOCK: android.support.v17.leanback.app.RowsFragment Method findRowViewHolderByPosition(int)
+NO DOC BLOCK: android.support.v17.leanback.app.RowsSupportFragment Method findRowViewHolderByPosition(int)
+NO DOC BLOCK: android.support.v7.media.MediaRouter Method getBluetoothRoute()
+NO DOC BLOCK: android.support.v17.leanback.widget.PlaybackControlsRow Method getBufferedProgressLong()
+NO DOC BLOCK: android.support.v17.leanback.widget.PlaybackControlsRow Method getCurrentTimeLong()
+NO DOC BLOCK: android.support.v17.leanback.widget.HeaderItem Method getDescription()
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackOverlayFragment Method getEventHandler()
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackOverlaySupportFragment Method getEventHandler()
+NO DOC BLOCK: android.support.v7.widget.LinearLayoutCompat Method getGravity()
+NO DOC BLOCK: android.support.v17.leanback.app.BrowseFragment Method getMainFragment()
+NO DOC BLOCK: android.support.v17.leanback.app.BrowseSupportFragment Method getMainFragment()
+NO DOC BLOCK: android.support.v4.media.session.MediaControllerCompat Method getMediaController(android.app.Activity)
+NO DOC BLOCK: android.support.v7.preference.PreferenceManager Method getPreferenceComparisonCallback()
+NO DOC BLOCK: android.support.v7.widget.RecyclerView.RecycledViewPool Method getRecycledViewCount(int)
+NO DOC BLOCK: android.support.v17.leanback.widget.RowPresenter.ViewHolder Method getSelectedItem()
+NO DOC BLOCK: android.support.v17.leanback.widget.RowPresenter.ViewHolder Method getSelectedItemViewHolder()
+NO DOC BLOCK: android.support.v17.leanback.app.BrowseFragment Method getSelectedRowViewHolder()
+NO DOC BLOCK: android.support.v17.leanback.app.BrowseSupportFragment Method getSelectedRowViewHolder()
+NO DOC BLOCK: android.support.v17.leanback.widget.PlaybackControlsRow Method getTotalTimeLong()
+NO DOC BLOCK: android.support.v17.leanback.app.BaseRowFragment Method getVerticalGridView()
+NO DOC BLOCK: android.support.v17.leanback.app.BaseRowSupportFragment Method getVerticalGridView()
+NO DOC BLOCK: android.support.v4.os.BuildCompat Method isAtLeastO()
+NO DOC BLOCK: android.support.v17.leanback.app.BackgroundManager Method isAutoReleaseOnStop()
+NO DOC BLOCK: android.support.v17.leanback.widget.GuidedActionsStylist Method isBackKeyToCollapseActivatorView()
+NO DOC BLOCK: android.support.v17.leanback.widget.GuidedActionsStylist Method isBackKeyToCollapseSubActions()
+NO DOC BLOCK: android.support.v7.media.MediaRouter.RouteInfo Method isBluetooth()
+NO DOC BLOCK: android.support.v7.media.MediaRouter.RouteInfo Method isDeviceSpeaker()
+NO DOC BLOCK: android.support.v17.leanback.app.GuidedStepFragment Method isExpanded()
+NO DOC BLOCK: android.support.v17.leanback.app.GuidedStepSupportFragment Method isExpanded()
+NO DOC BLOCK: android.support.v17.leanback.widget.GuidedActionsStylist Method isExpanded()
+NO DOC BLOCK: android.support.v4.provider.DocumentFile Method isVirtual()
+NO DOC BLOCK: android.support.v17.leanback.widget.OnChildViewHolderSelectedListener Method onChildViewHolderSelectedAndPositioned(android.support.v7.widget.RecyclerView, android.support.v7.widget.RecyclerView.ViewHolder, int, int)
+NO DOC BLOCK: android.support.v17.leanback.widget.GuidedActionsStylist Method onEditingModeChange(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean, boolean)
+NO DOC BLOCK: android.support.v4.app.Fragment Method postponeEnterTransition()
+NO DOC BLOCK: android.support.v4.app.FragmentManager Method registerFragmentLifecycleCallbacks(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks, boolean)
+NO DOC BLOCK: android.support.v4.app.FragmentTransaction Method setAllowOptimization(boolean)
+NO DOC BLOCK: android.support.v17.leanback.app.BackgroundManager Method setAutoReleaseOnStop(boolean)
+NO DOC BLOCK: android.support.v17.leanback.widget.GuidedActionsStylist Method setBackKeyToCollapseActivatorView(boolean)
+NO DOC BLOCK: android.support.v17.leanback.widget.GuidedActionsStylist Method setBackKeyToCollapseSubActions(boolean)
+NO DOC BLOCK: android.support.v17.leanback.widget.PlaybackControlsRow Method setBufferedProgressLong(long)
+NO DOC BLOCK: android.support.v17.leanback.widget.PlaybackControlsRow Method setCurrentTimeLong(long)
+NO DOC BLOCK: android.support.v17.leanback.widget.HeaderItem Method setDescription(java.lang.CharSequence)
+NO DOC BLOCK: android.support.design.widget.TextInputLayout Method setErrorTextAppearance(int)
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackOverlayFragment Method setEventHandler(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)
+NO DOC BLOCK: android.support.v17.leanback.app.PlaybackOverlaySupportFragment Method setEventHandler(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)
+NO DOC BLOCK: android.support.v17.leanback.widget.SpeechOrbView Method setListeningOrbColors(android.support.v17.leanback.widget.SearchOrbView.Colors)
+NO DOC BLOCK: android.support.v4.media.session.MediaControllerCompat Method setMediaController(android.app.Activity, android.support.v4.media.session.MediaControllerCompat)
+NO DOC BLOCK: android.support.v17.leanback.widget.SpeechOrbView Method setNotListeningOrbColors(android.support.v17.leanback.widget.SearchOrbView.Colors)
+NO DOC BLOCK: android.support.v17.leanback.widget.BrowseFrameLayout Method setOnDispatchKeyListener(android.view.View.OnKeyListener)
+NO DOC BLOCK: android.support.v7.preference.PreferenceManager Method setPreferenceComparisonCallback(android.support.v7.preference.PreferenceManager.PreferenceComparisonCallback)
+NO DOC BLOCK: android.support.v17.leanback.app.SearchFragment Method setSearchAffordanceColors(android.support.v17.leanback.widget.SearchOrbView.Colors)
+NO DOC BLOCK: android.support.v17.leanback.app.SearchSupportFragment Method setSearchAffordanceColors(android.support.v17.leanback.widget.SearchOrbView.Colors)
+NO DOC BLOCK: android.support.v17.leanback.widget.SearchBar Method setSearchAffordanceColors(android.support.v17.leanback.widget.SearchOrbView.Colors)
+NO DOC BLOCK: android.support.v17.leanback.app.SearchFragment Method setSearchAffordanceColorsInListening(android.support.v17.leanback.widget.SearchOrbView.Colors)
+NO DOC BLOCK: android.support.v17.leanback.app.SearchSupportFragment Method setSearchAffordanceColorsInListening(android.support.v17.leanback.widget.SearchOrbView.Colors)
+NO DOC BLOCK: android.support.v17.leanback.widget.SearchBar Method setSearchAffordanceColorsInListening(android.support.v17.leanback.widget.SearchOrbView.Colors)
+NO DOC BLOCK: android.support.v17.preference.LeanbackPreferenceFragment Method setTitle(java.lang.CharSequence)
+NO DOC BLOCK: android.support.v17.leanback.widget.PlaybackControlsRow Method setTotalTimeLong(long)
+NO DOC BLOCK: android.support.v7.widget.RecyclerView Method smoothScrollBy(int, int, android.view.animation.Interpolator)
+NO DOC BLOCK: android.support.v4.app.Fragment Method startPostponedEnterTransition()
+NO DOC BLOCK: android.support.v4.app.FragmentManager Method unregisterFragmentLifecycleCallbacks(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks)
diff --git a/docs/html/sdk/support_api_diff/25.1.0/stylesheet-jdiff.css b/docs/html/sdk/support_api_diff/25.1.0/stylesheet-jdiff.css
new file mode 100644
index 0000000..edafaa3
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/stylesheet-jdiff.css
@@ -0,0 +1,44 @@
+
+/* (http://www.jdiff.org) */
+
+div.and-diff-id {border: 1px solid #eee;position:relative;float:right;clear:both;padding:0px;}
+table.diffspectable {border:1px;padding:0px;margin:0px;}
+.diffspechead {background-color:#eee;}
+.diffspectable tr {border:0px;padding:0px;}
+.diffspectable td {background-color:eee;border:0px;font-size:90%;font-weight:normal;padding:0px;padding-left:1px;padding-right:1px;text-align:center;color:777;}
+td.diffvalueold {color:orange;background-color:white;border:0px;font-size:80%;font-style:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;}
+td.diffvaluenew {color:green;background-color:white;border:0px;font-size:80%;font-weight:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;}
+td.diffvalue {color:444;background-color:white;border:0px;font-size:80%;font-weight:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;}
+td.diffspec {background-color:white;border:0px;font-size:80%;font-weight:normal;padding:1px;color:444;text-align:right;padding-right:.5em;line-height:.95em;}
+tt {font-size:11pt;font-family:monospace;}
+.indexHeader {
+ font-size:96%;
+ line-height:.8em;}
+.jdiffIndex td {
+ font-size:96%;
+ xline-height:.8em;
+ padding:2px;
+ padding-left:1em;}
+.indexText {
+ font-size:100%;
+ padding-left:1em;}
+#indexTableCaption {
+ font-size:96%;
+ margin-top:.25em;
+ margin-bottom:0;
+ }
+.hiddenlink {
+ font-size:96%;
+ line-height:.8em;
+ text-decoration:none;}
+a {
+ text-decoration:none;}
+a:hover {
+ text-decoration:underline;}
+.indexBox {
+ border: 1px solid red;
+ margin:1em 0 0 0;}
+.letterIndexHead {
+ font-size: 1.5em;font-weight:9;
+ margin:0 0 0em 0;
+ border: 1px solid red;}
diff --git a/docs/html/sdk/support_api_diff/25.1.0/user_comments_for_25.0.0_to_25.1.0.xml b/docs/html/sdk/support_api_diff/25.1.0/user_comments_for_25.0.0_to_25.1.0.xml
new file mode 100644
index 0000000..b3dcd67
--- /dev/null
+++ b/docs/html/sdk/support_api_diff/25.1.0/user_comments_for_25.0.0_to_25.1.0.xml
@@ -0,0 +1,1459 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
+<comments
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+ xsi:noNamespaceSchemaLocation='comments.xsd'
+ name="25.0.0_to_25.1.0"
+ jdversion="1.1.0">
+
+<!-- Use this file to enter an API change description. For example, when you remove a class,
+ you can enter a comment for that class that points developers to the replacement class.
+ You can also provide a change summary for modified API, to give an overview of the changes
+ why they were made, workarounds, etc. -->
+
+<!-- When the API diffs report is generated, the comments in this file get added to the tables of
+ removed, added, and modified packages, classes, methods, and fields. This file does not ship
+ with the final report. -->
+
+<!-- The id attribute in an identifier element identifies the change as noted in the report.
+ An id has the form package[.class[.[ctor|method|field].signature]], where [] indicates optional
+ text. A comment element can have multiple identifier elements, which will will cause the same
+ text to appear at each place in the report, but will be converted to separate comments when the
+ comments file is used. -->
+
+<!-- HTML tags in the text field will appear in the report. You also need to close p HTML elements,
+ used for paragraphs - see the top-level documentation. -->
+
+<!-- You can include standard javadoc links in your change descriptions. You can use the @first command
+ to cause jdiff to include the first line of the API documentation. You also need to close p HTML
+ elements, used for paragraphs - see the top-level documentation. -->
+
+<comment>
+ <identifier id="android.support.design.widget"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.BaseTransientBottomBar"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.BaseTransientBottomBar.BaseCallback"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.BaseTransientBottomBar.ContentViewCallback"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.BaseTransientBottomBar.dismiss_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.BaseTransientBottomBar.getDuration_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.BaseTransientBottomBar.getView_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.BaseTransientBottomBar.isShownOrQueued_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.BaseTransientBottomBar.isShown_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.BaseTransientBottomBar.setDuration_changed(int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.BaseTransientBottomBar.show_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.Snackbar"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.Snackbar.Callback"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.Snackbar.setCallback_changed(android.support.design.widget.Snackbar.Callback)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.TextInputLayout"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.design.widget.TextInputLayout.setErrorTextAppearance_added(int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.graphics.drawable"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.graphics.drawable.AnimatedVectorDrawableCompat"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BackgroundManager"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BackgroundManager.attachToView_added(android.view.View)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BackgroundManager.clearDrawable_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BackgroundManager.getDefaultDimLayer_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BackgroundManager.getDimLayer_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BackgroundManager.isAutoReleaseOnStop_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BackgroundManager.setAutoReleaseOnStop_added(boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BackgroundManager.setDimLayer_changed(android.graphics.drawable.Drawable)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BaseRowFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BaseRowFragment.getVerticalGridView_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BaseRowSupportFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BaseRowSupportFragment.getVerticalGridView_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BrowseFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BrowseFragment.MainFragmentRowsAdapter.findRowViewHolderByPosition_added(int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BrowseFragment.getMainFragment_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BrowseFragment.getSelectedRowViewHolder_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BrowseSupportFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BrowseSupportFragment.MainFragmentRowsAdapter.findRowViewHolderByPosition_added(int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BrowseSupportFragment.getMainFragment_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.BrowseSupportFragment.getSelectedRowViewHolder_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.GuidedStepFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.GuidedStepFragment.collapseAction_added(boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.GuidedStepFragment.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.GuidedStepFragment.isExpanded_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.GuidedStepSupportFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.GuidedStepSupportFragment.collapseAction_added(boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.GuidedStepSupportFragment.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.GuidedStepSupportFragment.isExpanded_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.MediaControllerGlue"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.MediaControllerGlue.ctor_added(android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.MediaControllerGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[])"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.MediaControllerGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[])"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.createControlsRowAndPresenter_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.createPrimaryActionsAdapter_changed(android.support.v17.leanback.widget.PresenterSelector)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.ctor_added(android.content.Context, android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost, int[], int[])"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[])"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.ctor_changed(android.content.Context, android.support.v17.leanback.app.PlaybackOverlayFragment, int[], int[])"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.enableProgressUpdating_changed(boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getControlsRow_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getCurrentPosition_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getCurrentSpeedId_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getFastForwardSpeeds_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getFragment_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getFragment_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getMediaArt_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getMediaDuration_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getMediaSubtitle_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getMediaTitle_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getOnItemViewClickedListener_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getOnItemViewClickedListener_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getRewindSpeeds_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getSupportedActions_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.getUpdatePeriod_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.hasValidMedia_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.isFadingEnabled_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.isMediaPlaying_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.onActionClicked_changed(android.support.v17.leanback.widget.Action)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.onKey_changed(android.view.View, int, android.view.KeyEvent)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.onMetadataChanged_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.onRowChanged_changed(android.support.v17.leanback.widget.PlaybackControlsRow)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.onRowChanged_changed(android.support.v17.leanback.widget.PlaybackControlsRow)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.onStateChanged_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.pausePlayback_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.pausePlayback_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.pausePlayback_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.setControlsRow_changed(android.support.v17.leanback.widget.PlaybackControlsRow)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.setFadingEnabled_changed(boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.setOnItemViewClickedListener_changed(android.support.v17.leanback.widget.OnItemViewClickedListener)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.skipToNext_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.skipToNext_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.skipToNext_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.skipToPrevious_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.skipToPrevious_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.skipToPrevious_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.startPlayback_changed(int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.startPlayback_changed(int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.startPlayback_changed(int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlGlue.updateProgress_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackControlSupportGlue"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackFragment.OnFadeCompleteListener"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackFragmentGlueHost"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackGlue"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackGlue.HostLifecycleCallback"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackGlue.PlaybackGlueHost"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackGlue.PlayerCallback"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackGlue.getContext_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackGlue.getContext_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackOverlayFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler.handleInputEvent_removed(android.view.InputEvent)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackOverlayFragment.getEventHandler_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackOverlayFragment.getInputEventHandler_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackOverlayFragment.setEventHandler_added(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackOverlayFragment.setInputEventHandler_changed(android.support.v17.leanback.app.PlaybackOverlayFragment.InputEventHandler)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackOverlaySupportFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler.handleInputEvent_removed(android.view.InputEvent)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.getEventHandler_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.getInputEventHandler_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.setEventHandler_added(android.support.v17.leanback.app.PlaybackControlGlue.InputEventHandler)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackOverlaySupportFragment.setInputEventHandler_changed(android.support.v17.leanback.app.PlaybackOverlaySupportFragment.InputEventHandler)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackSupportFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackSupportFragment.OnFadeCompleteListener"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.PlaybackSupportFragmentGlueHost"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.RowsFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.RowsFragment.findRowViewHolderByPosition_added(int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.RowsSupportFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.RowsSupportFragment.findRowViewHolderByPosition_added(int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.SearchFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.SearchFragment.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.SearchFragment.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.SearchSupportFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.SearchSupportFragment.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.SearchSupportFragment.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.app.SurfaceHolderGlueHost"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.BaseCardView"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.BaseCardView.getExtraVisibility_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.BaseCardView.setExtraVisibility_changed(int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.BrowseFrameLayout"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.BrowseFrameLayout.setOnDispatchKeyListener_added(android.view.View.OnKeyListener)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.GuidedActionsStylist"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.GuidedActionsStylist.collapseAction_added(boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.GuidedActionsStylist.expandAction_added(android.support.v17.leanback.widget.GuidedAction, boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.GuidedActionsStylist.isBackKeyToCollapseActivatorView_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.GuidedActionsStylist.isBackKeyToCollapseSubActions_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.GuidedActionsStylist.isExpanded_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.GuidedActionsStylist.onEditingModeChange_added(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean, boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.GuidedActionsStylist.onEditingModeChange_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.GuidedActionsStylist.setBackKeyToCollapseActivatorView_added(boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.GuidedActionsStylist.setBackKeyToCollapseSubActions_added(boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.GuidedActionsStylist.setEditingMode_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.GuidedActionsStylist.setExpandedViewHolder_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.GuidedActionsStylist.startExpandedTransition_changed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.HeaderItem"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.HeaderItem.getDescription_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.HeaderItem.setDescription_added(java.lang.CharSequence)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.ObjectAdapter"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.ObjectAdapter.notifyItemRangeChanged_changed(int, int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.OnChildViewHolderSelectedListener"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.OnChildViewHolderSelectedListener.onChildViewHolderSelectedAndPositioned_added(android.support.v7.widget.RecyclerView, android.support.v7.widget.RecyclerView.ViewHolder, int, int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.PlaybackControlsRow"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.PlaybackControlsRow.getBufferedProgressLong_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.PlaybackControlsRow.getCurrentTimeLong_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.PlaybackControlsRow.getTotalTimeLong_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.PlaybackControlsRow.setBufferedProgressLong_added(long)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.PlaybackControlsRow.setCurrentTimeLong_added(long)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.PlaybackControlsRow.setTotalTimeLong_added(long)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.PlaybackControlsRowPresenter"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.PlaybackControlsRowPresenter.ViewHolder"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.PlaybackRowPresenter"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.PlaybackRowPresenter.ViewHolder"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.RowPresenter.ViewHolder"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.RowPresenter.ViewHolder.getSelectedItemViewHolder_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.RowPresenter.ViewHolder.getSelectedItem_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.SearchBar"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.SearchBar.setSearchAffordanceColorsInListening_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.SearchBar.setSearchAffordanceColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.SpeechOrbView"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.SpeechOrbView.setListeningOrbColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.leanback.widget.SpeechOrbView.setNotListeningOrbColors_added(android.support.v17.leanback.widget.SearchOrbView.Colors)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.preference"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.preference.LeanbackPreferenceFragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v17.preference.LeanbackPreferenceFragment.setTitle_added(java.lang.CharSequence)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.Fragment"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.Fragment.postponeEnterTransition_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.Fragment.startPostponedEnterTransition_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.FragmentActivity"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.FragmentActivity.getSupportMediaController_changed()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.FragmentActivity.setSupportMediaController_changed(android.support.v4.media.session.MediaControllerCompat)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.FragmentManager"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.FragmentManager.registerFragmentLifecycleCallbacks_added(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks, boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.FragmentManager.unregisterFragmentLifecycleCallbacks_added(android.support.v4.app.FragmentManager.FragmentLifecycleCallbacks)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.FragmentTransaction"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.app.FragmentTransaction.setAllowOptimization_added(boolean)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.media.session"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.media.session.MediaControllerCompat"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.media.session.MediaControllerCompat.getMediaController_added(android.app.Activity)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.media.session.MediaControllerCompat.setMediaController_added(android.app.Activity, android.support.v4.media.session.MediaControllerCompat)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.os"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.os.BuildCompat"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.os.BuildCompat.isAtLeastO_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.provider"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.provider.DocumentFile"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.provider.DocumentFile.isVirtual_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.util"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v4.util.ArraySet"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.app"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.app.MediaRouteChooserDialog"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.media"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.media.MediaRouter"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.media.MediaRouter.RouteInfo"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.media.MediaRouter.RouteInfo.isBluetooth_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.media.MediaRouter.RouteInfo.isDeviceSpeaker_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.media.MediaRouter.getBluetoothRoute_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.preference"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.preference.PreferenceManager"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.preference.PreferenceManager.PreferenceComparisonCallback"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.preference.PreferenceManager.SimplePreferenceComparisonCallback"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.preference.PreferenceManager.getPreferenceComparisonCallback_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.preference.PreferenceManager.setPreferenceComparisonCallback_added(android.support.v7.preference.PreferenceManager.PreferenceComparisonCallback)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.preference.SeekBarPreference"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.LinearLayoutCompat"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.LinearLayoutCompat.getGravity_added()"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.PagerSnapHelper"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.RecyclerView"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.RecyclerView.RecycledViewPool"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.RecyclerView.RecycledViewPool.getRecycledViewCount_added(int)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.RecyclerView.smoothScrollBy_added(int, int, android.view.animation.Interpolator)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.SnapHelper"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+<comment>
+ <identifier id="android.support.v7.widget.SnapHelper.createSnapScroller_added(android.support.v7.widget.RecyclerView.LayoutManager)"/>
+ <text>
+ InsertCommentsHere
+ </text>
+</comment>
+
+</comments>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 756087c..cd75fe9 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -467,7 +467,11 @@
/**
- * @hide
+ * Special configuration, when bitmap is stored only in graphic memory.
+ * Bitmaps in this configuration are always immutable.
+ *
+ * It is optimal for cases, when the only operation with the bitmap is to draw it on a
+ * screen.
*/
HARDWARE (6);
@@ -810,7 +814,8 @@
* @param width The width of the bitmap
* @param height The height of the bitmap
* @param config The bitmap config to create.
- * @throws IllegalArgumentException if the width or height are <= 0
+ * @throws IllegalArgumentException if the width or height are <= 0, or if
+ * Config is Config.HARDWARE, because hardware bitmaps are always immutable
*/
public static Bitmap createBitmap(int width, int height, Config config) {
return createBitmap(width, height, config, true);
@@ -825,7 +830,8 @@
* @param width The width of the bitmap
* @param height The height of the bitmap
* @param config The bitmap config to create.
- * @throws IllegalArgumentException if the width or height are <= 0
+ * @throws IllegalArgumentException if the width or height are <= 0, or if
+ * Config is Config.HARDWARE, because hardware bitmaps are always immutable
*/
public static Bitmap createBitmap(DisplayMetrics display, int width,
int height, Config config) {
@@ -843,7 +849,8 @@
* bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
*
- * @throws IllegalArgumentException if the width or height are <= 0
+ * @throws IllegalArgumentException if the width or height are <= 0, or if
+ * Config is Config.HARDWARE, because hardware bitmaps are always immutable
*/
private static Bitmap createBitmap(int width, int height, Config config, boolean hasAlpha) {
return createBitmap(null, width, height, config, hasAlpha);
@@ -862,13 +869,17 @@
* bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
*
- * @throws IllegalArgumentException if the width or height are <= 0
+ * @throws IllegalArgumentException if the width or height are <= 0, or if
+ * Config is Config.HARDWARE, because hardware bitmaps are always immutable
*/
private static Bitmap createBitmap(DisplayMetrics display, int width, int height,
Config config, boolean hasAlpha) {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("width and height must be > 0");
}
+ if (config == Config.HARDWARE) {
+ throw new IllegalArgumentException("can't create mutable bitmap with Config.HARDWARE");
+ }
Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true);
if (display != null) {
bm.mDensity = display.densityDpi;
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 447a4c4..a5517f0 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -16,6 +16,8 @@
package android.graphics;
+import static android.graphics.BitmapFactory.Options.validate;
+
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.Trace;
@@ -103,6 +105,9 @@
* If set, decode methods will always return a mutable Bitmap instead of
* an immutable one. This can be used for instance to programmatically apply
* effects to a Bitmap loaded through BitmapFactory.
+ * <p>Can not be set simultaneously with inPreferredConfig =
+ * {@link android.graphics.Bitmap.Config#HARDWARE},
+ * because hardware bitmaps are always immutable.
*/
@SuppressWarnings({"UnusedDeclaration"}) // used in native code
public boolean inMutable;
@@ -381,6 +386,12 @@
public void requestCancelDecode() {
mCancel = true;
}
+
+ static void validate(Options opts) {
+ if (opts != null && opts.inMutable && opts.inPreferredConfig == Bitmap.Config.HARDWARE) {
+ throw new IllegalArgumentException("Bitmaps with Config.HARWARE are always immutable");
+ }
+ }
}
/**
@@ -393,8 +404,12 @@
* @return The decoded bitmap, or null if the image data could not be
* decoded, or, if opts is non-null, if opts requested only the
* size be returned (in opts.outWidth and opts.outHeight)
+ * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
+ * is {@link android.graphics.Bitmap.Config#HARDWARE}
+ * and {@link BitmapFactory.Options#inMutable} is set.
*/
public static Bitmap decodeFile(String pathName, Options opts) {
+ validate(opts);
Bitmap bm = null;
InputStream stream = null;
try {
@@ -431,10 +446,13 @@
/**
* Decode a new Bitmap from an InputStream. This InputStream was obtained from
* resources, which we pass to be able to scale the bitmap accordingly.
+ * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
+ * is {@link android.graphics.Bitmap.Config#HARDWARE}
+ * and {@link BitmapFactory.Options#inMutable} is set.
*/
public static Bitmap decodeResourceStream(Resources res, TypedValue value,
InputStream is, Rect pad, Options opts) {
-
+ validate(opts);
if (opts == null) {
opts = new Options();
}
@@ -466,8 +484,12 @@
* @return The decoded bitmap, or null if the image data could not be
* decoded, or, if opts is non-null, if opts requested only the
* size be returned (in opts.outWidth and opts.outHeight)
+ * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
+ * is {@link android.graphics.Bitmap.Config#HARDWARE}
+ * and {@link BitmapFactory.Options#inMutable} is set.
*/
public static Bitmap decodeResource(Resources res, int id, Options opts) {
+ validate(opts);
Bitmap bm = null;
InputStream is = null;
@@ -520,11 +542,15 @@
* @return The decoded bitmap, or null if the image data could not be
* decoded, or, if opts is non-null, if opts requested only the
* size be returned (in opts.outWidth and opts.outHeight)
+ * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
+ * is {@link android.graphics.Bitmap.Config#HARDWARE}
+ * and {@link BitmapFactory.Options#inMutable} is set.
*/
public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts) {
if ((offset | length) < 0 || data.length < offset + length) {
throw new ArrayIndexOutOfBoundsException();
}
+ validate(opts);
Bitmap bm;
@@ -598,6 +624,9 @@
* @return The decoded bitmap, or null if the image data could not be
* decoded, or, if opts is non-null, if opts requested only the
* size be returned (in opts.outWidth and opts.outHeight)
+ * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
+ * is {@link android.graphics.Bitmap.Config#HARDWARE}
+ * and {@link BitmapFactory.Options#inMutable} is set.
*
* <p class="note">Prior to {@link android.os.Build.VERSION_CODES#KITKAT},
* if {@link InputStream#markSupported is.markSupported()} returns true,
@@ -610,6 +639,7 @@
if (is == null) {
return null;
}
+ validate(opts);
Bitmap bm = null;
@@ -673,8 +703,12 @@
* @param opts null-ok; Options that control downsampling and whether the
* image should be completely decoded, or just its size returned.
* @return the decoded bitmap, or null
+ * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
+ * is {@link android.graphics.Bitmap.Config#HARDWARE}
+ * and {@link BitmapFactory.Options#inMutable} is set.
*/
public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) {
+ validate(opts);
Bitmap bm;
Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeFileDescriptor");
diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java
index e689b08..04abca1 100644
--- a/graphics/java/android/graphics/BitmapRegionDecoder.java
+++ b/graphics/java/android/graphics/BitmapRegionDecoder.java
@@ -178,8 +178,12 @@
* inPurgeable is not supported.
* @return The decoded bitmap, or null if the image data could not be
* decoded.
+ * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
+ * is {@link android.graphics.Bitmap.Config#HARDWARE}
+ * and {@link BitmapFactory.Options#inMutable} is set.
*/
public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) {
+ BitmapFactory.Options.validate(options);
synchronized (mNativeLock) {
checkRecycled("decodeRegion called on recycled region decoder");
if (rect.right <= 0 || rect.bottom <= 0 || rect.left >= getWidth()
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 069f81b..9490436 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -155,7 +155,7 @@
@VisibleForTesting
public static int makeTag(char c1, char c2, char c3, char c4) {
- return (c1 << 24) + (c2 << 16) + (c3 << 8) + c4;
+ return (c1 << 24) | (c2 << 16) | (c3 << 8) | c4;
}
private static boolean isSpacer(char c) {
@@ -228,8 +228,10 @@
return new Font(fullFilename, index, axes, weight, isItalic);
}
- /** The 'tag' attribute value is read as four character values between 0 and 255 inclusive. */
- private static final Pattern TAG_PATTERN = Pattern.compile("[\\x00-\\xFF]{4}");
+ /** The 'tag' attribute value is read as four character values between U+0020 and U+007E
+ * inclusive.
+ */
+ private static final Pattern TAG_PATTERN = Pattern.compile("[\\x20-\\x7E]{4}");
/** The 'styleValue' attribute has an optional leading '-', followed by '<digits>',
* '<digits>.<digits>', or '.<digits>' where '<digits>' is one or more of [0-9].
diff --git a/graphics/java/android/graphics/LayerRasterizer.java b/graphics/java/android/graphics/LayerRasterizer.java
index b692ecf..25155ab 100644
--- a/graphics/java/android/graphics/LayerRasterizer.java
+++ b/graphics/java/android/graphics/LayerRasterizer.java
@@ -16,26 +16,20 @@
package android.graphics;
+/**
+ * @removed feature is not supported by hw-accerlerated or PDF backends
+ */
@Deprecated
public class LayerRasterizer extends Rasterizer {
- public LayerRasterizer() {
- native_instance = nativeConstructor();
- }
+ public LayerRasterizer() { }
/** Add a new layer (above any previous layers) to the rasterizer.
The layer will extract those fields that affect the mask from
the specified paint, but will not retain a reference to the paint
object itself, so it may be reused without danger of side-effects.
*/
- public void addLayer(Paint paint, float dx, float dy) {
- nativeAddLayer(native_instance, paint.getNativeInstance(), dx, dy);
- }
+ public void addLayer(Paint paint, float dx, float dy) { }
- public void addLayer(Paint paint) {
- nativeAddLayer(native_instance, paint.getNativeInstance(), 0, 0);
- }
-
- private static native long nativeConstructor();
- private static native void nativeAddLayer(long native_layer, long native_paint, float dx, float dy);
+ public void addLayer(Paint paint) { }
}
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index aa81b91..3e59f34 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -58,8 +58,12 @@
@Mode
public int mMode = MODE_EMPTY;
- /** @hide */
- public final Path mPath = new Path();
+ /**
+ * Only guaranteed to be non-null when mode == MODE_CONVEX_PATH
+ *
+ * @hide
+ */
+ public Path mPath;
/** @hide */
public final Rect mRect = new Rect();
@@ -87,8 +91,11 @@
* @see #isEmpty()
*/
public void setEmpty() {
+ if (mPath != null) {
+ // rewind here to avoid thrashing the allocations, but could alternately clear ref
+ mPath.rewind();
+ }
mMode = MODE_EMPTY;
- mPath.rewind();
mRect.setEmpty();
mRadius = RADIUS_UNDEFINED;
}
@@ -148,7 +155,12 @@
*/
public void set(@NonNull Outline src) {
mMode = src.mMode;
- mPath.set(src.mPath);
+ if (src.mMode == MODE_CONVEX_PATH) {
+ if (mPath == null) {
+ mPath = new Path();
+ }
+ mPath.set(src.mPath);
+ }
mRect.set(src.mRect);
mRadius = src.mRadius;
mAlpha = src.mAlpha;
@@ -180,10 +192,13 @@
return;
}
+ if (mMode == MODE_CONVEX_PATH) {
+ // rewind here to avoid thrashing the allocations, but could alternately clear ref
+ mPath.rewind();
+ }
mMode = MODE_ROUND_RECT;
mRect.set(left, top, right, bottom);
mRadius = radius;
- mPath.rewind();
}
/**
@@ -236,8 +251,13 @@
return;
}
+ if (mPath == null) {
+ mPath = new Path();
+ } else {
+ mPath.rewind();
+ }
+
mMode = MODE_CONVEX_PATH;
- mPath.rewind();
mPath.addOval(left, top, right, bottom, Path.Direction.CW);
mRect.setEmpty();
mRadius = RADIUS_UNDEFINED;
@@ -264,6 +284,10 @@
throw new IllegalArgumentException("path must be convex");
}
+ if (mPath == null) {
+ mPath = new Path();
+ }
+
mMode = MODE_CONVEX_PATH;
mPath.set(convexPath);
mRect.setEmpty();
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 554e5d2..fc873c4 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -61,7 +61,6 @@
private ColorFilter mColorFilter;
private MaskFilter mMaskFilter;
private PathEffect mPathEffect;
- private Rasterizer mRasterizer;
private Shader mShader;
private Typeface mTypeface;
private Xfermode mXfermode;
@@ -494,7 +493,6 @@
mColorFilter = null;
mMaskFilter = null;
mPathEffect = null;
- mRasterizer = null;
mShader = null;
mNativeShader = 0;
mTypeface = null;
@@ -532,7 +530,6 @@
mColorFilter = paint.mColorFilter;
mMaskFilter = paint.mMaskFilter;
mPathEffect = paint.mPathEffect;
- mRasterizer = paint.mRasterizer;
mShader = paint.mShader;
mNativeShader = paint.mNativeShader;
mTypeface = paint.mTypeface;
@@ -1164,11 +1161,12 @@
*
* @return the paint's rasterizer (or null)
*
- * @deprecated Rasterizer is not supported by either the HW or PDF backends.
+ * @deprecated Rasterizer is not supported by either the HW or PDF backends.
+ * @removed
*/
@Deprecated
public Rasterizer getRasterizer() {
- return mRasterizer;
+ return null;
}
/**
@@ -1181,16 +1179,11 @@
* the paint.
* @return rasterizer
*
- * @deprecated Rasterizer is not supported by either the HW or PDF backends.
+ * @deprecated Rasterizer is not supported by either the HW or PDF backends.
+ * @removed
*/
@Deprecated
public Rasterizer setRasterizer(Rasterizer rasterizer) {
- long rasterizerNative = 0;
- if (rasterizer != null) {
- rasterizerNative = rasterizer.native_instance;
- }
- nSetRasterizer(mNativePaint, rasterizerNative);
- mRasterizer = rasterizer;
return rasterizer;
}
@@ -2715,8 +2708,6 @@
@CriticalNative
private static native long nSetTypeface(long paintPtr, long typeface);
@CriticalNative
- private static native long nSetRasterizer(long paintPtr, long rasterizer);
- @CriticalNative
private static native int nGetTextAlign(long paintPtr);
@CriticalNative
private static native void nSetTextAlign(long paintPtr, int align);
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 4ed2581..3631373 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -19,6 +19,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import dalvik.annotation.optimization.CriticalNative;
+import dalvik.annotation.optimization.FastNative;
+
/**
* The Path class encapsulates compound (multiple contour) geometric paths
* consisting of straight line segments, quadratic curves, and cubic curves.
@@ -46,7 +49,7 @@
* Create an empty path
*/
public Path() {
- mNativePath = init1();
+ mNativePath = nInit();
}
/**
@@ -63,7 +66,7 @@
rects = new Region(src.rects);
}
}
- mNativePath = init2(valNative);
+ mNativePath = nInit(valNative);
}
/**
@@ -77,7 +80,7 @@
// We promised not to change this, so preserve it around the native
// call, which does now reset fill type.
final FillType fillType = getFillType();
- native_reset(mNativePath);
+ nReset(mNativePath);
setFillType(fillType);
}
@@ -89,7 +92,7 @@
isSimplePath = true;
mLastDirection = null;
if (rects != null) rects.setEmpty();
- native_rewind(mNativePath);
+ nRewind(mNativePath);
}
/** Replace the contents of this with the contents of src.
@@ -99,7 +102,7 @@
return;
}
isSimplePath = src.isSimplePath;
- native_set(mNativePath, src.mNativePath);
+ nSet(mNativePath, src.mNativePath);
if (!isSimplePath) {
return;
}
@@ -174,7 +177,7 @@
* @see #op(Path, android.graphics.Path.Op)
*/
public boolean op(Path path1, Path path2, Op op) {
- if (native_op(path1.mNativePath, path2.mNativePath, op.ordinal(), this.mNativePath)) {
+ if (nOp(path1.mNativePath, path2.mNativePath, op.ordinal(), this.mNativePath)) {
isSimplePath = false;
rects = null;
return true;
@@ -194,7 +197,7 @@
* @return True if the path is convex.
*/
public boolean isConvex() {
- return native_isConvex(mNativePath);
+ return nIsConvex(mNativePath);
}
/**
@@ -243,7 +246,7 @@
* @return the path's fill type
*/
public FillType getFillType() {
- return sFillTypeArray[native_getFillType(mNativePath)];
+ return sFillTypeArray[nGetFillType(mNativePath)];
}
/**
@@ -252,7 +255,7 @@
* @param ft The new fill type for this path
*/
public void setFillType(FillType ft) {
- native_setFillType(mNativePath, ft.nativeInt);
+ nSetFillType(mNativePath, ft.nativeInt);
}
/**
@@ -261,7 +264,7 @@
* @return true if the filltype is one of the INVERSE variants
*/
public boolean isInverseFillType() {
- final int ft = native_getFillType(mNativePath);
+ final int ft = nGetFillType(mNativePath);
return (ft & FillType.INVERSE_WINDING.nativeInt) != 0;
}
@@ -269,9 +272,9 @@
* Toggles the INVERSE state of the filltype
*/
public void toggleInverseFillType() {
- int ft = native_getFillType(mNativePath);
+ int ft = nGetFillType(mNativePath);
ft ^= FillType.INVERSE_WINDING.nativeInt;
- native_setFillType(mNativePath, ft);
+ nSetFillType(mNativePath, ft);
}
/**
@@ -280,7 +283,7 @@
* @return true if the path is empty (contains no lines or curves)
*/
public boolean isEmpty() {
- return native_isEmpty(mNativePath);
+ return nIsEmpty(mNativePath);
}
/**
@@ -293,7 +296,7 @@
* @return true if the path specifies a rectangle
*/
public boolean isRect(RectF rect) {
- return native_isRect(mNativePath, rect);
+ return nIsRect(mNativePath, rect);
}
/**
@@ -306,7 +309,7 @@
*/
@SuppressWarnings({"UnusedDeclaration"})
public void computeBounds(RectF bounds, boolean exact) {
- native_computeBounds(mNativePath, bounds);
+ nComputeBounds(mNativePath, bounds);
}
/**
@@ -317,7 +320,7 @@
* path
*/
public void incReserve(int extraPtCount) {
- native_incReserve(mNativePath, extraPtCount);
+ nIncReserve(mNativePath, extraPtCount);
}
/**
@@ -327,7 +330,7 @@
* @param y The y-coordinate of the start of a new contour
*/
public void moveTo(float x, float y) {
- native_moveTo(mNativePath, x, y);
+ nMoveTo(mNativePath, x, y);
}
/**
@@ -341,7 +344,7 @@
* previous contour, to specify the start of a new contour
*/
public void rMoveTo(float dx, float dy) {
- native_rMoveTo(mNativePath, dx, dy);
+ nRMoveTo(mNativePath, dx, dy);
}
/**
@@ -354,7 +357,7 @@
*/
public void lineTo(float x, float y) {
isSimplePath = false;
- native_lineTo(mNativePath, x, y);
+ nLineTo(mNativePath, x, y);
}
/**
@@ -369,7 +372,7 @@
*/
public void rLineTo(float dx, float dy) {
isSimplePath = false;
- native_rLineTo(mNativePath, dx, dy);
+ nRLineTo(mNativePath, dx, dy);
}
/**
@@ -384,7 +387,7 @@
*/
public void quadTo(float x1, float y1, float x2, float y2) {
isSimplePath = false;
- native_quadTo(mNativePath, x1, y1, x2, y2);
+ nQuadTo(mNativePath, x1, y1, x2, y2);
}
/**
@@ -403,7 +406,7 @@
*/
public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
isSimplePath = false;
- native_rQuadTo(mNativePath, dx1, dy1, dx2, dy2);
+ nRQuadTo(mNativePath, dx1, dy1, dx2, dy2);
}
/**
@@ -421,7 +424,7 @@
public void cubicTo(float x1, float y1, float x2, float y2,
float x3, float y3) {
isSimplePath = false;
- native_cubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
+ nCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
}
/**
@@ -432,7 +435,7 @@
public void rCubicTo(float x1, float y1, float x2, float y2,
float x3, float y3) {
isSimplePath = false;
- native_rCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
+ nRCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
}
/**
@@ -483,7 +486,7 @@
public void arcTo(float left, float top, float right, float bottom, float startAngle,
float sweepAngle, boolean forceMoveTo) {
isSimplePath = false;
- native_arcTo(mNativePath, left, top, right, bottom, startAngle, sweepAngle, forceMoveTo);
+ nArcTo(mNativePath, left, top, right, bottom, startAngle, sweepAngle, forceMoveTo);
}
/**
@@ -492,7 +495,7 @@
*/
public void close() {
isSimplePath = false;
- native_close(mNativePath);
+ nClose(mNativePath);
}
/**
@@ -544,7 +547,7 @@
*/
public void addRect(float left, float top, float right, float bottom, Direction dir) {
detectSimplePath(left, top, right, bottom, dir);
- native_addRect(mNativePath, left, top, right, bottom, dir.nativeInt);
+ nAddRect(mNativePath, left, top, right, bottom, dir.nativeInt);
}
/**
@@ -564,7 +567,7 @@
*/
public void addOval(float left, float top, float right, float bottom, Direction dir) {
isSimplePath = false;
- native_addOval(mNativePath, left, top, right, bottom, dir.nativeInt);
+ nAddOval(mNativePath, left, top, right, bottom, dir.nativeInt);
}
/**
@@ -577,7 +580,7 @@
*/
public void addCircle(float x, float y, float radius, Direction dir) {
isSimplePath = false;
- native_addCircle(mNativePath, x, y, radius, dir.nativeInt);
+ nAddCircle(mNativePath, x, y, radius, dir.nativeInt);
}
/**
@@ -600,7 +603,7 @@
public void addArc(float left, float top, float right, float bottom, float startAngle,
float sweepAngle) {
isSimplePath = false;
- native_addArc(mNativePath, left, top, right, bottom, startAngle, sweepAngle);
+ nAddArc(mNativePath, left, top, right, bottom, startAngle, sweepAngle);
}
/**
@@ -625,7 +628,7 @@
public void addRoundRect(float left, float top, float right, float bottom, float rx, float ry,
Direction dir) {
isSimplePath = false;
- native_addRoundRect(mNativePath, left, top, right, bottom, rx, ry, dir.nativeInt);
+ nAddRoundRect(mNativePath, left, top, right, bottom, rx, ry, dir.nativeInt);
}
/**
@@ -658,7 +661,7 @@
throw new ArrayIndexOutOfBoundsException("radii[] needs 8 values");
}
isSimplePath = false;
- native_addRoundRect(mNativePath, left, top, right, bottom, radii, dir.nativeInt);
+ nAddRoundRect(mNativePath, left, top, right, bottom, radii, dir.nativeInt);
}
/**
@@ -669,7 +672,7 @@
*/
public void addPath(Path src, float dx, float dy) {
isSimplePath = false;
- native_addPath(mNativePath, src.mNativePath, dx, dy);
+ nAddPath(mNativePath, src.mNativePath, dx, dy);
}
/**
@@ -679,7 +682,7 @@
*/
public void addPath(Path src) {
isSimplePath = false;
- native_addPath(mNativePath, src.mNativePath);
+ nAddPath(mNativePath, src.mNativePath);
}
/**
@@ -689,7 +692,7 @@
*/
public void addPath(Path src, Matrix matrix) {
if (!src.isSimplePath) isSimplePath = false;
- native_addPath(mNativePath, src.mNativePath, matrix.native_instance);
+ nAddPath(mNativePath, src.mNativePath, matrix.native_instance);
}
/**
@@ -725,7 +728,7 @@
} else {
isSimplePath = false;
}
- native_offset(mNativePath, dx, dy);
+ nOffset(mNativePath, dx, dy);
}
/**
@@ -736,7 +739,7 @@
*/
public void setLastPoint(float dx, float dy) {
isSimplePath = false;
- native_setLastPoint(mNativePath, dx, dy);
+ nSetLastPoint(mNativePath, dx, dy);
}
/**
@@ -753,7 +756,7 @@
dst.isSimplePath = false;
dstNative = dst.mNativePath;
}
- native_transform(mNativePath, matrix.native_instance, dstNative);
+ nTransform(mNativePath, matrix.native_instance, dstNative);
}
/**
@@ -763,12 +766,12 @@
*/
public void transform(Matrix matrix) {
isSimplePath = false;
- native_transform(mNativePath, matrix.native_instance);
+ nTransform(mNativePath, matrix.native_instance);
}
protected void finalize() throws Throwable {
try {
- finalizer(mNativePath);
+ nFinalize(mNativePath);
mNativePath = 0; // Other finalizers can still call us.
} finally {
super.finalize();
@@ -803,59 +806,68 @@
* @return An array of components for points approximating the Path.
*/
public float[] approximate(float acceptableError) {
- return native_approximate(mNativePath, acceptableError);
+ return nApproximate(mNativePath, acceptableError);
}
- private static native long init1();
- private static native long init2(long nPath);
- private static native void native_reset(long nPath);
- private static native void native_rewind(long nPath);
- private static native void native_set(long native_dst, long native_src);
- private static native boolean native_isConvex(long nPath);
- private static native int native_getFillType(long nPath);
- private static native void native_setFillType(long nPath, int ft);
- private static native boolean native_isEmpty(long nPath);
- private static native boolean native_isRect(long nPath, RectF rect);
- private static native void native_computeBounds(long nPath, RectF bounds);
- private static native void native_incReserve(long nPath, int extraPtCount);
- private static native void native_moveTo(long nPath, float x, float y);
- private static native void native_rMoveTo(long nPath, float dx, float dy);
- private static native void native_lineTo(long nPath, float x, float y);
- private static native void native_rLineTo(long nPath, float dx, float dy);
- private static native void native_quadTo(long nPath, float x1, float y1,
- float x2, float y2);
- private static native void native_rQuadTo(long nPath, float dx1, float dy1,
- float dx2, float dy2);
- private static native void native_cubicTo(long nPath, float x1, float y1,
- float x2, float y2, float x3, float y3);
- private static native void native_rCubicTo(long nPath, float x1, float y1,
- float x2, float y2, float x3, float y3);
- private static native void native_arcTo(long nPath, float left, float top,
- float right, float bottom, float startAngle,
- float sweepAngle, boolean forceMoveTo);
- private static native void native_close(long nPath);
- private static native void native_addRect(long nPath, float left, float top,
- float right, float bottom, int dir);
- private static native void native_addOval(long nPath, float left, float top,
+ // ------------------ Regular JNI ------------------------
+
+ private static native long nInit();
+ private static native long nInit(long nPath);
+ private static native void nFinalize(long nPath);
+ private static native void nSet(long native_dst, long nSrc);
+ private static native void nComputeBounds(long nPath, RectF bounds);
+ private static native void nIncReserve(long nPath, int extraPtCount);
+ private static native void nMoveTo(long nPath, float x, float y);
+ private static native void nRMoveTo(long nPath, float dx, float dy);
+ private static native void nLineTo(long nPath, float x, float y);
+ private static native void nRLineTo(long nPath, float dx, float dy);
+ private static native void nQuadTo(long nPath, float x1, float y1, float x2, float y2);
+ private static native void nRQuadTo(long nPath, float dx1, float dy1, float dx2, float dy2);
+ private static native void nCubicTo(long nPath, float x1, float y1, float x2, float y2,
+ float x3, float y3);
+ private static native void nRCubicTo(long nPath, float x1, float y1, float x2, float y2,
+ float x3, float y3);
+ private static native void nArcTo(long nPath, float left, float top, float right, float bottom,
+ float startAngle, float sweepAngle, boolean forceMoveTo);
+ private static native void nClose(long nPath);
+ private static native void nAddRect(long nPath, float left, float top,
float right, float bottom, int dir);
- private static native void native_addCircle(long nPath, float x, float y, float radius, int dir);
- private static native void native_addArc(long nPath, float left, float top,
- float right, float bottom,
- float startAngle, float sweepAngle);
- private static native void native_addRoundRect(long nPath, float left, float top,
- float right, float bottom,
- float rx, float ry, int dir);
- private static native void native_addRoundRect(long nPath, float left, float top,
- float right, float bottom,
- float[] radii, int dir);
- private static native void native_addPath(long nPath, long src, float dx, float dy);
- private static native void native_addPath(long nPath, long src);
- private static native void native_addPath(long nPath, long src, long matrix);
- private static native void native_offset(long nPath, float dx, float dy);
- private static native void native_setLastPoint(long nPath, float dx, float dy);
- private static native void native_transform(long nPath, long matrix, long dst_path);
- private static native void native_transform(long nPath, long matrix);
- private static native boolean native_op(long path1, long path2, int op, long result);
- private static native void finalizer(long nPath);
- private static native float[] native_approximate(long nPath, float error);
+ private static native void nAddOval(long nPath, float left, float top,
+ float right, float bottom, int dir);
+ private static native void nAddCircle(long nPath, float x, float y, float radius, int dir);
+ private static native void nAddArc(long nPath, float left, float top, float right, float bottom,
+ float startAngle, float sweepAngle);
+ private static native void nAddRoundRect(long nPath, float left, float top,
+ float right, float bottom, float rx, float ry, int dir);
+ private static native void nAddRoundRect(long nPath, float left, float top,
+ float right, float bottom, float[] radii, int dir);
+ private static native void nAddPath(long nPath, long src, float dx, float dy);
+ private static native void nAddPath(long nPath, long src);
+ private static native void nAddPath(long nPath, long src, long matrix);
+ private static native void nOffset(long nPath, float dx, float dy);
+ private static native void nSetLastPoint(long nPath, float dx, float dy);
+ private static native void nTransform(long nPath, long matrix, long dst_path);
+ private static native void nTransform(long nPath, long matrix);
+ private static native boolean nOp(long path1, long path2, int op, long result);
+ private static native float[] nApproximate(long nPath, float error);
+
+ // ------------------ Fast JNI ------------------------
+
+ @FastNative
+ private static native boolean nIsRect(long nPath, RectF rect);
+
+ // ------------------ Critical JNI ------------------------
+
+ @CriticalNative
+ private static native void nReset(long nPath);
+ @CriticalNative
+ private static native void nRewind(long nPath);
+ @CriticalNative
+ private static native boolean nIsEmpty(long nPath);
+ @CriticalNative
+ private static native boolean nIsConvex(long nPath);
+ @CriticalNative
+ private static native int nGetFillType(long nPath);
+ @CriticalNative
+ private static native void nSetFillType(long nPath, int ft);
}
diff --git a/graphics/java/android/graphics/Rasterizer.java b/graphics/java/android/graphics/Rasterizer.java
index f6a38fe..29d82fa 100644
--- a/graphics/java/android/graphics/Rasterizer.java
+++ b/graphics/java/android/graphics/Rasterizer.java
@@ -21,15 +21,10 @@
package android.graphics;
-@Deprecated
+/**
+ * @removed feature is not supported by hw-accerlerated or PDF backends
+ */
public class Rasterizer {
- protected void finalize() throws Throwable {
- finalizer(native_instance);
- native_instance = 0;
- }
-
- private static native void finalizer(long native_instance);
-
- long native_instance;
+ protected void finalize() throws Throwable { }
}
diff --git a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
index e4d6aa8..d046c11 100644
--- a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
+++ b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
@@ -105,9 +105,18 @@
}
@SmallTest
+ public void testInvalidTagCharacters() {
+ FontListParser.Axis[] axis =
+ FontListParser.parseFontVariationSettings("'\u0000\u0000\u0000\u0000' 10");
+ assertEquals(0, axis.length);
+ axis = FontListParser.parseFontVariationSettings("'\u3042\u3044\u3046\u3048' 10");
+ assertEquals(0, axis.length);
+ }
+
+ @SmallTest
public void testMakeTag() {
assertEquals(0x77647468, FontListParser.makeTag('w', 'd', 't', 'h'));
assertEquals(0x41582020, FontListParser.makeTag('A', 'X', ' ', ' '));
assertEquals(0x20202020, FontListParser.makeTag(' ', ' ', ' ', ' '));
}
-}
\ No newline at end of file
+}
diff --git a/legacy-test/Android.mk b/legacy-test/Android.mk
index fe5d8ca..5e72a0d 100644
--- a/legacy-test/Android.mk
+++ b/legacy-test/Android.mk
@@ -21,9 +21,21 @@
# This contains the junit.framework classes that were in Android API level 25.
include $(CLEAR_VARS)
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_STATIC_JAVA_LIBRARIES := core-junit-static
-
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_MODULE := legacy-test
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
include $(BUILD_JAVA_LIBRARY)
+
+ifeq ($(HOST_OS),linux)
+# Build the legacy-performance-test-hostdex library
+# =================================================
+# This contains the android.test.PerformanceTestCase class only
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := src/android/test/PerformanceTestCase.java
+LOCAL_MODULE := legacy-performance-test-hostdex
+
+include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
+endif # HOST_OS == linux
diff --git a/core/java/android/test/AndroidTestCase.java b/legacy-test/src/android/test/AndroidTestCase.java
similarity index 100%
rename from core/java/android/test/AndroidTestCase.java
rename to legacy-test/src/android/test/AndroidTestCase.java
diff --git a/core/java/android/test/FlakyTest.java b/legacy-test/src/android/test/FlakyTest.java
similarity index 100%
rename from core/java/android/test/FlakyTest.java
rename to legacy-test/src/android/test/FlakyTest.java
diff --git a/core/java/android/test/InstrumentationTestCase.java b/legacy-test/src/android/test/InstrumentationTestCase.java
similarity index 100%
rename from core/java/android/test/InstrumentationTestCase.java
rename to legacy-test/src/android/test/InstrumentationTestCase.java
diff --git a/core/java/android/test/InstrumentationTestSuite.java b/legacy-test/src/android/test/InstrumentationTestSuite.java
similarity index 100%
rename from core/java/android/test/InstrumentationTestSuite.java
rename to legacy-test/src/android/test/InstrumentationTestSuite.java
diff --git a/core/java/android/test/PerformanceTestCase.java b/legacy-test/src/android/test/PerformanceTestCase.java
similarity index 100%
rename from core/java/android/test/PerformanceTestCase.java
rename to legacy-test/src/android/test/PerformanceTestCase.java
diff --git a/core/java/android/test/RepetitiveTest.java b/legacy-test/src/android/test/RepetitiveTest.java
similarity index 100%
rename from core/java/android/test/RepetitiveTest.java
rename to legacy-test/src/android/test/RepetitiveTest.java
diff --git a/core/java/android/test/UiThreadTest.java b/legacy-test/src/android/test/UiThreadTest.java
similarity index 100%
rename from core/java/android/test/UiThreadTest.java
rename to legacy-test/src/android/test/UiThreadTest.java
diff --git a/core/java/android/test/package.html b/legacy-test/src/android/test/package.html
similarity index 100%
rename from core/java/android/test/package.html
rename to legacy-test/src/android/test/package.html
diff --git a/core/java/android/test/suitebuilder/annotation/LargeTest.java b/legacy-test/src/android/test/suitebuilder/annotation/LargeTest.java
similarity index 100%
rename from core/java/android/test/suitebuilder/annotation/LargeTest.java
rename to legacy-test/src/android/test/suitebuilder/annotation/LargeTest.java
diff --git a/core/java/android/test/suitebuilder/annotation/MediumTest.java b/legacy-test/src/android/test/suitebuilder/annotation/MediumTest.java
similarity index 100%
rename from core/java/android/test/suitebuilder/annotation/MediumTest.java
rename to legacy-test/src/android/test/suitebuilder/annotation/MediumTest.java
diff --git a/core/java/android/test/suitebuilder/annotation/SmallTest.java b/legacy-test/src/android/test/suitebuilder/annotation/SmallTest.java
similarity index 100%
rename from core/java/android/test/suitebuilder/annotation/SmallTest.java
rename to legacy-test/src/android/test/suitebuilder/annotation/SmallTest.java
diff --git a/core/java/android/test/suitebuilder/annotation/Smoke.java b/legacy-test/src/android/test/suitebuilder/annotation/Smoke.java
similarity index 100%
rename from core/java/android/test/suitebuilder/annotation/Smoke.java
rename to legacy-test/src/android/test/suitebuilder/annotation/Smoke.java
diff --git a/core/java/android/test/suitebuilder/annotation/Suppress.java b/legacy-test/src/android/test/suitebuilder/annotation/Suppress.java
similarity index 100%
rename from core/java/android/test/suitebuilder/annotation/Suppress.java
rename to legacy-test/src/android/test/suitebuilder/annotation/Suppress.java
diff --git a/legacy-test/src/junit/MODULE_LICENSE_CPL b/legacy-test/src/junit/MODULE_LICENSE_CPL
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/legacy-test/src/junit/MODULE_LICENSE_CPL
diff --git a/legacy-test/src/junit/README.android b/legacy-test/src/junit/README.android
new file mode 100644
index 0000000..1384a1f
--- /dev/null
+++ b/legacy-test/src/junit/README.android
@@ -0,0 +1,11 @@
+URL: https://github.com/junit-team/junit4
+License: Common Public License Version 1.0
+License File: cpl-v10.html
+
+This is JUnit 4.10 source that was previously part of the Android Public API.
+Where necessary it has been patched to be compatible (according to Android API
+requirements) with JUnit 3.8.
+
+These are copied here to ensure that the android.test.runner target remains
+compatible with the last version of the Android API (25) that contained these
+classes even when external/junit is upgraded to a later version.
diff --git a/legacy-test/src/junit/cpl-v10.html b/legacy-test/src/junit/cpl-v10.html
new file mode 100644
index 0000000..36aa208
--- /dev/null
+++ b/legacy-test/src/junit/cpl-v10.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Common Public License - v 1.0</TITLE>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</HEAD>
+
+<BODY BGCOLOR="#FFFFFF" VLINK="#800000">
+
+
+<P ALIGN="CENTER"><B>Common Public License - v 1.0</B>
+<P><B></B><FONT SIZE="3"></FONT>
+<P><FONT SIZE="3"></FONT><FONT SIZE="2">THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"><B>1. DEFINITIONS</B></FONT>
+<P><FONT SIZE="2">"Contribution" means:</FONT>
+
+<UL><FONT SIZE="2">a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and<BR CLEAR="LEFT">
+b) in the case of each subsequent Contributor:</FONT></UL>
+
+
+<UL><FONT SIZE="2">i) changes to the Program, and</FONT></UL>
+
+
+<UL><FONT SIZE="2">ii) additions to the Program;</FONT></UL>
+
+
+<UL><FONT SIZE="2">where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. </FONT><FONT SIZE="2">A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. </FONT><FONT SIZE="2">Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. </FONT></UL>
+
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">"Contributor" means any person or entity that distributes the Program.</FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. </FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">"Program" means the Contributions distributed in accordance with this Agreement.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.</FONT>
+<P><FONT SIZE="2"><B></B></FONT>
+<P><FONT SIZE="2"><B>2. GRANT OF RIGHTS</B></FONT>
+
+<UL><FONT SIZE="2"></FONT><FONT SIZE="2">a) </FONT><FONT SIZE="2">Subject to the terms of this Agreement, each Contributor hereby grants</FONT><FONT SIZE="2"> Recipient a non-exclusive, worldwide, royalty-free copyright license to</FONT><FONT SIZE="2" COLOR="#FF0000"> </FONT><FONT SIZE="2">reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.</FONT></UL>
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+
+<UL><FONT SIZE="2"></FONT><FONT SIZE="2">b) Subject to the terms of this Agreement, each Contributor hereby grants </FONT><FONT SIZE="2">Recipient a non-exclusive, worldwide,</FONT><FONT SIZE="2" COLOR="#008000"> </FONT><FONT SIZE="2">royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. </FONT></UL>
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+
+<UL><FONT SIZE="2">c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.</FONT></UL>
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+
+<UL><FONT SIZE="2">d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. </FONT></UL>
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+<P><FONT SIZE="2"><B>3. REQUIREMENTS</B></FONT>
+<P><FONT SIZE="2"><B></B>A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:</FONT>
+
+<UL><FONT SIZE="2">a) it complies with the terms and conditions of this Agreement; and</FONT></UL>
+
+
+<UL><FONT SIZE="2">b) its license agreement:</FONT></UL>
+
+
+<UL><FONT SIZE="2">i) effectively disclaims</FONT><FONT SIZE="2"> on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; </FONT></UL>
+
+
+<UL><FONT SIZE="2">ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; </FONT></UL>
+
+
+<UL><FONT SIZE="2">iii)</FONT><FONT SIZE="2"> states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and</FONT></UL>
+
+
+<UL><FONT SIZE="2">iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.</FONT><FONT SIZE="2" COLOR="#0000FF"> </FONT><FONT SIZE="2" COLOR="#FF0000"></FONT></UL>
+
+
+<UL><FONT SIZE="2" COLOR="#FF0000"></FONT><FONT SIZE="2"></FONT></UL>
+
+<P><FONT SIZE="2">When the Program is made available in source code form:</FONT>
+
+<UL><FONT SIZE="2">a) it must be made available under this Agreement; and </FONT></UL>
+
+
+<UL><FONT SIZE="2">b) a copy of this Agreement must be included with each copy of the Program. </FONT></UL>
+
+<P><FONT SIZE="2"></FONT><FONT SIZE="2" COLOR="#0000FF"><STRIKE></STRIKE></FONT>
+<P><FONT SIZE="2" COLOR="#0000FF"><STRIKE></STRIKE></FONT><FONT SIZE="2">Contributors may not remove or alter any copyright notices contained within the Program. </FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. </FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"><B>4. COMMERCIAL DISTRIBUTION</B></FONT>
+<P><FONT SIZE="2">Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.</FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2" COLOR="#0000FF"></FONT>
+<P><FONT SIZE="2" COLOR="#0000FF"></FONT><FONT SIZE="2"><B>5. NO WARRANTY</B></FONT>
+<P><FONT SIZE="2">EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is</FONT><FONT SIZE="2"> solely responsible for determining the appropriateness of using and distributing </FONT><FONT SIZE="2">the Program</FONT><FONT SIZE="2"> and assumes all risks associated with its exercise of rights under this Agreement</FONT><FONT SIZE="2">, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, </FONT><FONT SIZE="2">programs or equipment, and unavailability or interruption of operations</FONT><FONT SIZE="2">. </FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"><B>6. DISCLAIMER OF LIABILITY</B></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES </FONT><FONT SIZE="2">(INCLUDING WITHOUT LIMITATION LOST PROFITS),</FONT><FONT SIZE="2"> HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"><B>7. GENERAL</B></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. </FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. </FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to </FONT><FONT SIZE="2">publish new versions (including revisions) of this Agreement from time to </FONT><FONT SIZE="2">time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. </FONT><FONT SIZE="2">Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new </FONT><FONT SIZE="2">version. </FONT><FONT SIZE="2">Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, </FONT><FONT SIZE="2">by implication, estoppel or otherwise</FONT><FONT SIZE="2">.</FONT><FONT SIZE="2"> All rights in the Program not expressly granted under this Agreement are reserved.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.</FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT>
+
+</BODY>
+
+</HTML>
\ No newline at end of file
diff --git a/legacy-test/src/junit/framework/Assert.java b/legacy-test/src/junit/framework/Assert.java
new file mode 100644
index 0000000..3dcc23d
--- /dev/null
+++ b/legacy-test/src/junit/framework/Assert.java
@@ -0,0 +1,296 @@
+package junit.framework;
+
+/**
+ * A set of assert methods. Messages are only displayed when an assert fails.
+ */
+
+public class Assert {
+ /**
+ * Protect constructor since it is a static only class
+ */
+ protected Assert() {
+ }
+
+ /**
+ * Asserts that a condition is true. If it isn't it throws
+ * an AssertionFailedError with the given message.
+ */
+ static public void assertTrue(String message, boolean condition) {
+ if (!condition)
+ fail(message);
+ }
+ /**
+ * Asserts that a condition is true. If it isn't it throws
+ * an AssertionFailedError.
+ */
+ static public void assertTrue(boolean condition) {
+ assertTrue(null, condition);
+ }
+ /**
+ * Asserts that a condition is false. If it isn't it throws
+ * an AssertionFailedError with the given message.
+ */
+ static public void assertFalse(String message, boolean condition) {
+ assertTrue(message, !condition);
+ }
+ /**
+ * Asserts that a condition is false. If it isn't it throws
+ * an AssertionFailedError.
+ */
+ static public void assertFalse(boolean condition) {
+ assertFalse(null, condition);
+ }
+ /**
+ * Fails a test with the given message.
+ */
+ static public void fail(String message) {
+ if (message == null) {
+ throw new AssertionFailedError();
+ }
+ throw new AssertionFailedError(message);
+ }
+ /**
+ * Fails a test with no message.
+ */
+ static public void fail() {
+ fail(null);
+ }
+ /**
+ * Asserts that two objects are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, Object expected, Object actual) {
+ if (expected == null && actual == null)
+ return;
+ if (expected != null && expected.equals(actual))
+ return;
+ failNotEquals(message, expected, actual);
+ }
+ /**
+ * Asserts that two objects are equal. If they are not
+ * an AssertionFailedError is thrown.
+ */
+ static public void assertEquals(Object expected, Object actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two Strings are equal.
+ */
+ static public void assertEquals(String message, String expected, String actual) {
+ if (expected == null && actual == null)
+ return;
+ if (expected != null && expected.equals(actual))
+ return;
+ String cleanMessage= message == null ? "" : message;
+ throw new ComparisonFailure(cleanMessage, expected, actual);
+ }
+ /**
+ * Asserts that two Strings are equal.
+ */
+ static public void assertEquals(String expected, String actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two doubles are equal concerning a delta. If they are not
+ * an AssertionFailedError is thrown with the given message. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(String message, double expected, double actual, double delta) {
+ if (Double.compare(expected, actual) == 0)
+ return;
+ if (!(Math.abs(expected-actual) <= delta))
+ failNotEquals(message, new Double(expected), new Double(actual));
+ }
+ /**
+ * Asserts that two doubles are equal concerning a delta. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(double expected, double actual, double delta) {
+ assertEquals(null, expected, actual, delta);
+ }
+ /**
+ * Asserts that two floats are equal concerning a positive delta. If they
+ * are not an AssertionFailedError is thrown with the given message. If the
+ * expected value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(String message, float expected, float actual, float delta) {
+ if (Float.compare(expected, actual) == 0)
+ return;
+ if (!(Math.abs(expected - actual) <= delta))
+ failNotEquals(message, new Float(expected), new Float(actual));
+ }
+ /**
+ * Asserts that two floats are equal concerning a delta. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(float expected, float actual, float delta) {
+ assertEquals(null, expected, actual, delta);
+ }
+ /**
+ * Asserts that two longs are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, long expected, long actual) {
+ assertEquals(message, new Long(expected), new Long(actual));
+ }
+ /**
+ * Asserts that two longs are equal.
+ */
+ static public void assertEquals(long expected, long actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two booleans are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, boolean expected, boolean actual) {
+ assertEquals(message, Boolean.valueOf(expected), Boolean.valueOf(actual));
+ }
+ /**
+ * Asserts that two booleans are equal.
+ */
+ static public void assertEquals(boolean expected, boolean actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two bytes are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, byte expected, byte actual) {
+ assertEquals(message, new Byte(expected), new Byte(actual));
+ }
+ /**
+ * Asserts that two bytes are equal.
+ */
+ static public void assertEquals(byte expected, byte actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two chars are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, char expected, char actual) {
+ assertEquals(message, new Character(expected), new Character(actual));
+ }
+ /**
+ * Asserts that two chars are equal.
+ */
+ static public void assertEquals(char expected, char actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two shorts are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, short expected, short actual) {
+ assertEquals(message, new Short(expected), new Short(actual));
+ }
+ /**
+ * Asserts that two shorts are equal.
+ */
+ static public void assertEquals(short expected, short actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two ints are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, int expected, int actual) {
+ assertEquals(message, new Integer(expected), new Integer(actual));
+ }
+ /**
+ * Asserts that two ints are equal.
+ */
+ static public void assertEquals(int expected, int actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that an object isn't null.
+ */
+ static public void assertNotNull(Object object) {
+ assertNotNull(null, object);
+ }
+ /**
+ * Asserts that an object isn't null. If it is
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertNotNull(String message, Object object) {
+ assertTrue(message, object != null);
+ }
+ /**
+ * Asserts that an object is null. If it isn't an {@link AssertionError} is
+ * thrown.
+ * Message contains: Expected: <null> but was: object
+ *
+ * @param object
+ * Object to check or <code>null</code>
+ */
+ static public void assertNull(Object object) {
+ String message = "Expected: <null> but was: " + String.valueOf(object);
+ assertNull(message, object);
+ }
+ /**
+ * Asserts that an object is null. If it is not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertNull(String message, Object object) {
+ assertTrue(message, object == null);
+ }
+ /**
+ * Asserts that two objects refer to the same object. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertSame(String message, Object expected, Object actual) {
+ if (expected == actual)
+ return;
+ failNotSame(message, expected, actual);
+ }
+ /**
+ * Asserts that two objects refer to the same object. If they are not
+ * the same an AssertionFailedError is thrown.
+ */
+ static public void assertSame(Object expected, Object actual) {
+ assertSame(null, expected, actual);
+ }
+ /**
+ * Asserts that two objects do not refer to the same object. If they do
+ * refer to the same object an AssertionFailedError is thrown with the
+ * given message.
+ */
+ static public void assertNotSame(String message, Object expected, Object actual) {
+ if (expected == actual)
+ failSame(message);
+ }
+ /**
+ * Asserts that two objects do not refer to the same object. If they do
+ * refer to the same object an AssertionFailedError is thrown.
+ */
+ static public void assertNotSame(Object expected, Object actual) {
+ assertNotSame(null, expected, actual);
+ }
+
+ static public void failSame(String message) {
+ String formatted= "";
+ if (message != null)
+ formatted= message+" ";
+ fail(formatted+"expected not same");
+ }
+
+ static public void failNotSame(String message, Object expected, Object actual) {
+ String formatted= "";
+ if (message != null)
+ formatted= message+" ";
+ fail(formatted+"expected same:<"+expected+"> was not:<"+actual+">");
+ }
+
+ static public void failNotEquals(String message, Object expected, Object actual) {
+ fail(format(message, expected, actual));
+ }
+
+ public static String format(String message, Object expected, Object actual) {
+ String formatted= "";
+ if (message != null && message.length() > 0)
+ formatted= message+" ";
+ return formatted+"expected:<"+expected+"> but was:<"+actual+">";
+ }
+}
diff --git a/legacy-test/src/junit/framework/AssertionFailedError.java b/legacy-test/src/junit/framework/AssertionFailedError.java
new file mode 100644
index 0000000..0d7802c
--- /dev/null
+++ b/legacy-test/src/junit/framework/AssertionFailedError.java
@@ -0,0 +1,20 @@
+package junit.framework;
+
+/**
+ * Thrown when an assertion failed.
+ */
+public class AssertionFailedError extends AssertionError {
+
+ private static final long serialVersionUID= 1L;
+
+ public AssertionFailedError() {
+ }
+
+ public AssertionFailedError(String message) {
+ super(defaultString(message));
+ }
+
+ private static String defaultString(String message) {
+ return message == null ? "" : message;
+ }
+}
\ No newline at end of file
diff --git a/legacy-test/src/junit/framework/ComparisonCompactor.java b/legacy-test/src/junit/framework/ComparisonCompactor.java
new file mode 100644
index 0000000..e540f03
--- /dev/null
+++ b/legacy-test/src/junit/framework/ComparisonCompactor.java
@@ -0,0 +1,87 @@
+package junit.framework;
+
+// android-changed add @hide
+/**
+ * @hide not needed for public API
+ */
+public class ComparisonCompactor {
+
+ private static final String ELLIPSIS= "...";
+ private static final String DELTA_END= "]";
+ private static final String DELTA_START= "[";
+
+ private int fContextLength;
+ private String fExpected;
+ private String fActual;
+ private int fPrefix;
+ private int fSuffix;
+
+ public ComparisonCompactor(int contextLength, String expected, String actual) {
+ fContextLength= contextLength;
+ fExpected= expected;
+ fActual= actual;
+ }
+
+ public String compact(String message) {
+ if (fExpected == null || fActual == null || areStringsEqual()) {
+ // android-changed use local method instead of Assert.format, since
+ // the later is not part of Android API till API 16
+ return format(message, fExpected, fActual);
+ }
+ findCommonPrefix();
+ findCommonSuffix();
+ String expected= compactString(fExpected);
+ String actual= compactString(fActual);
+ // android-changed use local format method
+ return format(message, expected, actual);
+ }
+
+ private String compactString(String source) {
+ String result= DELTA_START + source.substring(fPrefix, source.length() - fSuffix + 1) + DELTA_END;
+ if (fPrefix > 0)
+ result= computeCommonPrefix() + result;
+ if (fSuffix > 0)
+ result= result + computeCommonSuffix();
+ return result;
+ }
+
+ private void findCommonPrefix() {
+ fPrefix= 0;
+ int end= Math.min(fExpected.length(), fActual.length());
+ for (; fPrefix < end; fPrefix++) {
+ if (fExpected.charAt(fPrefix) != fActual.charAt(fPrefix))
+ break;
+ }
+ }
+
+ private void findCommonSuffix() {
+ int expectedSuffix= fExpected.length() - 1;
+ int actualSuffix= fActual.length() - 1;
+ for (; actualSuffix >= fPrefix && expectedSuffix >= fPrefix; actualSuffix--, expectedSuffix--) {
+ if (fExpected.charAt(expectedSuffix) != fActual.charAt(actualSuffix))
+ break;
+ }
+ fSuffix= fExpected.length() - expectedSuffix;
+ }
+
+ private String computeCommonPrefix() {
+ return (fPrefix > fContextLength ? ELLIPSIS : "") + fExpected.substring(Math.max(0, fPrefix - fContextLength), fPrefix);
+ }
+
+ private String computeCommonSuffix() {
+ int end= Math.min(fExpected.length() - fSuffix + 1 + fContextLength, fExpected.length());
+ return fExpected.substring(fExpected.length() - fSuffix + 1, end) + (fExpected.length() - fSuffix + 1 < fExpected.length() - fContextLength ? ELLIPSIS : "");
+ }
+
+ private boolean areStringsEqual() {
+ return fExpected.equals(fActual);
+ }
+
+ // android-changed copy of Assert.format for reasons described above
+ private static String format(String message, Object expected, Object actual) {
+ String formatted= "";
+ if (message != null && message.length() > 0)
+ formatted= message+" ";
+ return formatted+"expected:<"+expected+"> but was:<"+actual+">";
+ }
+}
diff --git a/legacy-test/src/junit/framework/ComparisonFailure.java b/legacy-test/src/junit/framework/ComparisonFailure.java
new file mode 100644
index 0000000..5077993
--- /dev/null
+++ b/legacy-test/src/junit/framework/ComparisonFailure.java
@@ -0,0 +1,52 @@
+package junit.framework;
+
+/**
+ * Thrown when an assert equals for Strings failed.
+ *
+ * Inspired by a patch from Alex Chaffee mailto:alex@purpletech.com
+ */
+public class ComparisonFailure extends AssertionFailedError {
+ private static final int MAX_CONTEXT_LENGTH= 20;
+ private static final long serialVersionUID= 1L;
+
+ private String fExpected;
+ private String fActual;
+
+ /**
+ * Constructs a comparison failure.
+ * @param message the identifying message or null
+ * @param expected the expected string value
+ * @param actual the actual string value
+ */
+ public ComparisonFailure (String message, String expected, String actual) {
+ super (message);
+ fExpected= expected;
+ fActual= actual;
+ }
+
+ /**
+ * Returns "..." in place of common prefix and "..." in
+ * place of common suffix between expected and actual.
+ *
+ * @see Throwable#getMessage()
+ */
+ @Override
+ public String getMessage() {
+ return new ComparisonCompactor(MAX_CONTEXT_LENGTH, fExpected, fActual).compact(super.getMessage());
+ }
+
+ /**
+ * Gets the actual string value
+ * @return the actual string value
+ */
+ public String getActual() {
+ return fActual;
+ }
+ /**
+ * Gets the expected string value
+ * @return the expected string value
+ */
+ public String getExpected() {
+ return fExpected;
+ }
+}
\ No newline at end of file
diff --git a/legacy-test/src/junit/framework/Protectable.java b/legacy-test/src/junit/framework/Protectable.java
new file mode 100644
index 0000000..e143237
--- /dev/null
+++ b/legacy-test/src/junit/framework/Protectable.java
@@ -0,0 +1,14 @@
+package junit.framework;
+
+/**
+ * A <em>Protectable</em> can be run and can throw a Throwable.
+ *
+ * @see TestResult
+ */
+public interface Protectable {
+
+ /**
+ * Run the the following method protected.
+ */
+ public abstract void protect() throws Throwable;
+}
\ No newline at end of file
diff --git a/legacy-test/src/junit/framework/Test.java b/legacy-test/src/junit/framework/Test.java
new file mode 100644
index 0000000..a016ee8
--- /dev/null
+++ b/legacy-test/src/junit/framework/Test.java
@@ -0,0 +1,17 @@
+package junit.framework;
+
+/**
+ * A <em>Test</em> can be run and collect its results.
+ *
+ * @see TestResult
+ */
+public interface Test {
+ /**
+ * Counts the number of test cases that will be run by this test.
+ */
+ public abstract int countTestCases();
+ /**
+ * Runs a test and collects its result in a TestResult instance.
+ */
+ public abstract void run(TestResult result);
+}
\ No newline at end of file
diff --git a/legacy-test/src/junit/framework/TestCase.java b/legacy-test/src/junit/framework/TestCase.java
new file mode 100644
index 0000000..b047ec9
--- /dev/null
+++ b/legacy-test/src/junit/framework/TestCase.java
@@ -0,0 +1,212 @@
+package junit.framework;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * A test case defines the fixture to run multiple tests. To define a test case<br/>
+ * <ol>
+ * <li>implement a subclass of <code>TestCase</code></li>
+ * <li>define instance variables that store the state of the fixture</li>
+ * <li>initialize the fixture state by overriding {@link #setUp()}</li>
+ * <li>clean-up after a test by overriding {@link #tearDown()}.</li>
+ * </ol>
+ * Each test runs in its own fixture so there
+ * can be no side effects among test runs.
+ * Here is an example:
+ * <pre>
+ * public class MathTest extends TestCase {
+ * protected double fValue1;
+ * protected double fValue2;
+ *
+ * protected void setUp() {
+ * fValue1= 2.0;
+ * fValue2= 3.0;
+ * }
+ * }
+ * </pre>
+ *
+ * For each test implement a method which interacts
+ * with the fixture. Verify the expected results with assertions specified
+ * by calling {@link junit.framework.Assert#assertTrue(String, boolean)} with a boolean.
+ * <pre>
+ * public void testAdd() {
+ * double result= fValue1 + fValue2;
+ * assertTrue(result == 5.0);
+ * }
+ * </pre>
+ *
+ * Once the methods are defined you can run them. The framework supports
+ * both a static type safe and more dynamic way to run a test.
+ * In the static way you override the runTest method and define the method to
+ * be invoked. A convenient way to do so is with an anonymous inner class.
+ * <pre>
+ * TestCase test= new MathTest("add") {
+ * public void runTest() {
+ * testAdd();
+ * }
+ * };
+ * test.run();
+ * </pre>
+ *
+ * The dynamic way uses reflection to implement {@link #runTest()}. It dynamically finds
+ * and invokes a method.
+ * In this case the name of the test case has to correspond to the test method
+ * to be run.
+ * <pre>
+ * TestCase test= new MathTest("testAdd");
+ * test.run();
+ * </pre>
+ *
+ * The tests to be run can be collected into a TestSuite. JUnit provides
+ * different <i>test runners</i> which can run a test suite and collect the results.
+ * A test runner either expects a static method <code>suite</code> as the entry
+ * point to get a test to run or it will extract the suite automatically.
+ * <pre>
+ * public static Test suite() {
+ * suite.addTest(new MathTest("testAdd"));
+ * suite.addTest(new MathTest("testDivideByZero"));
+ * return suite;
+ * }
+ * </pre>
+ * @see TestResult
+ * @see TestSuite
+ */
+public abstract class TestCase extends Assert implements Test {
+ /**
+ * the name of the test case
+ */
+ private String fName;
+
+ /**
+ * No-arg constructor to enable serialization. This method
+ * is not intended to be used by mere mortals without calling setName().
+ */
+ public TestCase() {
+ fName= null;
+ }
+ /**
+ * Constructs a test case with the given name.
+ */
+ public TestCase(String name) {
+ fName= name;
+ }
+ /**
+ * Counts the number of test cases executed by run(TestResult result).
+ */
+ public int countTestCases() {
+ return 1;
+ }
+ /**
+ * Creates a default TestResult object
+ *
+ * @see TestResult
+ */
+ protected TestResult createResult() {
+ return new TestResult();
+ }
+ /**
+ * A convenience method to run this test, collecting the results with a
+ * default TestResult object.
+ *
+ * @see TestResult
+ */
+ public TestResult run() {
+ TestResult result= createResult();
+ run(result);
+ return result;
+ }
+ /**
+ * Runs the test case and collects the results in TestResult.
+ */
+ public void run(TestResult result) {
+ result.run(this);
+ }
+ /**
+ * Runs the bare test sequence.
+ * @throws Throwable if any exception is thrown
+ */
+ public void runBare() throws Throwable {
+ Throwable exception= null;
+ setUp();
+ try {
+ runTest();
+ } catch (Throwable running) {
+ exception= running;
+ }
+ finally {
+ try {
+ tearDown();
+ } catch (Throwable tearingDown) {
+ if (exception == null) exception= tearingDown;
+ }
+ }
+ if (exception != null) throw exception;
+ }
+ /**
+ * Override to run the test and assert its state.
+ * @throws Throwable if any exception is thrown
+ */
+ protected void runTest() throws Throwable {
+ assertNotNull("TestCase.fName cannot be null", fName); // Some VMs crash when calling getMethod(null,null);
+ Method runMethod= null;
+ try {
+ // use getMethod to get all public inherited
+ // methods. getDeclaredMethods returns all
+ // methods of this class but excludes the
+ // inherited ones.
+ runMethod= getClass().getMethod(fName, (Class[])null);
+ } catch (NoSuchMethodException e) {
+ fail("Method \""+fName+"\" not found");
+ }
+ if (!Modifier.isPublic(runMethod.getModifiers())) {
+ fail("Method \""+fName+"\" should be public");
+ }
+
+ try {
+ runMethod.invoke(this);
+ }
+ catch (InvocationTargetException e) {
+ e.fillInStackTrace();
+ throw e.getTargetException();
+ }
+ catch (IllegalAccessException e) {
+ e.fillInStackTrace();
+ throw e;
+ }
+ }
+ /**
+ * Sets up the fixture, for example, open a network connection.
+ * This method is called before a test is executed.
+ */
+ protected void setUp() throws Exception {
+ }
+ /**
+ * Tears down the fixture, for example, close a network connection.
+ * This method is called after a test is executed.
+ */
+ protected void tearDown() throws Exception {
+ }
+ /**
+ * Returns a string representation of the test case
+ */
+ @Override
+ public String toString() {
+ return getName() + "(" + getClass().getName() + ")";
+ }
+ /**
+ * Gets the name of a TestCase
+ * @return the name of the TestCase
+ */
+ public String getName() {
+ return fName;
+ }
+ /**
+ * Sets the name of a TestCase
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ fName= name;
+ }
+}
diff --git a/legacy-test/src/junit/framework/TestFailure.java b/legacy-test/src/junit/framework/TestFailure.java
new file mode 100644
index 0000000..6662b1f
--- /dev/null
+++ b/legacy-test/src/junit/framework/TestFailure.java
@@ -0,0 +1,58 @@
+package junit.framework;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+
+/**
+ * A <code>TestFailure</code> collects a failed test together with
+ * the caught exception.
+ * @see TestResult
+ */
+public class TestFailure extends Object {
+ protected Test fFailedTest;
+ protected Throwable fThrownException;
+
+
+ /**
+ * Constructs a TestFailure with the given test and exception.
+ */
+ public TestFailure(Test failedTest, Throwable thrownException) {
+ fFailedTest= failedTest;
+ fThrownException= thrownException;
+ }
+ /**
+ * Gets the failed test.
+ */
+ public Test failedTest() {
+ return fFailedTest;
+ }
+ /**
+ * Gets the thrown exception.
+ */
+ public Throwable thrownException() {
+ return fThrownException;
+ }
+ /**
+ * Returns a short description of the failure.
+ */
+ @Override
+ public String toString() {
+ StringBuffer buffer= new StringBuffer();
+ buffer.append(fFailedTest+": "+fThrownException.getMessage());
+ return buffer.toString();
+ }
+ public String trace() {
+ StringWriter stringWriter= new StringWriter();
+ PrintWriter writer= new PrintWriter(stringWriter);
+ thrownException().printStackTrace(writer);
+ StringBuffer buffer= stringWriter.getBuffer();
+ return buffer.toString();
+ }
+ public String exceptionMessage() {
+ return thrownException().getMessage();
+ }
+ public boolean isFailure() {
+ return thrownException() instanceof AssertionFailedError;
+ }
+}
\ No newline at end of file
diff --git a/legacy-test/src/junit/framework/TestListener.java b/legacy-test/src/junit/framework/TestListener.java
new file mode 100644
index 0000000..9b69443
--- /dev/null
+++ b/legacy-test/src/junit/framework/TestListener.java
@@ -0,0 +1,23 @@
+package junit.framework;
+
+/**
+ * A Listener for test progress
+ */
+public interface TestListener {
+ /**
+ * An error occurred.
+ */
+ public void addError(Test test, Throwable t);
+ /**
+ * A failure occurred.
+ */
+ public void addFailure(Test test, AssertionFailedError t);
+ /**
+ * A test ended.
+ */
+ public void endTest(Test test);
+ /**
+ * A test started.
+ */
+ public void startTest(Test test);
+}
\ No newline at end of file
diff --git a/legacy-test/src/junit/framework/TestResult.java b/legacy-test/src/junit/framework/TestResult.java
new file mode 100644
index 0000000..3052e94
--- /dev/null
+++ b/legacy-test/src/junit/framework/TestResult.java
@@ -0,0 +1,174 @@
+package junit.framework;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * A <code>TestResult</code> collects the results of executing
+ * a test case. It is an instance of the Collecting Parameter pattern.
+ * The test framework distinguishes between <i>failures</i> and <i>errors</i>.
+ * A failure is anticipated and checked for with assertions. Errors are
+ * unanticipated problems like an {@link ArrayIndexOutOfBoundsException}.
+ *
+ * @see Test
+ */
+public class TestResult extends Object {
+ // BEGIN android-changed changed types from List<> to Vector<> for API compatibility
+ protected Vector<TestFailure> fFailures;
+ protected Vector<TestFailure> fErrors;
+ protected Vector<TestListener> fListeners;
+ // END android-changed
+ protected int fRunTests;
+ private boolean fStop;
+
+ public TestResult() {
+ // BEGIN android-changed to Vector
+ fFailures= new Vector<TestFailure>();
+ fErrors= new Vector<TestFailure>();
+ fListeners= new Vector<TestListener>();
+ // END android-changed
+ fRunTests= 0;
+ fStop= false;
+ }
+ /**
+ * Adds an error to the list of errors. The passed in exception
+ * caused the error.
+ */
+ public synchronized void addError(Test test, Throwable t) {
+ fErrors.add(new TestFailure(test, t));
+ for (TestListener each : cloneListeners())
+ each.addError(test, t);
+ }
+ /**
+ * Adds a failure to the list of failures. The passed in exception
+ * caused the failure.
+ */
+ public synchronized void addFailure(Test test, AssertionFailedError t) {
+ fFailures.add(new TestFailure(test, t));
+ for (TestListener each : cloneListeners())
+ each.addFailure(test, t);
+ }
+ /**
+ * Registers a TestListener
+ */
+ public synchronized void addListener(TestListener listener) {
+ fListeners.add(listener);
+ }
+ /**
+ * Unregisters a TestListener
+ */
+ public synchronized void removeListener(TestListener listener) {
+ fListeners.remove(listener);
+ }
+ /**
+ * Returns a copy of the listeners.
+ */
+ private synchronized List<TestListener> cloneListeners() {
+ List<TestListener> result= new ArrayList<TestListener>();
+ result.addAll(fListeners);
+ return result;
+ }
+ /**
+ * Informs the result that a test was completed.
+ */
+ public void endTest(Test test) {
+ for (TestListener each : cloneListeners())
+ each.endTest(test);
+ }
+ /**
+ * Gets the number of detected errors.
+ */
+ public synchronized int errorCount() {
+ return fErrors.size();
+ }
+ /**
+ * Returns an Enumeration for the errors
+ */
+ public synchronized Enumeration<TestFailure> errors() {
+ return Collections.enumeration(fErrors);
+ }
+
+
+ /**
+ * Gets the number of detected failures.
+ */
+ public synchronized int failureCount() {
+ return fFailures.size();
+ }
+ /**
+ * Returns an Enumeration for the failures
+ */
+ public synchronized Enumeration<TestFailure> failures() {
+ return Collections.enumeration(fFailures);
+ }
+
+ /**
+ * Runs a TestCase.
+ */
+ protected void run(final TestCase test) {
+ startTest(test);
+ Protectable p= new Protectable() {
+ public void protect() throws Throwable {
+ test.runBare();
+ }
+ };
+ runProtected(test, p);
+
+ endTest(test);
+ }
+ /**
+ * Gets the number of run tests.
+ */
+ public synchronized int runCount() {
+ return fRunTests;
+ }
+ /**
+ * Runs a TestCase.
+ */
+ public void runProtected(final Test test, Protectable p) {
+ try {
+ p.protect();
+ }
+ catch (AssertionFailedError e) {
+ addFailure(test, e);
+ }
+ catch (ThreadDeath e) { // don't catch ThreadDeath by accident
+ throw e;
+ }
+ catch (Throwable e) {
+ addError(test, e);
+ }
+ }
+ /**
+ * Checks whether the test run should stop
+ */
+ public synchronized boolean shouldStop() {
+ return fStop;
+ }
+ /**
+ * Informs the result that a test will be started.
+ */
+ public void startTest(Test test) {
+ final int count= test.countTestCases();
+ synchronized(this) {
+ fRunTests+= count;
+ }
+ for (TestListener each : cloneListeners())
+ each.startTest(test);
+ }
+ /**
+ * Marks that the test run should stop.
+ */
+ public synchronized void stop() {
+ fStop= true;
+ }
+ /**
+ * Returns whether the entire test was successful or not.
+ */
+ public synchronized boolean wasSuccessful() {
+ return failureCount() == 0 && errorCount() == 0;
+ }
+}
diff --git a/legacy-test/src/junit/framework/TestSuite.java b/legacy-test/src/junit/framework/TestSuite.java
new file mode 100644
index 0000000..336efd1
--- /dev/null
+++ b/legacy-test/src/junit/framework/TestSuite.java
@@ -0,0 +1,307 @@
+package junit.framework;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * <p>A <code>TestSuite</code> is a <code>Composite</code> of Tests.
+ * It runs a collection of test cases. Here is an example using
+ * the dynamic test definition.
+ * <pre>
+ * TestSuite suite= new TestSuite();
+ * suite.addTest(new MathTest("testAdd"));
+ * suite.addTest(new MathTest("testDivideByZero"));
+ * </pre>
+ * </p>
+ *
+ * <p>Alternatively, a TestSuite can extract the tests to be run automatically.
+ * To do so you pass the class of your TestCase class to the
+ * TestSuite constructor.
+ * <pre>
+ * TestSuite suite= new TestSuite(MathTest.class);
+ * </pre>
+ * </p>
+ *
+ * <p>This constructor creates a suite with all the methods
+ * starting with "test" that take no arguments.</p>
+ *
+ * <p>A final option is to do the same for a large array of test classes.
+ * <pre>
+ * Class[] testClasses = { MathTest.class, AnotherTest.class }
+ * TestSuite suite= new TestSuite(testClasses);
+ * </pre>
+ * </p>
+ *
+ * @see Test
+ */
+public class TestSuite implements Test {
+
+ /**
+ * ...as the moon sets over the early morning Merlin, Oregon
+ * mountains, our intrepid adventurers type...
+ */
+ static public Test createTest(Class<?> theClass, String name) {
+ Constructor<?> constructor;
+ try {
+ constructor= getTestConstructor(theClass);
+ } catch (NoSuchMethodException e) {
+ return warning("Class "+theClass.getName()+" has no public constructor TestCase(String name) or TestCase()");
+ }
+ Object test;
+ try {
+ if (constructor.getParameterTypes().length == 0) {
+ test= constructor.newInstance(new Object[0]);
+ if (test instanceof TestCase)
+ ((TestCase) test).setName(name);
+ } else {
+ test= constructor.newInstance(new Object[]{name});
+ }
+ } catch (InstantiationException e) {
+ return(warning("Cannot instantiate test case: "+name+" ("+exceptionToString(e)+")"));
+ } catch (InvocationTargetException e) {
+ return(warning("Exception in constructor: "+name+" ("+exceptionToString(e.getTargetException())+")"));
+ } catch (IllegalAccessException e) {
+ return(warning("Cannot access test case: "+name+" ("+exceptionToString(e)+")"));
+ }
+ return (Test) test;
+ }
+
+ /**
+ * Gets a constructor which takes a single String as
+ * its argument or a no arg constructor.
+ */
+ public static Constructor<?> getTestConstructor(Class<?> theClass) throws NoSuchMethodException {
+ try {
+ return theClass.getConstructor(String.class);
+ } catch (NoSuchMethodException e) {
+ // fall through
+ }
+ return theClass.getConstructor(new Class[0]);
+ }
+
+ /**
+ * Returns a test which will fail and log a warning message.
+ */
+ public static Test warning(final String message) {
+ return new TestCase("warning") {
+ @Override
+ protected void runTest() {
+ fail(message);
+ }
+ };
+ }
+
+ /**
+ * Converts the stack trace into a string
+ */
+ private static String exceptionToString(Throwable t) {
+ StringWriter stringWriter= new StringWriter();
+ PrintWriter writer= new PrintWriter(stringWriter);
+ t.printStackTrace(writer);
+ return stringWriter.toString();
+ }
+
+ private String fName;
+
+ private Vector<Test> fTests= new Vector<Test>(10); // Cannot convert this to List because it is used directly by some test runners
+
+ /**
+ * Constructs an empty TestSuite.
+ */
+ public TestSuite() {
+ }
+
+ /**
+ * Constructs a TestSuite from the given class. Adds all the methods
+ * starting with "test" as test cases to the suite.
+ * Parts of this method were written at 2337 meters in the Hueffihuette,
+ * Kanton Uri
+ */
+ public TestSuite(final Class<?> theClass) {
+ addTestsFromTestCase(theClass);
+ }
+
+ private void addTestsFromTestCase(final Class<?> theClass) {
+ fName= theClass.getName();
+ try {
+ getTestConstructor(theClass); // Avoid generating multiple error messages
+ } catch (NoSuchMethodException e) {
+ addTest(warning("Class "+theClass.getName()+" has no public constructor TestCase(String name) or TestCase()"));
+ return;
+ }
+
+ if (!Modifier.isPublic(theClass.getModifiers())) {
+ addTest(warning("Class "+theClass.getName()+" is not public"));
+ return;
+ }
+
+ Class<?> superClass= theClass;
+ List<String> names= new ArrayList<String>();
+ while (Test.class.isAssignableFrom(superClass)) {
+ for (Method each : superClass.getDeclaredMethods())
+ addTestMethod(each, names, theClass);
+ superClass= superClass.getSuperclass();
+ }
+ if (fTests.size() == 0)
+ addTest(warning("No tests found in "+theClass.getName()));
+ }
+
+ /**
+ * Constructs a TestSuite from the given class with the given name.
+ * @see TestSuite#TestSuite(Class)
+ */
+ public TestSuite(Class<? extends TestCase> theClass, String name) {
+ this(theClass);
+ setName(name);
+ }
+
+ /**
+ * Constructs an empty TestSuite.
+ */
+ public TestSuite(String name) {
+ setName(name);
+ }
+
+ /**
+ * Constructs a TestSuite from the given array of classes.
+ * @param classes {@link TestCase}s
+ */
+ public TestSuite (Class<?>... classes) {
+ for (Class<?> each : classes)
+ addTest(testCaseForClass(each));
+ }
+
+ private Test testCaseForClass(Class<?> each) {
+ if (TestCase.class.isAssignableFrom(each))
+ return new TestSuite(each.asSubclass(TestCase.class));
+ else
+ return warning(each.getCanonicalName() + " does not extend TestCase");
+ }
+
+ /**
+ * Constructs a TestSuite from the given array of classes with the given name.
+ * @see TestSuite#TestSuite(Class[])
+ */
+ public TestSuite(Class<? extends TestCase>[] classes, String name) {
+ this(classes);
+ setName(name);
+ }
+
+ /**
+ * Adds a test to the suite.
+ */
+ public void addTest(Test test) {
+ fTests.add(test);
+ }
+
+ /**
+ * Adds the tests from the given class to the suite
+ */
+ public void addTestSuite(Class<? extends TestCase> testClass) {
+ addTest(new TestSuite(testClass));
+ }
+
+ /**
+ * Counts the number of test cases that will be run by this test.
+ */
+ public int countTestCases() {
+ int count= 0;
+ for (Test each : fTests)
+ count+= each.countTestCases();
+ return count;
+ }
+
+ /**
+ * Returns the name of the suite. Not all
+ * test suites have a name and this method
+ * can return null.
+ */
+ public String getName() {
+ return fName;
+ }
+
+ /**
+ * Runs the tests and collects their result in a TestResult.
+ */
+ public void run(TestResult result) {
+ for (Test each : fTests) {
+ if (result.shouldStop() )
+ break;
+ runTest(each, result);
+ }
+ }
+
+ public void runTest(Test test, TestResult result) {
+ test.run(result);
+ }
+
+ /**
+ * Sets the name of the suite.
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ fName= name;
+ }
+
+ /**
+ * Returns the test at the given index
+ */
+ public Test testAt(int index) {
+ return fTests.get(index);
+ }
+
+ /**
+ * Returns the number of tests in this suite
+ */
+ public int testCount() {
+ return fTests.size();
+ }
+
+ /**
+ * Returns the tests as an enumeration
+ */
+ public Enumeration<Test> tests() {
+ return fTests.elements();
+ }
+
+ /**
+ */
+ @Override
+ public String toString() {
+ if (getName() != null)
+ return getName();
+ return super.toString();
+ }
+
+ private void addTestMethod(Method m, List<String> names, Class<?> theClass) {
+ String name= m.getName();
+ if (names.contains(name))
+ return;
+ if (! isPublicTestMethod(m)) {
+ if (isTestMethod(m))
+ addTest(warning("Test method isn't public: "+ m.getName() + "(" + theClass.getCanonicalName() + ")"));
+ return;
+ }
+ names.add(name);
+ addTest(createTest(theClass, name));
+ }
+
+ private boolean isPublicTestMethod(Method m) {
+ return isTestMethod(m) && Modifier.isPublic(m.getModifiers());
+ }
+
+ private boolean isTestMethod(Method m) {
+ return
+ m.getParameterTypes().length == 0 &&
+ m.getName().startsWith("test") &&
+ m.getReturnType().equals(Void.TYPE);
+ }
+}
\ No newline at end of file
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
new file mode 100644
index 0000000..d501d25
--- /dev/null
+++ b/libs/androidfw/Android.bp
@@ -0,0 +1,74 @@
+// Copyright (C) 2010 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.
+
+// libandroidfw is partially built for the host (used by obbtool, aapt, and others)
+
+cc_library {
+ name: "libandroidfw",
+ host_supported: true,
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wunused",
+ "-Wunreachable-code",
+ ],
+ srcs: [
+ "Asset.cpp",
+ "AssetDir.cpp",
+ "AssetManager.cpp",
+ "AttributeResolution.cpp",
+ "LocaleData.cpp",
+ "misc.cpp",
+ "ObbFile.cpp",
+ "ResourceTypes.cpp",
+ "StreamingZipInflater.cpp",
+ "TypeWrappers.cpp",
+ "ZipFileRO.cpp",
+ "ZipUtils.cpp",
+ ],
+ export_include_dirs: ["include"],
+ target: {
+ android: {
+ srcs: [
+ "BackupData.cpp",
+ "BackupHelpers.cpp",
+ "CursorWindow.cpp",
+ "DisplayEventDispatcher.cpp",
+ ],
+ shared_libs: [
+ "libziparchive",
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libcutils",
+ "libgui",
+ "libutils",
+ "libz",
+ ],
+ static: {
+ enabled: false,
+ },
+ },
+ host: {
+ cflags: ["-DSTATIC_ANDROIDFW_FOR_TOOLS"],
+ shared: {
+ enabled: false,
+ },
+ shared_libs: ["libz-host"],
+ },
+ windows: {
+ enabled: true,
+ },
+ },
+}
diff --git a/libs/androidfw/Android.mk b/libs/androidfw/Android.mk
index 7689256..68c51ef 100644
--- a/libs/androidfw/Android.mk
+++ b/libs/androidfw/Android.mk
@@ -14,74 +14,6 @@
LOCAL_PATH:= $(call my-dir)
-# libandroidfw is partially built for the host (used by obbtool, aapt, and others)
-# These files are common to host and target builds.
-
-commonSources := \
- Asset.cpp \
- AssetDir.cpp \
- AssetManager.cpp \
- AttributeResolution.cpp \
- LocaleData.cpp \
- misc.cpp \
- ObbFile.cpp \
- ResourceTypes.cpp \
- StreamingZipInflater.cpp \
- TypeWrappers.cpp \
- ZipFileRO.cpp \
- ZipUtils.cpp
-
-deviceSources := \
- $(commonSources) \
- BackupData.cpp \
- BackupHelpers.cpp \
- CursorWindow.cpp \
- DisplayEventDispatcher.cpp
-
-hostSources := $(commonSources)
-
-# For the host
-# =====================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= libandroidfw
-LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_CFLAGS += -DSTATIC_ANDROIDFW_FOR_TOOLS
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-LOCAL_SRC_FILES:= $(hostSources)
-LOCAL_C_INCLUDES := external/zlib
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-
-# For the device
-# =====================================================
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= libandroidfw
-LOCAL_SRC_FILES:= $(deviceSources)
-LOCAL_C_INCLUDES := \
- system/core/include
-LOCAL_SHARED_LIBRARIES := \
- libziparchive \
- libbase \
- libbinder \
- liblog \
- libcutils \
- libgui \
- libutils \
- libz
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-
-include $(BUILD_SHARED_LIBRARY)
-
-
# Include subdirectory makefiles
# ============================================================
diff --git a/libs/androidfw/AttributeResolution.cpp b/libs/androidfw/AttributeResolution.cpp
index 00f7a42..f5aef05 100644
--- a/libs/androidfw/AttributeResolution.cpp
+++ b/libs/androidfw/AttributeResolution.cpp
@@ -14,34 +14,41 @@
* limitations under the License.
*/
-#include "AttributeFinder.h"
-
#include "androidfw/AttributeResolution.h"
-#include "androidfw/ResourceTypes.h"
+
+#include <cstdint>
#include <android/log.h>
-#include <cstdint>
+
+#include "androidfw/AttributeFinder.h"
+#include "androidfw/ResourceTypes.h"
constexpr bool kDebugStyles = false;
namespace android {
-class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, size_t> {
+class XmlAttributeFinder
+ : public BackTrackingAttributeFinder<XmlAttributeFinder, size_t> {
public:
explicit XmlAttributeFinder(const ResXMLParser* parser)
- : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0),
+ : BackTrackingAttributeFinder(
+ 0, parser != nullptr ? parser->getAttributeCount() : 0),
parser_(parser) {}
- inline uint32_t GetAttribute(size_t index) const { return parser_->getAttributeNameResID(index); }
+ inline uint32_t GetAttribute(size_t index) const {
+ return parser_->getAttributeNameResID(index);
+ }
private:
const ResXMLParser* parser_;
};
class BagAttributeFinder
- : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
+ : public BackTrackingAttributeFinder<BagAttributeFinder,
+ const ResTable::bag_entry*> {
public:
- BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
+ BagAttributeFinder(const ResTable::bag_entry* start,
+ const ResTable::bag_entry* end)
: BackTrackingAttributeFinder(start, end) {}
inline uint32_t GetAttribute(const ResTable::bag_entry* entry) const {
@@ -49,12 +56,14 @@
}
};
-bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr, uint32_t def_style_res,
- uint32_t* src_values, size_t src_values_length, uint32_t* attrs,
- size_t attrs_length, uint32_t* out_values, uint32_t* out_indices) {
+bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr,
+ uint32_t def_style_res, uint32_t* src_values,
+ size_t src_values_length, uint32_t* attrs,
+ size_t attrs_length, uint32_t* out_values,
+ uint32_t* out_indices) {
if (kDebugStyles) {
- ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x", theme, def_style_attr,
- def_style_res);
+ ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x", theme,
+ def_style_attr, def_style_res);
}
const ResTable& res = theme->getResTable();
@@ -67,7 +76,8 @@
uint32_t def_style_bag_type_set_flags = 0;
if (def_style_attr != 0) {
Res_value value;
- if (theme->getAttribute(def_style_attr, &value, &def_style_bag_type_set_flags) >= 0) {
+ if (theme->getAttribute(def_style_attr, &value,
+ &def_style_bag_type_set_flags) >= 0) {
if (value.dataType == Res_value::TYPE_REFERENCE) {
def_style_res = value.data;
}
@@ -78,14 +88,15 @@
res.lock();
// Retrieve the default style bag, if requested.
- const ResTable::bag_entry* def_style_start = NULL;
+ const ResTable::bag_entry* def_style_start = nullptr;
uint32_t def_style_type_set_flags = 0;
- ssize_t bag_off =
- def_style_res != 0
- ? res.getBagLocked(def_style_res, &def_style_start, &def_style_type_set_flags)
- : -1;
+ ssize_t bag_off = def_style_res != 0
+ ? res.getBagLocked(def_style_res, &def_style_start,
+ &def_style_type_set_flags)
+ : -1;
def_style_type_set_flags |= def_style_bag_type_set_flags;
- const ResTable::bag_entry* const def_style_end = def_style_start + (bag_off >= 0 ? bag_off : 0);
+ const ResTable::bag_entry* const def_style_end =
+ def_style_start + (bag_off >= 0 ? bag_off : 0);
BagAttributeFinder def_style_attr_finder(def_style_start, def_style_end);
// Now iterate through all of the attributes that the client has requested,
@@ -113,18 +124,21 @@
value.dataType = Res_value::TYPE_ATTRIBUTE;
value.data = src_values[ii];
if (kDebugStyles) {
- ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
}
if (value.dataType == Res_value::TYPE_NULL) {
- const ResTable::bag_entry* const def_style_entry = def_style_attr_finder.Find(cur_ident);
+ const ResTable::bag_entry* const def_style_entry =
+ def_style_attr_finder.Find(cur_ident);
if (def_style_entry != def_style_end) {
block = def_style_entry->stringBlock;
type_set_flags = def_style_type_set_flags;
value = def_style_entry->map.value;
if (kDebugStyles) {
- ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
}
}
@@ -132,24 +146,29 @@
uint32_t resid = 0;
if (value.dataType != Res_value::TYPE_NULL) {
// Take care of resolving the found resource to its final value.
- ssize_t new_block =
- theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
+ ssize_t new_block = theme->resolveAttributeReference(
+ &value, block, &resid, &type_set_flags, &config);
if (new_block >= 0) block = new_block;
if (kDebugStyles) {
- ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
} else {
// If we still don't have a value for this attribute, try to find
// it in the theme!
- ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
+ ssize_t new_block =
+ theme->getAttribute(cur_ident, &value, &type_set_flags);
if (new_block >= 0) {
if (kDebugStyles) {
- ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
- new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
+ new_block = res.resolveReference(&value, new_block, &resid,
+ &type_set_flags, &config);
if (new_block >= 0) block = new_block;
if (kDebugStyles) {
- ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
}
}
@@ -165,19 +184,21 @@
}
if (kDebugStyles) {
- ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.dataType, value.data);
+ ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident,
+ value.dataType, value.data);
}
// Write the final value back to Java.
out_values[STYLE_TYPE] = value.dataType;
out_values[STYLE_DATA] = value.data;
out_values[STYLE_ASSET_COOKIE] =
- block != -1 ? static_cast<uint32_t>(res.getTableCookie(block)) : static_cast<uint32_t>(-1);
+ block != -1 ? static_cast<uint32_t>(res.getTableCookie(block))
+ : static_cast<uint32_t>(-1);
out_values[STYLE_RESOURCE_ID] = resid;
out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
out_values[STYLE_DENSITY] = config.density;
- if (out_indices != NULL && value.dataType != Res_value::TYPE_NULL) {
+ if (out_indices != nullptr && value.dataType != Res_value::TYPE_NULL) {
indices_idx++;
out_indices[indices_idx] = ii;
}
@@ -187,18 +208,18 @@
res.unlock();
- if (out_indices != NULL) {
+ if (out_indices != nullptr) {
out_indices[0] = indices_idx;
}
return true;
}
-bool ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
- uint32_t def_style_res, uint32_t* attrs, size_t attrs_length, uint32_t* out_values,
- uint32_t* out_indices) {
+void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
+ uint32_t def_style_res, const uint32_t* attrs, size_t attrs_length,
+ uint32_t* out_values, uint32_t* out_indices) {
if (kDebugStyles) {
- ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x xml=0x%p", theme,
- def_style_attr, def_style_res, xml_parser);
+ ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x xml=0x%p",
+ theme, def_style_attr, def_style_res, xml_parser);
}
const ResTable& res = theme->getResTable();
@@ -211,7 +232,8 @@
uint32_t def_style_bag_type_set_flags = 0;
if (def_style_attr != 0) {
Res_value value;
- if (theme->getAttribute(def_style_attr, &value, &def_style_bag_type_set_flags) >= 0) {
+ if (theme->getAttribute(def_style_attr, &value,
+ &def_style_bag_type_set_flags) >= 0) {
if (value.dataType == Res_value::TYPE_REFERENCE) {
def_style_res = value.data;
}
@@ -221,11 +243,12 @@
// Retrieve the style class associated with the current XML tag.
int style = 0;
uint32_t style_bag_type_set_flags = 0;
- if (xml_parser != NULL) {
+ if (xml_parser != nullptr) {
ssize_t idx = xml_parser->indexOfStyle();
if (idx >= 0 && xml_parser->getAttributeValue(idx, &value) >= 0) {
if (value.dataType == value.TYPE_ATTRIBUTE) {
- if (theme->getAttribute(value.data, &value, &style_bag_type_set_flags) < 0) {
+ if (theme->getAttribute(value.data, &value, &style_bag_type_set_flags) <
+ 0) {
value.dataType = Res_value::TYPE_NULL;
}
}
@@ -239,29 +262,35 @@
res.lock();
// Retrieve the default style bag, if requested.
- const ResTable::bag_entry* def_style_attr_start = NULL;
+ const ResTable::bag_entry* def_style_attr_start = nullptr;
uint32_t def_style_type_set_flags = 0;
- ssize_t bag_off =
- def_style_res != 0
- ? res.getBagLocked(def_style_res, &def_style_attr_start, &def_style_type_set_flags)
- : -1;
+ ssize_t bag_off = def_style_res != 0
+ ? res.getBagLocked(def_style_res, &def_style_attr_start,
+ &def_style_type_set_flags)
+ : -1;
def_style_type_set_flags |= def_style_bag_type_set_flags;
const ResTable::bag_entry* const def_style_attr_end =
def_style_attr_start + (bag_off >= 0 ? bag_off : 0);
- BagAttributeFinder def_style_attr_finder(def_style_attr_start, def_style_attr_end);
+ BagAttributeFinder def_style_attr_finder(def_style_attr_start,
+ def_style_attr_end);
// Retrieve the style class bag, if requested.
- const ResTable::bag_entry* style_attr_start = NULL;
+ const ResTable::bag_entry* style_attr_start = nullptr;
uint32_t style_type_set_flags = 0;
- bag_off = style != 0 ? res.getBagLocked(style, &style_attr_start, &style_type_set_flags) : -1;
+ bag_off =
+ style != 0
+ ? res.getBagLocked(style, &style_attr_start, &style_type_set_flags)
+ : -1;
style_type_set_flags |= style_bag_type_set_flags;
- const ResTable::bag_entry* const style_attr_end = style_attr_start + (bag_off >= 0 ? bag_off : 0);
+ const ResTable::bag_entry* const style_attr_end =
+ style_attr_start + (bag_off >= 0 ? bag_off : 0);
BagAttributeFinder style_attr_finder(style_attr_start, style_attr_end);
// Retrieve the XML attributes, if requested.
static const ssize_t kXmlBlock = 0x10000000;
XmlAttributeFinder xml_attr_finder(xml_parser);
- const size_t xml_attr_end = xml_parser != NULL ? xml_parser->getAttributeCount() : 0;
+ const size_t xml_attr_end =
+ xml_parser != nullptr ? xml_parser->getAttributeCount() : 0;
// Now iterate through all of the attributes that the client has requested,
// filling in each with whatever data we can find.
@@ -289,34 +318,41 @@
// We found the attribute we were looking for.
xml_parser->getAttributeValue(xml_attr_idx, &value);
if (kDebugStyles) {
- ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
}
if (value.dataType == Res_value::TYPE_NULL) {
- // Walk through the style class values looking for the requested attribute.
- const ResTable::bag_entry* const style_attr_entry = style_attr_finder.Find(cur_ident);
+ // Walk through the style class values looking for the requested
+ // attribute.
+ const ResTable::bag_entry* const style_attr_entry =
+ style_attr_finder.Find(cur_ident);
if (style_attr_entry != style_attr_end) {
// We found the attribute we were looking for.
block = style_attr_entry->stringBlock;
type_set_flags = style_type_set_flags;
value = style_attr_entry->map.value;
if (kDebugStyles) {
- ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
}
}
if (value.dataType == Res_value::TYPE_NULL) {
- // Walk through the default style values looking for the requested attribute.
- const ResTable::bag_entry* const def_style_attr_entry = def_style_attr_finder.Find(cur_ident);
+ // Walk through the default style values looking for the requested
+ // attribute.
+ const ResTable::bag_entry* const def_style_attr_entry =
+ def_style_attr_finder.Find(cur_ident);
if (def_style_attr_entry != def_style_attr_end) {
// We found the attribute we were looking for.
block = def_style_attr_entry->stringBlock;
type_set_flags = style_type_set_flags;
value = def_style_attr_entry->map.value;
if (kDebugStyles) {
- ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
}
}
@@ -324,30 +360,35 @@
uint32_t resid = 0;
if (value.dataType != Res_value::TYPE_NULL) {
// Take care of resolving the found resource to its final value.
- ssize_t new_block =
- theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
+ ssize_t new_block = theme->resolveAttributeReference(
+ &value, block, &resid, &type_set_flags, &config);
if (new_block >= 0) {
block = new_block;
}
if (kDebugStyles) {
- ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
} else {
// If we still don't have a value for this attribute, try to find
// it in the theme!
- ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
+ ssize_t new_block =
+ theme->getAttribute(cur_ident, &value, &type_set_flags);
if (new_block >= 0) {
if (kDebugStyles) {
- ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
- new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
+ new_block = res.resolveReference(&value, new_block, &resid,
+ &type_set_flags, &config);
if (new_block >= 0) {
block = new_block;
}
if (kDebugStyles) {
- ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
+ ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType,
+ value.data);
}
}
}
@@ -363,20 +404,21 @@
}
if (kDebugStyles) {
- ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.dataType, value.data);
+ ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident,
+ value.dataType, value.data);
}
// Write the final value back to Java.
out_values[STYLE_TYPE] = value.dataType;
out_values[STYLE_DATA] = value.data;
- out_values[STYLE_ASSET_COOKIE] = block != kXmlBlock
- ? static_cast<uint32_t>(res.getTableCookie(block))
- : static_cast<uint32_t>(-1);
+ out_values[STYLE_ASSET_COOKIE] =
+ block != kXmlBlock ? static_cast<uint32_t>(res.getTableCookie(block))
+ : static_cast<uint32_t>(-1);
out_values[STYLE_RESOURCE_ID] = resid;
out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
out_values[STYLE_DENSITY] = config.density;
- if (out_indices != NULL && value.dataType != Res_value::TYPE_NULL) {
+ if (out_indices != nullptr && value.dataType != Res_value::TYPE_NULL) {
indices_idx++;
out_indices[indices_idx] = ii;
}
@@ -386,14 +428,14 @@
res.unlock();
- if (out_indices != NULL) {
+ if (out_indices != nullptr) {
out_indices[0] = indices_idx;
}
- return true;
}
-bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser, uint32_t* attrs,
- size_t attrs_length, uint32_t* out_values, uint32_t* out_indices) {
+bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser,
+ uint32_t* attrs, size_t attrs_length,
+ uint32_t* out_values, uint32_t* out_indices) {
ResTable_config config;
Res_value value;
@@ -437,7 +479,8 @@
if (value.dataType != Res_value::TYPE_NULL) {
// Take care of resolving the found resource to its final value.
// printf("Resolving attribute reference\n");
- ssize_t new_block = res->resolveReference(&value, block, &resid, &type_set_flags, &config);
+ ssize_t new_block = res->resolveReference(&value, block, &resid,
+ &type_set_flags, &config);
if (new_block >= 0) block = new_block;
}
@@ -451,14 +494,14 @@
// Write the final value back to Java.
out_values[STYLE_TYPE] = value.dataType;
out_values[STYLE_DATA] = value.data;
- out_values[STYLE_ASSET_COOKIE] = block != kXmlBlock
- ? static_cast<uint32_t>(res->getTableCookie(block))
- : static_cast<uint32_t>(-1);
+ out_values[STYLE_ASSET_COOKIE] =
+ block != kXmlBlock ? static_cast<uint32_t>(res->getTableCookie(block))
+ : static_cast<uint32_t>(-1);
out_values[STYLE_RESOURCE_ID] = resid;
out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
out_values[STYLE_DENSITY] = config.density;
- if (out_indices != NULL && value.dataType != Res_value::TYPE_NULL) {
+ if (out_indices != nullptr && value.dataType != Res_value::TYPE_NULL) {
indices_idx++;
out_indices[indices_idx] = ii;
}
@@ -468,7 +511,7 @@
res->unlock();
- if (out_indices != NULL) {
+ if (out_indices != nullptr) {
out_indices[0] = indices_idx;
}
return true;
diff --git a/libs/androidfw/AttributeFinder.h b/libs/androidfw/include/androidfw/AttributeFinder.h
similarity index 100%
rename from libs/androidfw/AttributeFinder.h
rename to libs/androidfw/include/androidfw/AttributeFinder.h
diff --git a/libs/androidfw/include/androidfw/AttributeResolution.h b/libs/androidfw/include/androidfw/AttributeResolution.h
index 3ed8bce..8d5ff46 100644
--- a/libs/androidfw/include/androidfw/AttributeResolution.h
+++ b/libs/androidfw/include/androidfw/AttributeResolution.h
@@ -44,9 +44,9 @@
uint32_t* src_values, size_t src_values_length, uint32_t* attrs,
size_t attrs_length, uint32_t* out_values, uint32_t* out_indices);
-bool ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
- uint32_t def_style_res, uint32_t* attrs, size_t attrs_length, uint32_t* out_values,
- uint32_t* out_indices);
+void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
+ uint32_t def_style_res, const uint32_t* attrs, size_t attrs_length,
+ uint32_t* out_values, uint32_t* out_indices);
bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser, uint32_t* attrs,
size_t attrs_length, uint32_t* out_values, uint32_t* out_indices);
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index d18cb8f..d91a133 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -24,6 +24,7 @@
AppAsLib_test.cpp \
Asset_test.cpp \
AttributeFinder_test.cpp \
+ AttributeResolution_test.cpp \
ByteBucketArray_test.cpp \
Config_test.cpp \
ConfigLocale_test.cpp \
@@ -53,14 +54,15 @@
LOCAL_MODULE := libandroidfw_tests
LOCAL_CFLAGS := $(androidfw_test_cflags)
-LOCAL_SRC_FILES := $(testFiles) AttributeResolution_test.cpp
+LOCAL_SRC_FILES := $(testFiles)
LOCAL_STATIC_LIBRARIES := \
libandroidfw \
libbase \
libutils \
libcutils \
liblog \
- libz
+ libz \
+ libziparchive
LOCAL_PICKUP_FILES := $(LOCAL_PATH)/data
include $(BUILD_HOST_NATIVE_TEST)
@@ -82,7 +84,8 @@
libbase \
libcutils \
libutils \
- libui
+ libui \
+ libziparchive
LOCAL_PICKUP_FILES := $(LOCAL_PATH)/data
include $(BUILD_NATIVE_TEST)
diff --git a/libs/androidfw/tests/AppAsLib_test.cpp b/libs/androidfw/tests/AppAsLib_test.cpp
index 8489acf..ddaa46d 100644
--- a/libs/androidfw/tests/AppAsLib_test.cpp
+++ b/libs/androidfw/tests/AppAsLib_test.cpp
@@ -14,55 +14,69 @@
* limitations under the License.
*/
-#include <androidfw/ResourceTypes.h>
+#include "androidfw/ResourceTypes.h"
+#include "TestHelpers.h"
#include "data/appaslib/R.h"
-#include <gtest/gtest.h>
+namespace app = com::android::appaslib::app;
+namespace lib = com::android::appaslib::lib;
-using namespace android;
-
-namespace {
-
-#include "data/appaslib/appaslib_arsc.h"
-#include "data/appaslib/appaslib_lib_arsc.h"
+namespace android {
// This tests the app resources loaded as app.
-TEST(AppAsLibTest, loadedAsApp) {
+TEST(AppAsLibTest, LoadedAsApp) {
+ std::string contents;
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/appaslib/appaslib.apk",
+ "resources.arsc", &contents));
+
ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(appaslib_arsc, appaslib_arsc_len));
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
Res_value val;
- ssize_t block = table.getResource(appaslib::R::app::integer::number1, &val);
+ ssize_t block = table.getResource(app::R::integer::number1, &val);
ASSERT_GE(block, 0);
ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- ASSERT_EQ(appaslib::R::app::array::integerArray1, val.data);
+ ASSERT_EQ(app::R::array::integerArray1, val.data);
}
// This tests the app resources loaded as shared-lib.
-TEST(AppAsLibTest, loadedAsSharedLib) {
+TEST(AppAsLibTest, LoadedAsSharedLib) {
+ std::string contents;
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/appaslib/appaslib.apk",
+ "resources.arsc", &contents));
+
ResTable table;
// Load as shared library.
- ASSERT_EQ(NO_ERROR, table.add(appaslib_arsc, appaslib_arsc_len, NULL, 0, -1, false, true));
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size(), NULL, 0, -1,
+ false, true));
Res_value val;
- ssize_t block = table.getResource(appaslib::R::lib::integer::number1, &val);
+ ssize_t block = table.getResource(lib::R::integer::number1, &val);
ASSERT_GE(block, 0);
ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- ASSERT_EQ(appaslib::R::lib::array::integerArray1, val.data);
+ ASSERT_EQ(lib::R::array::integerArray1, val.data);
}
// This tests the shared-lib loaded with appAsLib as true.
-TEST(AppAsLibTest, loadedSharedLib) {
+TEST(AppAsLibTest, LoadedSharedLib) {
+ std::string contents;
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/appaslib/appaslib_lib.apk",
+ "resources.arsc", &contents));
+
ResTable table;
// Load shared library with appAsLib as true.
- ASSERT_EQ(NO_ERROR, table.add(appaslib_lib_arsc, appaslib_lib_arsc_len, NULL, 0, -1, false, true));
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size(), NULL, 0, -1,
+ false, true));
Res_value val;
- ssize_t block = table.getResource(appaslib::R::lib::integer::number1, &val);
+ ssize_t block = table.getResource(lib::R::integer::number1, &val);
ASSERT_GE(block, 0);
ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- ASSERT_EQ(appaslib::R::lib::array::integerArray1, val.data);
+ ASSERT_EQ(lib::R::array::integerArray1, val.data);
}
-}
+} // namespace android
diff --git a/libs/androidfw/tests/Asset_test.cpp b/libs/androidfw/tests/Asset_test.cpp
index 45c8cef..5018218 100644
--- a/libs/androidfw/tests/Asset_test.cpp
+++ b/libs/androidfw/tests/Asset_test.cpp
@@ -14,24 +14,26 @@
* limitations under the License.
*/
-#include <androidfw/Asset.h>
+#include "androidfw/Asset.h"
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
-using namespace android;
+namespace android {
TEST(AssetTest, FileAssetRegistersItself) {
- const int32_t count = Asset::getGlobalCount();
- Asset* asset = new _FileAsset();
- EXPECT_EQ(count + 1, Asset::getGlobalCount());
- delete asset;
- EXPECT_EQ(count, Asset::getGlobalCount());
+ const int32_t count = Asset::getGlobalCount();
+ Asset* asset = new _FileAsset();
+ EXPECT_EQ(count + 1, Asset::getGlobalCount());
+ delete asset;
+ EXPECT_EQ(count, Asset::getGlobalCount());
}
TEST(AssetTest, CompressedAssetRegistersItself) {
- const int32_t count = Asset::getGlobalCount();
- Asset* asset = new _CompressedAsset();
- EXPECT_EQ(count + 1, Asset::getGlobalCount());
- delete asset;
- EXPECT_EQ(count, Asset::getGlobalCount());
+ const int32_t count = Asset::getGlobalCount();
+ Asset* asset = new _CompressedAsset();
+ EXPECT_EQ(count + 1, Asset::getGlobalCount());
+ delete asset;
+ EXPECT_EQ(count, Asset::getGlobalCount());
}
+
+} // nameapce android
diff --git a/libs/androidfw/tests/AttributeFinder_test.cpp b/libs/androidfw/tests/AttributeFinder_test.cpp
index d9ed48e..7264b81 100644
--- a/libs/androidfw/tests/AttributeFinder_test.cpp
+++ b/libs/androidfw/tests/AttributeFinder_test.cpp
@@ -14,16 +14,18 @@
* limitations under the License.
*/
-#include "../AttributeFinder.h"
+#include "androidfw/AttributeFinder.h"
-#include <android-base/macros.h>
-#include <gtest/gtest.h>
+#include "android-base/macros.h"
+#include "gtest/gtest.h"
-using android::BackTrackingAttributeFinder;
+namespace android {
-class MockAttributeFinder : public BackTrackingAttributeFinder<MockAttributeFinder, int> {
+class MockAttributeFinder
+ : public BackTrackingAttributeFinder<MockAttributeFinder, int> {
public:
- MockAttributeFinder(const uint32_t* attrs, int len) : BackTrackingAttributeFinder(0, len) {
+ MockAttributeFinder(const uint32_t* attrs, int len)
+ : BackTrackingAttributeFinder(0, len) {
attrs_ = new uint32_t[len];
memcpy(attrs_, attrs, sizeof(*attrs) * len);
}
@@ -36,13 +38,16 @@
uint32_t* attrs_;
};
-static const uint32_t kSortedAttributes[] = {0x01010000, 0x01010001, 0x01010002, 0x01010004,
- 0x02010001, 0x02010010, 0x7f010001};
+static const uint32_t kSortedAttributes[] = {0x01010000, 0x01010001, 0x01010002,
+ 0x01010004, 0x02010001, 0x02010010,
+ 0x7f010001};
static const uint32_t kPackageUnsortedAttributes[] = {
- 0x02010001, 0x02010010, 0x01010000, 0x01010001, 0x01010002, 0x01010004, 0x7f010001};
+ 0x02010001, 0x02010010, 0x01010000, 0x01010001,
+ 0x01010002, 0x01010004, 0x7f010001};
-static const uint32_t kSinglePackageAttributes[] = {0x7f010007, 0x7f01000a, 0x7f01000d, 0x00000000};
+static const uint32_t kSinglePackageAttributes[] = {0x7f010007, 0x7f01000a,
+ 0x7f01000d, 0x00000000};
TEST(AttributeFinderTest, IteratesSequentially) {
const int end = arraysize(kSortedAttributes);
@@ -116,3 +121,5 @@
EXPECT_EQ(end, finder.Find(0x010100fa));
EXPECT_EQ(0, finder.Find(0x7f010007));
}
+
+} // namespace android
diff --git a/libs/androidfw/tests/AttributeResolution_test.cpp b/libs/androidfw/tests/AttributeResolution_test.cpp
index d6d7890..d417aba 100644
--- a/libs/androidfw/tests/AttributeResolution_test.cpp
+++ b/libs/androidfw/tests/AttributeResolution_test.cpp
@@ -30,12 +30,11 @@
class AttributeResolutionTest : public ::testing::Test {
public:
virtual void SetUp() override {
- std::string test_source_dir = GetTestDataPath();
std::string contents;
- CHECK(base::ReadFileToString(test_source_dir + "/styles/resources.arsc",
- &contents));
- CHECK(table_.add(contents.data(), contents.size(), 1 /*cookie*/,
- true /*copyData*/) == NO_ERROR);
+ ASSERT_TRUE(ReadFileFromZipToString(
+ GetTestDataPath() + "/styles/styles.apk", "resources.arsc", &contents));
+ ASSERT_EQ(NO_ERROR, table_.add(contents.data(), contents.size(),
+ 1 /*cookie*/, true /*copyData*/));
}
protected:
@@ -46,12 +45,14 @@
public:
virtual void SetUp() override {
AttributeResolutionTest::SetUp();
- std::string test_source_dir = GetTestDataPath();
+
std::string contents;
- CHECK(base::ReadFileToString(test_source_dir + "/styles/layout.xml",
- &contents));
- CHECK(xml_parser_.setTo(contents.data(), contents.size(),
- true /*copyData*/) == NO_ERROR);
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/styles/styles.apk",
+ "res/layout/layout.xml", &contents));
+
+ ASSERT_EQ(NO_ERROR, xml_parser_.setTo(contents.data(), contents.size(),
+ true /*copyData*/));
// Skip to the first tag.
while (xml_parser_.next() != ResXMLParser::START_TAG) {
@@ -161,9 +162,9 @@
std::vector<uint32_t> values;
values.resize(arraysize(attrs) * 6);
- ASSERT_TRUE(ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/,
- 0 /*def_style_res*/, attrs, arraysize(attrs),
- values.data(), nullptr /*out_indices*/));
+ ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/,
+ 0 /*def_style_res*/, attrs, arraysize(attrs),
+ values.data(), nullptr /*out_indices*/);
const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
diff --git a/libs/androidfw/tests/ByteBucketArray_test.cpp b/libs/androidfw/tests/ByteBucketArray_test.cpp
index 376e79c..5d464c7 100644
--- a/libs/androidfw/tests/ByteBucketArray_test.cpp
+++ b/libs/androidfw/tests/ByteBucketArray_test.cpp
@@ -14,28 +14,42 @@
* limitations under the License.
*/
-#include <androidfw/ByteBucketArray.h>
+#include "androidfw/ByteBucketArray.h"
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
-using android::ByteBucketArray;
+namespace android {
TEST(ByteBucketArrayTest, TestSparseInsertion) {
- ByteBucketArray<int> bba;
- ASSERT_TRUE(bba.set(0, 1));
- ASSERT_TRUE(bba.set(10, 2));
- ASSERT_TRUE(bba.set(26, 3));
- ASSERT_TRUE(bba.set(129, 4));
- ASSERT_TRUE(bba.set(234, 5));
+ ByteBucketArray<int> bba;
+ ASSERT_TRUE(bba.set(0, 1));
+ ASSERT_TRUE(bba.set(10, 2));
+ ASSERT_TRUE(bba.set(26, 3));
+ ASSERT_TRUE(bba.set(129, 4));
+ ASSERT_TRUE(bba.set(234, 5));
- for (size_t i = 0; i < bba.size(); i++) {
- switch (i) {
- case 0: EXPECT_EQ(1, bba[i]); break;
- case 10: EXPECT_EQ(2, bba[i]); break;
- case 26: EXPECT_EQ(3, bba[i]); break;
- case 129: EXPECT_EQ(4, bba[i]); break;
- case 234: EXPECT_EQ(5, bba[i]); break;
- default: EXPECT_EQ(0, bba[i]); break;
- }
+ for (size_t i = 0; i < bba.size(); i++) {
+ switch (i) {
+ case 0:
+ EXPECT_EQ(1, bba[i]);
+ break;
+ case 10:
+ EXPECT_EQ(2, bba[i]);
+ break;
+ case 26:
+ EXPECT_EQ(3, bba[i]);
+ break;
+ case 129:
+ EXPECT_EQ(4, bba[i]);
+ break;
+ case 234:
+ EXPECT_EQ(5, bba[i]);
+ break;
+ default:
+ EXPECT_EQ(0, bba[i]);
+ break;
}
+ }
}
+
+} // namespace android
diff --git a/libs/androidfw/tests/Config_test.cpp b/libs/androidfw/tests/Config_test.cpp
index 738947a..778c7bf 100644
--- a/libs/androidfw/tests/Config_test.cpp
+++ b/libs/androidfw/tests/Config_test.cpp
@@ -14,168 +14,172 @@
* limitations under the License.
*/
-#include <androidfw/ResourceTypes.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
+#include "androidfw/ResourceTypes.h"
+
+#include "utils/Log.h"
+#include "utils/String8.h"
+#include "utils/Vector.h"
#include "TestHelpers.h"
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
namespace android {
static ResTable_config selectBest(const ResTable_config& target,
- const Vector<ResTable_config>& configs) {
- ResTable_config bestConfig;
- memset(&bestConfig, 0, sizeof(bestConfig));
- const size_t configCount = configs.size();
- for (size_t i = 0; i < configCount; i++) {
- const ResTable_config& thisConfig = configs[i];
- if (!thisConfig.match(target)) {
- continue;
- }
-
- if (thisConfig.isBetterThan(bestConfig, &target)) {
- bestConfig = thisConfig;
- }
+ const Vector<ResTable_config>& configs) {
+ ResTable_config bestConfig;
+ memset(&bestConfig, 0, sizeof(bestConfig));
+ const size_t configCount = configs.size();
+ for (size_t i = 0; i < configCount; i++) {
+ const ResTable_config& thisConfig = configs[i];
+ if (!thisConfig.match(target)) {
+ continue;
}
- return bestConfig;
+
+ if (thisConfig.isBetterThan(bestConfig, &target)) {
+ bestConfig = thisConfig;
+ }
+ }
+ return bestConfig;
}
static ResTable_config buildDensityConfig(int density) {
- ResTable_config config;
- memset(&config, 0, sizeof(config));
- config.density = uint16_t(density);
- config.sdkVersion = 4;
- return config;
+ ResTable_config config;
+ memset(&config, 0, sizeof(config));
+ config.density = uint16_t(density);
+ config.sdkVersion = 4;
+ return config;
}
TEST(ConfigTest, shouldSelectBestDensity) {
- ResTable_config deviceConfig;
- memset(&deviceConfig, 0, sizeof(deviceConfig));
- deviceConfig.density = ResTable_config::DENSITY_XHIGH;
- deviceConfig.sdkVersion = 21;
+ ResTable_config deviceConfig;
+ memset(&deviceConfig, 0, sizeof(deviceConfig));
+ deviceConfig.density = ResTable_config::DENSITY_XHIGH;
+ deviceConfig.sdkVersion = 21;
- Vector<ResTable_config> configs;
+ Vector<ResTable_config> configs;
- ResTable_config expectedBest = buildDensityConfig(ResTable_config::DENSITY_HIGH);
- configs.add(expectedBest);
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ ResTable_config expectedBest =
+ buildDensityConfig(ResTable_config::DENSITY_HIGH);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
- expectedBest = buildDensityConfig(ResTable_config::DENSITY_XXHIGH);
- configs.add(expectedBest);
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_XXHIGH);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
- expectedBest = buildDensityConfig(int(ResTable_config::DENSITY_XXHIGH) - 20);
- configs.add(expectedBest);
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ expectedBest = buildDensityConfig(int(ResTable_config::DENSITY_XXHIGH) - 20);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
- configs.add(buildDensityConfig(int(ResTable_config::DENSITY_HIGH) + 20));
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ configs.add(buildDensityConfig(int(ResTable_config::DENSITY_HIGH) + 20));
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
- expectedBest = buildDensityConfig(ResTable_config::DENSITY_XHIGH);
- configs.add(expectedBest);
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_XHIGH);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
- expectedBest = buildDensityConfig(ResTable_config::DENSITY_ANY);
- expectedBest.sdkVersion = 21;
- configs.add(expectedBest);
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_ANY);
+ expectedBest.sdkVersion = 21;
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
}
TEST(ConfigTest, shouldSelectBestDensityWhenNoneSpecified) {
- ResTable_config deviceConfig;
- memset(&deviceConfig, 0, sizeof(deviceConfig));
- deviceConfig.sdkVersion = 21;
+ ResTable_config deviceConfig;
+ memset(&deviceConfig, 0, sizeof(deviceConfig));
+ deviceConfig.sdkVersion = 21;
- Vector<ResTable_config> configs;
- configs.add(buildDensityConfig(ResTable_config::DENSITY_HIGH));
+ Vector<ResTable_config> configs;
+ configs.add(buildDensityConfig(ResTable_config::DENSITY_HIGH));
- ResTable_config expectedBest = buildDensityConfig(ResTable_config::DENSITY_MEDIUM);
- configs.add(expectedBest);
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ ResTable_config expectedBest =
+ buildDensityConfig(ResTable_config::DENSITY_MEDIUM);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
- expectedBest = buildDensityConfig(ResTable_config::DENSITY_ANY);
- configs.add(expectedBest);
- ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_ANY);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
}
TEST(ConfigTest, shouldMatchRoundQualifier) {
- ResTable_config deviceConfig;
- memset(&deviceConfig, 0, sizeof(deviceConfig));
+ ResTable_config deviceConfig;
+ memset(&deviceConfig, 0, sizeof(deviceConfig));
- ResTable_config roundConfig;
- memset(&roundConfig, 0, sizeof(roundConfig));
- roundConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
+ ResTable_config roundConfig;
+ memset(&roundConfig, 0, sizeof(roundConfig));
+ roundConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
- EXPECT_FALSE(roundConfig.match(deviceConfig));
+ EXPECT_FALSE(roundConfig.match(deviceConfig));
- deviceConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
+ deviceConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
- EXPECT_TRUE(roundConfig.match(deviceConfig));
+ EXPECT_TRUE(roundConfig.match(deviceConfig));
- deviceConfig.screenLayout2 = ResTable_config::SCREENROUND_NO;
+ deviceConfig.screenLayout2 = ResTable_config::SCREENROUND_NO;
- EXPECT_FALSE(roundConfig.match(deviceConfig));
+ EXPECT_FALSE(roundConfig.match(deviceConfig));
- ResTable_config notRoundConfig;
- memset(¬RoundConfig, 0, sizeof(notRoundConfig));
- notRoundConfig.screenLayout2 = ResTable_config::SCREENROUND_NO;
+ ResTable_config notRoundConfig;
+ memset(¬RoundConfig, 0, sizeof(notRoundConfig));
+ notRoundConfig.screenLayout2 = ResTable_config::SCREENROUND_NO;
- EXPECT_TRUE(notRoundConfig.match(deviceConfig));
+ EXPECT_TRUE(notRoundConfig.match(deviceConfig));
}
TEST(ConfigTest, RoundQualifierShouldHaveStableSortOrder) {
- ResTable_config defaultConfig;
- memset(&defaultConfig, 0, sizeof(defaultConfig));
+ ResTable_config defaultConfig;
+ memset(&defaultConfig, 0, sizeof(defaultConfig));
- ResTable_config longConfig = defaultConfig;
- longConfig.screenLayout = ResTable_config::SCREENLONG_YES;
+ ResTable_config longConfig = defaultConfig;
+ longConfig.screenLayout = ResTable_config::SCREENLONG_YES;
- ResTable_config longRoundConfig = longConfig;
- longRoundConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
+ ResTable_config longRoundConfig = longConfig;
+ longRoundConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
- ResTable_config longRoundPortConfig = longConfig;
- longRoundPortConfig.orientation = ResTable_config::ORIENTATION_PORT;
+ ResTable_config longRoundPortConfig = longConfig;
+ longRoundPortConfig.orientation = ResTable_config::ORIENTATION_PORT;
- EXPECT_TRUE(longConfig.compare(longRoundConfig) < 0);
- EXPECT_TRUE(longConfig.compareLogical(longRoundConfig) < 0);
- EXPECT_TRUE(longRoundConfig.compare(longConfig) > 0);
- EXPECT_TRUE(longRoundConfig.compareLogical(longConfig) > 0);
+ EXPECT_TRUE(longConfig.compare(longRoundConfig) < 0);
+ EXPECT_TRUE(longConfig.compareLogical(longRoundConfig) < 0);
+ EXPECT_TRUE(longRoundConfig.compare(longConfig) > 0);
+ EXPECT_TRUE(longRoundConfig.compareLogical(longConfig) > 0);
- EXPECT_TRUE(longRoundConfig.compare(longRoundPortConfig) < 0);
- EXPECT_TRUE(longRoundConfig.compareLogical(longRoundPortConfig) < 0);
- EXPECT_TRUE(longRoundPortConfig.compare(longRoundConfig) > 0);
- EXPECT_TRUE(longRoundPortConfig.compareLogical(longRoundConfig) > 0);
+ EXPECT_TRUE(longRoundConfig.compare(longRoundPortConfig) < 0);
+ EXPECT_TRUE(longRoundConfig.compareLogical(longRoundPortConfig) < 0);
+ EXPECT_TRUE(longRoundPortConfig.compare(longRoundConfig) > 0);
+ EXPECT_TRUE(longRoundPortConfig.compareLogical(longRoundConfig) > 0);
}
TEST(ConfigTest, ScreenShapeHasCorrectDiff) {
- ResTable_config defaultConfig;
- memset(&defaultConfig, 0, sizeof(defaultConfig));
+ ResTable_config defaultConfig;
+ memset(&defaultConfig, 0, sizeof(defaultConfig));
- ResTable_config roundConfig = defaultConfig;
- roundConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
+ ResTable_config roundConfig = defaultConfig;
+ roundConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
- EXPECT_EQ(defaultConfig.diff(roundConfig), ResTable_config::CONFIG_SCREEN_ROUND);
+ EXPECT_EQ(defaultConfig.diff(roundConfig),
+ ResTable_config::CONFIG_SCREEN_ROUND);
}
TEST(ConfigTest, RoundIsMoreSpecific) {
- ResTable_config deviceConfig;
- memset(&deviceConfig, 0, sizeof(deviceConfig));
- deviceConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
- deviceConfig.screenLayout = ResTable_config::SCREENLONG_YES;
+ ResTable_config deviceConfig;
+ memset(&deviceConfig, 0, sizeof(deviceConfig));
+ deviceConfig.screenLayout2 = ResTable_config::SCREENROUND_YES;
+ deviceConfig.screenLayout = ResTable_config::SCREENLONG_YES;
- ResTable_config targetConfigA;
- memset(&targetConfigA, 0, sizeof(targetConfigA));
+ ResTable_config targetConfigA;
+ memset(&targetConfigA, 0, sizeof(targetConfigA));
- ResTable_config targetConfigB = targetConfigA;
- targetConfigB.screenLayout = ResTable_config::SCREENLONG_YES;
+ ResTable_config targetConfigB = targetConfigA;
+ targetConfigB.screenLayout = ResTable_config::SCREENLONG_YES;
- ResTable_config targetConfigC = targetConfigB;
- targetConfigC.screenLayout2 = ResTable_config::SCREENROUND_YES;
+ ResTable_config targetConfigC = targetConfigB;
+ targetConfigC.screenLayout2 = ResTable_config::SCREENROUND_YES;
- EXPECT_TRUE(targetConfigB.isBetterThan(targetConfigA, &deviceConfig));
- EXPECT_TRUE(targetConfigC.isBetterThan(targetConfigB, &deviceConfig));
+ EXPECT_TRUE(targetConfigB.isBetterThan(targetConfigA, &deviceConfig));
+ EXPECT_TRUE(targetConfigC.isBetterThan(targetConfigB, &deviceConfig));
}
} // namespace android.
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index f50c178..0928b1b 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -14,102 +14,102 @@
* limitations under the License.
*/
-#include <androidfw/ResourceTypes.h>
+#include "androidfw/ResourceTypes.h"
-#include <utils/String8.h>
-#include <utils/String16.h>
+#include "utils/String16.h"
+#include "utils/String8.h"
+
#include "TestHelpers.h"
#include "data/basic/R.h"
-#include <gtest/gtest.h>
+using com::android::basic::R;
-using namespace android;
-
-namespace {
-
-/**
- * Include a binary resource table.
- *
- * Package: com.android.test.basic
- */
-#include "data/basic/basic_arsc.h"
-
-/**
- * Include a binary resource table.
- * This table is an overlay.
- *
- * Package: com.android.test.basic
- */
-#include "data/overlay/overlay_arsc.h"
-
-enum { MAY_NOT_BE_BAG = false };
+namespace android {
class IdmapTest : public ::testing::Test {
-protected:
- virtual void SetUp() {
- ASSERT_EQ(NO_ERROR, mTargetTable.add(basic_arsc, basic_arsc_len));
- ASSERT_EQ(NO_ERROR, mOverlayTable.add(overlay_arsc, overlay_arsc_len));
- char targetName[256] = "com.android.test.basic";
- ASSERT_EQ(NO_ERROR, mTargetTable.createIdmap(mOverlayTable, 0, 0,
- targetName, targetName, &mData, &mDataSize));
- }
+ protected:
+ void SetUp() override {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
+ ASSERT_EQ(NO_ERROR,
+ target_table_.add(contents.data(), contents.size(), 0, true));
- virtual void TearDown() {
- free(mData);
- }
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/overlay/overlay.apk",
+ "resources.arsc", &overlay_data_));
+ ResTable overlay_table;
+ ASSERT_EQ(NO_ERROR,
+ overlay_table.add(overlay_data_.data(), overlay_data_.size()));
- ResTable mTargetTable;
- ResTable mOverlayTable;
- void* mData;
- size_t mDataSize;
+ char target_name[256] = "com.android.basic";
+ ASSERT_EQ(NO_ERROR,
+ target_table_.createIdmap(overlay_table, 0, 0, target_name,
+ target_name, &data_, &data_size_));
+ }
+
+ void TearDown() override { ::free(data_); }
+
+ ResTable target_table_;
+ std::string overlay_data_;
+ void* data_ = nullptr;
+ size_t data_size_ = 0;
};
TEST_F(IdmapTest, canLoadIdmap) {
- ASSERT_EQ(NO_ERROR, mTargetTable.add(overlay_arsc, overlay_arsc_len, mData, mDataSize));
+ ASSERT_EQ(NO_ERROR,
+ target_table_.add(overlay_data_.data(), overlay_data_.size(), data_,
+ data_size_));
}
TEST_F(IdmapTest, overlayOverridesResourceValue) {
- Res_value val;
- ssize_t block = mTargetTable.getResource(base::R::string::test2, &val, false);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
- const ResStringPool* pool = mTargetTable.getTableStringBlock(block);
- ASSERT_TRUE(pool != NULL);
- ASSERT_LT(val.data, pool->size());
+ Res_value val;
+ ssize_t block = target_table_.getResource(R::string::test2, &val, false);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
+ const ResStringPool* pool = target_table_.getTableStringBlock(block);
+ ASSERT_TRUE(pool != NULL);
+ ASSERT_LT(val.data, pool->size());
- size_t strLen;
- const char16_t* targetStr16 = pool->stringAt(val.data, &strLen);
- ASSERT_TRUE(targetStr16 != NULL);
- ASSERT_EQ(String16("test2"), String16(targetStr16, strLen));
+ size_t strLen;
+ const char16_t* targetStr16 = pool->stringAt(val.data, &strLen);
+ ASSERT_TRUE(targetStr16 != NULL);
+ ASSERT_EQ(String16("test2"), String16(targetStr16, strLen));
- ASSERT_EQ(NO_ERROR, mTargetTable.add(overlay_arsc, overlay_arsc_len, mData, mDataSize));
+ ASSERT_EQ(NO_ERROR,
+ target_table_.add(overlay_data_.data(), overlay_data_.size(), data_,
+ data_size_));
- ssize_t newBlock = mTargetTable.getResource(base::R::string::test2, &val, false);
- ASSERT_GE(newBlock, 0);
- ASSERT_NE(block, newBlock);
- ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
- pool = mTargetTable.getTableStringBlock(newBlock);
- ASSERT_TRUE(pool != NULL);
- ASSERT_LT(val.data, pool->size());
+ ssize_t newBlock = target_table_.getResource(R::string::test2, &val, false);
+ ASSERT_GE(newBlock, 0);
+ ASSERT_NE(block, newBlock);
+ ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
+ pool = target_table_.getTableStringBlock(newBlock);
+ ASSERT_TRUE(pool != NULL);
+ ASSERT_LT(val.data, pool->size());
- targetStr16 = pool->stringAt(val.data, &strLen);
- ASSERT_TRUE(targetStr16 != NULL);
- ASSERT_EQ(String16("test2-overlay"), String16(targetStr16, strLen));
+ targetStr16 = pool->stringAt(val.data, &strLen);
+ ASSERT_TRUE(targetStr16 != NULL);
+ ASSERT_EQ(String16("test2-overlay"), String16(targetStr16, strLen));
}
TEST_F(IdmapTest, overlaidResourceHasSameName) {
- ASSERT_EQ(NO_ERROR, mTargetTable.add(overlay_arsc, overlay_arsc_len, mData, mDataSize));
+ ASSERT_EQ(NO_ERROR,
+ target_table_.add(overlay_data_.data(), overlay_data_.size(), data_,
+ data_size_));
- ResTable::resource_name resName;
- ASSERT_TRUE(mTargetTable.getResourceName(base::R::array::integerArray1, false, &resName));
+ ResTable::resource_name resName;
+ ASSERT_TRUE(
+ target_table_.getResourceName(R::array::integerArray1, false, &resName));
- ASSERT_TRUE(resName.package != NULL);
- ASSERT_TRUE(resName.type != NULL);
- ASSERT_TRUE(resName.name != NULL);
+ ASSERT_TRUE(resName.package != NULL);
+ ASSERT_TRUE(resName.type != NULL);
+ ASSERT_TRUE(resName.name != NULL);
- EXPECT_EQ(String16("com.android.test.basic"), String16(resName.package, resName.packageLen));
- EXPECT_EQ(String16("array"), String16(resName.type, resName.typeLen));
- EXPECT_EQ(String16("integerArray1"), String16(resName.name, resName.nameLen));
+ EXPECT_EQ(String16("com.android.basic"),
+ String16(resName.package, resName.packageLen));
+ EXPECT_EQ(String16("array"), String16(resName.type, resName.typeLen));
+ EXPECT_EQ(String16("integerArray1"), String16(resName.name, resName.nameLen));
}
-} // namespace
+} // namespace
diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp
index 9e53dd2..b151f3f 100644
--- a/libs/androidfw/tests/ResTable_test.cpp
+++ b/libs/androidfw/tests/ResTable_test.cpp
@@ -14,352 +14,386 @@
* limitations under the License.
*/
-#include <androidfw/ResourceTypes.h>
+#include "androidfw/ResourceTypes.h"
#include <codecvt>
#include <locale>
#include <string>
-#include <utils/String8.h>
-#include <utils/String16.h>
+#include "utils/String16.h"
+#include "utils/String8.h"
+
#include "TestHelpers.h"
#include "data/basic/R.h"
#include "data/lib/R.h"
-#include <gtest/gtest.h>
+namespace basic = com::android::basic;
+namespace lib = com::android::lib;
-using namespace android;
+namespace android {
-namespace {
+TEST(ResTableTest, ShouldLoadSuccessfully) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
-/**
- * Include a binary resource table.
- *
- * Package: com.android.test.basic
- */
-#include "data/basic/basic_arsc.h"
-
-/**
- * Include a binary library resource table.
- *
- * Package: com.android.test.basic
- */
-#include "data/lib/lib_arsc.h"
-
-/**
- * Include a system resource table.
- *
- * Package: android
- */
-#include "data/system/system_arsc.h"
-
-TEST(ResTableTest, shouldLoadSuccessfully) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
}
-TEST(ResTableTest, simpleTypeIsRetrievedCorrectly) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST(ResTableTest, SimpleTypeIsRetrievedCorrectly) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- EXPECT_TRUE(IsStringEqual(table, base::R::string::test1, "test1"));
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
+
+ EXPECT_TRUE(IsStringEqual(table, basic::R::string::test1, "test1"));
}
-TEST(ResTableTest, resourceNameIsResolved) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST(ResTableTest, ResourceNameIsResolved) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- String16 defPackage("com.android.test.basic");
- String16 testName("@string/test1");
- uint32_t resID = table.identifierForName(testName.string(), testName.size(),
- 0, 0,
- defPackage.string(), defPackage.size());
- ASSERT_NE(uint32_t(0x00000000), resID);
- ASSERT_EQ(base::R::string::test1, resID);
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
+
+ String16 defPackage("com.android.basic");
+ String16 testName("@string/test1");
+ uint32_t resID =
+ table.identifierForName(testName.string(), testName.size(), 0, 0,
+ defPackage.string(), defPackage.size());
+ ASSERT_NE(uint32_t(0x00000000), resID);
+ ASSERT_EQ(basic::R::string::test1, resID);
}
-TEST(ResTableTest, noParentThemeIsAppliedCorrectly) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST(ResTableTest, NoParentThemeIsAppliedCorrectly) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- ResTable::Theme theme(table);
- ASSERT_EQ(NO_ERROR, theme.applyStyle(base::R::style::Theme1));
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
- Res_value val;
- uint32_t specFlags = 0;
- ssize_t index = theme.getAttribute(base::R::attr::attr1, &val, &specFlags);
- ASSERT_GE(index, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(100), val.data);
+ ResTable::Theme theme(table);
+ ASSERT_EQ(NO_ERROR, theme.applyStyle(basic::R::style::Theme1));
- index = theme.getAttribute(base::R::attr::attr2, &val, &specFlags);
- ASSERT_GE(index, 0);
- ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- ASSERT_EQ(base::R::integer::number1, val.data);
+ Res_value val;
+ uint32_t specFlags = 0;
+ ssize_t index = theme.getAttribute(basic::R::attr::attr1, &val, &specFlags);
+ ASSERT_GE(index, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(100), val.data);
+
+ index = theme.getAttribute(basic::R::attr::attr2, &val, &specFlags);
+ ASSERT_GE(index, 0);
+ ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
+ ASSERT_EQ(basic::R::integer::number1, val.data);
}
-TEST(ResTableTest, parentThemeIsAppliedCorrectly) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST(ResTableTest, ParentThemeIsAppliedCorrectly) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- ResTable::Theme theme(table);
- ASSERT_EQ(NO_ERROR, theme.applyStyle(base::R::style::Theme2));
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
- Res_value val;
- uint32_t specFlags = 0;
- ssize_t index = theme.getAttribute(base::R::attr::attr1, &val, &specFlags);
- ASSERT_GE(index, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(300), val.data);
+ ResTable::Theme theme(table);
+ ASSERT_EQ(NO_ERROR, theme.applyStyle(basic::R::style::Theme2));
- index = theme.getAttribute(base::R::attr::attr2, &val, &specFlags);
- ASSERT_GE(index, 0);
- ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- ASSERT_EQ(base::R::integer::number1, val.data);
+ Res_value val;
+ uint32_t specFlags = 0;
+ ssize_t index = theme.getAttribute(basic::R::attr::attr1, &val, &specFlags);
+ ASSERT_GE(index, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(300), val.data);
+
+ index = theme.getAttribute(basic::R::attr::attr2, &val, &specFlags);
+ ASSERT_GE(index, 0);
+ ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
+ ASSERT_EQ(basic::R::integer::number1, val.data);
}
-TEST(ResTableTest, libraryThemeIsAppliedCorrectly) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(lib_arsc, lib_arsc_len));
+TEST(ResTableTest, LibraryThemeIsAppliedCorrectly) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/lib/lib.apk",
+ "resources.arsc", &contents));
- ResTable::Theme theme(table);
- ASSERT_EQ(NO_ERROR, theme.applyStyle(lib::R::style::Theme));
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
- Res_value val;
- uint32_t specFlags = 0;
- ssize_t index = theme.getAttribute(lib::R::attr::attr1, &val, &specFlags);
- ASSERT_GE(index, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(700), val.data);
+ ResTable::Theme theme(table);
+ ASSERT_EQ(NO_ERROR, theme.applyStyle(lib::R::style::Theme));
- index = theme.getAttribute(lib::R::attr::attr2, &val, &specFlags);
- ASSERT_GE(index, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(700), val.data);
+ Res_value val;
+ uint32_t specFlags = 0;
+ ssize_t index = theme.getAttribute(lib::R::attr::attr1, &val, &specFlags);
+ ASSERT_GE(index, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(700), val.data);
+
+ index = theme.getAttribute(lib::R::attr::attr2, &val, &specFlags);
+ ASSERT_GE(index, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(700), val.data);
}
-TEST(ResTableTest, referenceToBagIsNotResolved) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST(ResTableTest, ReferenceToBagIsNotResolved) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- Res_value val;
- ssize_t block = table.getResource(base::R::integer::number2, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- ASSERT_EQ(base::R::array::integerArray1, val.data);
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
- ssize_t newBlock = table.resolveReference(&val, block);
- EXPECT_EQ(block, newBlock);
- EXPECT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- EXPECT_EQ(base::R::array::integerArray1, val.data);
+ Res_value val;
+ ssize_t block =
+ table.getResource(basic::R::integer::number2, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
+ ASSERT_EQ(basic::R::array::integerArray1, val.data);
+
+ ssize_t newBlock = table.resolveReference(&val, block);
+ EXPECT_EQ(block, newBlock);
+ EXPECT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
+ EXPECT_EQ(basic::R::array::integerArray1, val.data);
}
-TEST(ResTableTest, resourcesStillAccessibleAfterParameterChange) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST(ResTableTest, ResourcesStillAccessibleAfterParameterChange) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- Res_value val;
- ssize_t block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
- const ResTable::bag_entry* entry;
- ssize_t count = table.lockBag(base::R::array::integerArray1, &entry);
- ASSERT_GE(count, 0);
- table.unlockBag(entry);
+ Res_value val;
+ ssize_t block =
+ table.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ResTable_config param;
- memset(¶m, 0, sizeof(param));
- param.density = 320;
- table.setParameters(¶m);
+ const ResTable::bag_entry* entry;
+ ssize_t count = table.lockBag(basic::R::array::integerArray1, &entry);
+ ASSERT_GE(count, 0);
+ table.unlockBag(entry);
- block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ResTable_config param;
+ memset(¶m, 0, sizeof(param));
+ param.density = 320;
+ table.setParameters(¶m);
- count = table.lockBag(base::R::array::integerArray1, &entry);
- ASSERT_GE(count, 0);
- table.unlockBag(entry);
+ block = table.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+
+ count = table.lockBag(basic::R::array::integerArray1, &entry);
+ ASSERT_GE(count, 0);
+ table.unlockBag(entry);
}
-TEST(ResTableTest, resourceIsOverridenWithBetterConfig) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST(ResTableTest, ResourceIsOverridenWithBetterConfig) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- Res_value val;
- ssize_t block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(200), val.data);
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
- ResTable_config param;
- memset(¶m, 0, sizeof(param));
- param.language[0] = 's';
- param.language[1] = 'v';
- param.country[0] = 'S';
- param.country[1] = 'E';
- table.setParameters(¶m);
+ Res_value val;
+ ssize_t block =
+ table.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(200), val.data);
- block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(400), val.data);
+ ResTable_config param;
+ memset(¶m, 0, sizeof(param));
+ param.language[0] = 's';
+ param.language[1] = 'v';
+ param.country[0] = 'S';
+ param.country[1] = 'E';
+ table.setParameters(¶m);
+
+ block = table.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(400), val.data);
}
TEST(ResTableTest, emptyTableHasSensibleDefaults) {
- const int32_t assetCookie = 1;
+ const int32_t assetCookie = 1;
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.addEmpty(assetCookie));
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.addEmpty(assetCookie));
- // Adding an empty table gives us one table!
- ASSERT_EQ(uint32_t(1), table.getTableCount());
+ // Adding an empty table gives us one table!
+ ASSERT_EQ(uint32_t(1), table.getTableCount());
- // Adding an empty table doesn't mean we get packages.
- ASSERT_EQ(uint32_t(0), table.getBasePackageCount());
+ // Adding an empty table doesn't mean we get packages.
+ ASSERT_EQ(uint32_t(0), table.getBasePackageCount());
- Res_value val;
- ASSERT_LT(table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG), 0);
+ Res_value val;
+ ASSERT_LT(table.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG),
+ 0);
}
void testU16StringToInt(const char16_t* str, uint32_t expectedValue,
bool expectSuccess, bool expectHex) {
- size_t len = std::char_traits<char16_t>::length(str);
+ size_t len = std::char_traits<char16_t>::length(str);
- // Gtest can't print UTF-16 strings, so we have to convert to UTF-8 :(
- std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
- std::string s = convert.to_bytes(std::u16string(str, len));
+ // Gtest can't print UTF-16 strings, so we have to convert to UTF-8 :(
+ std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
+ std::string s = convert.to_bytes(std::u16string(str, len));
- Res_value out = {};
- ASSERT_EQ(expectSuccess, U16StringToInt(str, len, &out))
- << "Failed with " << s;
+ Res_value out = {};
+ ASSERT_EQ(expectSuccess, U16StringToInt(str, len, &out)) << "Failed with "
+ << s;
- if (!expectSuccess) {
- ASSERT_EQ(out.TYPE_NULL, out.dataType) << "Failed with " << s;
- return;
- }
+ if (!expectSuccess) {
+ ASSERT_EQ(out.TYPE_NULL, out.dataType) << "Failed with " << s;
+ return;
+ }
- if (expectHex) {
- ASSERT_EQ(out.TYPE_INT_HEX, out.dataType) << "Failed with " << s;
- } else {
- ASSERT_EQ(out.TYPE_INT_DEC, out.dataType) << "Failed with " << s;
- }
+ if (expectHex) {
+ ASSERT_EQ(out.TYPE_INT_HEX, out.dataType) << "Failed with " << s;
+ } else {
+ ASSERT_EQ(out.TYPE_INT_DEC, out.dataType) << "Failed with " << s;
+ }
- ASSERT_EQ(expectedValue, out.data) << "Failed with " << s;
+ ASSERT_EQ(expectedValue, out.data) << "Failed with " << s;
}
TEST(ResTableTest, U16StringToInt) {
- testU16StringToInt(u"", 0U, false, false);
- testU16StringToInt(u" ", 0U, false, false);
- testU16StringToInt(u"\t\n", 0U, false, false);
+ testU16StringToInt(u"", 0U, false, false);
+ testU16StringToInt(u" ", 0U, false, false);
+ testU16StringToInt(u"\t\n", 0U, false, false);
- testU16StringToInt(u"abcd", 0U, false, false);
- testU16StringToInt(u"10abcd", 0U, false, false);
- testU16StringToInt(u"42 42", 0U, false, false);
- testU16StringToInt(u"- 42", 0U, false, false);
- testU16StringToInt(u"-", 0U, false, false);
+ testU16StringToInt(u"abcd", 0U, false, false);
+ testU16StringToInt(u"10abcd", 0U, false, false);
+ testU16StringToInt(u"42 42", 0U, false, false);
+ testU16StringToInt(u"- 42", 0U, false, false);
+ testU16StringToInt(u"-", 0U, false, false);
- testU16StringToInt(u"0x", 0U, false, true);
- testU16StringToInt(u"0xnope", 0U, false, true);
- testU16StringToInt(u"0X42", 0U, false, true);
- testU16StringToInt(u"0x42 0x42", 0U, false, true);
- testU16StringToInt(u"-0x0", 0U, false, true);
- testU16StringToInt(u"-0x42", 0U, false, true);
- testU16StringToInt(u"- 0x42", 0U, false, true);
+ testU16StringToInt(u"0x", 0U, false, true);
+ testU16StringToInt(u"0xnope", 0U, false, true);
+ testU16StringToInt(u"0X42", 0U, false, true);
+ testU16StringToInt(u"0x42 0x42", 0U, false, true);
+ testU16StringToInt(u"-0x0", 0U, false, true);
+ testU16StringToInt(u"-0x42", 0U, false, true);
+ testU16StringToInt(u"- 0x42", 0U, false, true);
- // Note that u" 42" would pass. This preserves the old behavior, but it may
- // not be desired.
- testU16StringToInt(u"42 ", 0U, false, false);
- testU16StringToInt(u"0x42 ", 0U, false, true);
+ // Note that u" 42" would pass. This preserves the old behavior, but it may
+ // not be desired.
+ testU16StringToInt(u"42 ", 0U, false, false);
+ testU16StringToInt(u"0x42 ", 0U, false, true);
- // Decimal cases.
- testU16StringToInt(u"0", 0U, true, false);
- testU16StringToInt(u"-0", 0U, true, false);
- testU16StringToInt(u"42", 42U, true, false);
- testU16StringToInt(u" 42", 42U, true, false);
- testU16StringToInt(u"-42", static_cast<uint32_t>(-42), true, false);
- testU16StringToInt(u" -42", static_cast<uint32_t>(-42), true, false);
- testU16StringToInt(u"042", 42U, true, false);
- testU16StringToInt(u"-042", static_cast<uint32_t>(-42), true, false);
+ // Decimal cases.
+ testU16StringToInt(u"0", 0U, true, false);
+ testU16StringToInt(u"-0", 0U, true, false);
+ testU16StringToInt(u"42", 42U, true, false);
+ testU16StringToInt(u" 42", 42U, true, false);
+ testU16StringToInt(u"-42", static_cast<uint32_t>(-42), true, false);
+ testU16StringToInt(u" -42", static_cast<uint32_t>(-42), true, false);
+ testU16StringToInt(u"042", 42U, true, false);
+ testU16StringToInt(u"-042", static_cast<uint32_t>(-42), true, false);
- // Hex cases.
- testU16StringToInt(u"0x0", 0x0, true, true);
- testU16StringToInt(u"0x42", 0x42, true, true);
- testU16StringToInt(u" 0x42", 0x42, true, true);
+ // Hex cases.
+ testU16StringToInt(u"0x0", 0x0, true, true);
+ testU16StringToInt(u"0x42", 0x42, true, true);
+ testU16StringToInt(u" 0x42", 0x42, true, true);
- // Just before overflow cases:
- testU16StringToInt(u"2147483647", INT_MAX, true, false);
- testU16StringToInt(u"-2147483648", static_cast<uint32_t>(INT_MIN), true,
- false);
- testU16StringToInt(u"0xffffffff", UINT_MAX, true, true);
+ // Just before overflow cases:
+ testU16StringToInt(u"2147483647", INT_MAX, true, false);
+ testU16StringToInt(u"-2147483648", static_cast<uint32_t>(INT_MIN), true,
+ false);
+ testU16StringToInt(u"0xffffffff", UINT_MAX, true, true);
- // Overflow cases:
- testU16StringToInt(u"2147483648", 0U, false, false);
- testU16StringToInt(u"-2147483649", 0U, false, false);
- testU16StringToInt(u"0x1ffffffff", 0U, false, true);
+ // Overflow cases:
+ testU16StringToInt(u"2147483648", 0U, false, false);
+ testU16StringToInt(u"-2147483649", 0U, false, false);
+ testU16StringToInt(u"0x1ffffffff", 0U, false, true);
}
TEST(ResTableTest, ShareButDontModifyResTable) {
- ResTable sharedTable;
- ASSERT_EQ(NO_ERROR, sharedTable.add(basic_arsc, basic_arsc_len));
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- ResTable_config param;
- memset(¶m, 0, sizeof(param));
- param.language[0] = 'v';
- param.language[1] = 's';
- sharedTable.setParameters(¶m);
+ ResTable sharedTable;
+ ASSERT_EQ(NO_ERROR, sharedTable.add(contents.data(), contents.size()));
- // Check that we get the default value for @integer:number1
- Res_value val;
- ssize_t block = sharedTable.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(600), val.data);
+ ResTable_config param;
+ memset(¶m, 0, sizeof(param));
+ param.language[0] = 'v';
+ param.language[1] = 's';
+ sharedTable.setParameters(¶m);
- // Create a new table that shares the entries of the shared table.
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(&sharedTable, false));
+ // Check that we get the default value for @integer:number1
+ Res_value val;
+ ssize_t block =
+ sharedTable.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(600), val.data);
- // Set a new configuration on the new table.
- memset(¶m, 0, sizeof(param));
- param.language[0] = 's';
- param.language[1] = 'v';
- param.country[0] = 'S';
- param.country[1] = 'E';
- table.setParameters(¶m);
+ // Create a new table that shares the entries of the shared table.
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(&sharedTable, false));
- // Check that we get a new value in the new table.
- block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(400), val.data);
+ // Set a new configuration on the new table.
+ memset(¶m, 0, sizeof(param));
+ param.language[0] = 's';
+ param.language[1] = 'v';
+ param.country[0] = 'S';
+ param.country[1] = 'E';
+ table.setParameters(¶m);
- // Check that we still get the old value in the shared table.
- block = sharedTable.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
- ASSERT_GE(block, 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(600), val.data);
+ // Check that we get a new value in the new table.
+ block = table.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(400), val.data);
+
+ // Check that we still get the old value in the shared table.
+ block =
+ sharedTable.getResource(basic::R::integer::number1, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(600), val.data);
}
TEST(ResTableTest, GetConfigurationsReturnsUniqueList) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(system_arsc, system_arsc_len));
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &contents));
- ResTable_config configSv;
- memset(&configSv, 0, sizeof(configSv));
- configSv.language[0] = 's';
- configSv.language[1] = 'v';
+ std::string system_contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/system/system.apk",
+ "resources.arsc", &system_contents));
- Vector<ResTable_config> configs;
- table.getConfigurations(&configs);
+ ResTable table;
+ ASSERT_EQ(NO_ERROR,
+ table.add(system_contents.data(), system_contents.size()));
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
- EXPECT_EQ(1, std::count(configs.begin(), configs.end(), configSv));
+ ResTable_config configSv;
+ memset(&configSv, 0, sizeof(configSv));
+ configSv.language[0] = 's';
+ configSv.language[1] = 'v';
- Vector<String8> locales;
- table.getLocales(&locales);
+ Vector<ResTable_config> configs;
+ table.getConfigurations(&configs);
- EXPECT_EQ(1, std::count(locales.begin(), locales.end(), String8("sv")));
+ EXPECT_EQ(1, std::count(configs.begin(), configs.end(), configSv));
+
+ Vector<String8> locales;
+ table.getLocales(&locales);
+
+ EXPECT_EQ(1, std::count(locales.begin(), locales.end(), String8("sv")));
}
-} // namespace
+} // namespace android
diff --git a/libs/androidfw/tests/Split_test.cpp b/libs/androidfw/tests/Split_test.cpp
index b69d685..2c242db 100644
--- a/libs/androidfw/tests/Split_test.cpp
+++ b/libs/androidfw/tests/Split_test.cpp
@@ -14,233 +14,255 @@
* limitations under the License.
*/
-#include <androidfw/ResourceTypes.h>
+#include "androidfw/ResourceTypes.h"
-#include <utils/String8.h>
-#include <utils/String16.h>
+#include "utils/String16.h"
+#include "utils/String8.h"
+
#include "TestHelpers.h"
#include "data/basic/R.h"
-#include <gtest/gtest.h>
+using com::android::basic::R;
-using namespace android;
+namespace android {
-namespace {
-
-/**
- * Include a binary resource table. This table
- * is a base table for an APK split.
- *
- * Package: com.android.test.basic
- */
-#include "data/basic/basic_arsc.h"
-
-/**
- * Include a binary resource table. This table
- * is a configuration split table for an APK split.
- *
- * Package: com.android.test.basic
- */
-#include "data/basic/split_de_fr_arsc.h"
-#include "data/basic/split_hdpi_v4_arsc.h"
-#include "data/basic/split_xhdpi_v4_arsc.h"
-#include "data/basic/split_xxhdpi_v4_arsc.h"
-
-/**
- * Include a binary resource table. This table
- * is a feature split table for an APK split.
- *
- * Package: com.android.test.basic
- */
-#include "data/feature/feature_arsc.h"
-
-enum { MAY_NOT_BE_BAG = false };
-
-void makeConfigFrench(ResTable_config* config) {
- memset(config, 0, sizeof(*config));
- config->language[0] = 'f';
- config->language[1] = 'r';
+static void makeConfigFrench(ResTable_config* config) {
+ memset(config, 0, sizeof(*config));
+ config->language[0] = 'f';
+ config->language[1] = 'r';
}
-TEST(SplitTest, TestLoadBase) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+class SplitTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
+ "resources.arsc", &basic_contents_));
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/basic/basic_de_fr.apk",
+ "resources.arsc", &basic_de_fr_contents_));
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/basic/basic_hdpi-v4.apk",
+ "resources.arsc", &basic_hdpi_contents_));
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/basic/basic_xhdpi-v4.apk",
+ "resources.arsc", &basic_xhdpi_contents_));
+ ASSERT_TRUE(ReadFileFromZipToString(
+ GetTestDataPath() + "/basic/basic_xxhdpi-v4.apk", "resources.arsc",
+ &basic_xxhdpi_contents_));
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/feature/feature.apk",
+ "resources.arsc", &feature_contents_));
+ }
+
+ protected:
+ std::string basic_contents_;
+ std::string basic_de_fr_contents_;
+ std::string basic_hdpi_contents_;
+ std::string basic_xhdpi_contents_;
+ std::string basic_xxhdpi_contents_;
+ std::string feature_contents_;
+};
+
+TEST_F(SplitTest, TestLoadBase) {
+ ResTable table;
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
}
-TEST(SplitTest, TestGetResourceFromBase) {
- ResTable_config frenchConfig;
- makeConfigFrench(&frenchConfig);
+TEST_F(SplitTest, TestGetResourceFromBase) {
+ ResTable_config frenchConfig;
+ makeConfigFrench(&frenchConfig);
- ResTable table;
- table.setParameters(&frenchConfig);
+ ResTable table;
+ table.setParameters(&frenchConfig);
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
- ResTable_config expectedConfig;
- memset(&expectedConfig, 0, sizeof(expectedConfig));
+ ResTable_config expectedConfig;
+ memset(&expectedConfig, 0, sizeof(expectedConfig));
- Res_value val;
- ResTable_config config;
- ssize_t block = table.getResource(base::R::string::test1, &val, MAY_NOT_BE_BAG, 0, NULL, &config);
+ Res_value val;
+ ResTable_config config;
+ ssize_t block = table.getResource(R::string::test1, &val, MAY_NOT_BE_BAG, 0,
+ NULL, &config);
- // The returned block should tell us which string pool to get the value, if it is a string.
- EXPECT_GE(block, 0);
+ // The returned block should tell us which string pool to get the value, if it
+ // is a string.
+ EXPECT_GE(block, 0);
- // We expect the default resource to be selected since it is the only resource configuration.
- EXPECT_EQ(0, expectedConfig.compare(config));
+ // We expect the default resource to be selected since it is the only resource
+ // configuration.
+ EXPECT_EQ(0, expectedConfig.compare(config));
- EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
+ EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
}
-TEST(SplitTest, TestGetResourceFromSplit) {
- ResTable_config expectedConfig;
- makeConfigFrench(&expectedConfig);
+TEST_F(SplitTest, TestGetResourceFromSplit) {
+ ResTable_config expectedConfig;
+ makeConfigFrench(&expectedConfig);
- ResTable table;
- table.setParameters(&expectedConfig);
+ ResTable table;
+ table.setParameters(&expectedConfig);
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
- ASSERT_EQ(NO_ERROR, table.add(split_de_fr_arsc, split_de_fr_arsc_len));
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
+ ASSERT_EQ(NO_ERROR, table.add(basic_de_fr_contents_.data(),
+ basic_de_fr_contents_.size()));
- Res_value val;
- ResTable_config config;
- ssize_t block = table.getResource(base::R::string::test1, &val, MAY_NOT_BE_BAG, 0, NULL, &config);
+ Res_value val;
+ ResTable_config config;
+ ssize_t block = table.getResource(R::string::test1, &val, MAY_NOT_BE_BAG, 0,
+ NULL, &config);
- EXPECT_GE(block, 0);
+ EXPECT_GE(block, 0);
- EXPECT_EQ(0, expectedConfig.compare(config));
+ EXPECT_EQ(0, expectedConfig.compare(config));
- EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
+ EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
}
-TEST(SplitTest, ResourcesFromBaseAndSplitHaveSameNames) {
- ResTable_config expectedConfig;
- makeConfigFrench(&expectedConfig);
+TEST_F(SplitTest, ResourcesFromBaseAndSplitHaveSameNames) {
+ ResTable_config expectedConfig;
+ makeConfigFrench(&expectedConfig);
- ResTable table;
- table.setParameters(&expectedConfig);
+ ResTable table;
+ table.setParameters(&expectedConfig);
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
- ResTable::resource_name baseName;
- EXPECT_TRUE(table.getResourceName(base::R::string::test1, false, &baseName));
+ ResTable::resource_name baseName;
+ EXPECT_TRUE(table.getResourceName(R::string::test1, false, &baseName));
- ASSERT_EQ(NO_ERROR, table.add(split_de_fr_arsc, split_de_fr_arsc_len));
+ ASSERT_EQ(NO_ERROR, table.add(basic_de_fr_contents_.data(),
+ basic_de_fr_contents_.size()));
- ResTable::resource_name frName;
- EXPECT_TRUE(table.getResourceName(base::R::string::test1, false, &frName));
+ ResTable::resource_name frName;
+ EXPECT_TRUE(table.getResourceName(R::string::test1, false, &frName));
- EXPECT_EQ(
- String16(baseName.package, baseName.packageLen),
+ EXPECT_EQ(String16(baseName.package, baseName.packageLen),
String16(frName.package, frName.packageLen));
- EXPECT_EQ(
- String16(baseName.type, baseName.typeLen),
+ EXPECT_EQ(String16(baseName.type, baseName.typeLen),
String16(frName.type, frName.typeLen));
- EXPECT_EQ(
- String16(baseName.name, baseName.nameLen),
+ EXPECT_EQ(String16(baseName.name, baseName.nameLen),
String16(frName.name, frName.nameLen));
}
-TEST(SplitTest, TypeEntrySpecFlagsAreUpdated) {
- ResTable_config defaultConfig;
- memset(&defaultConfig, 0, sizeof(defaultConfig));
+TEST_F(SplitTest, TypeEntrySpecFlagsAreUpdated) {
+ ResTable_config defaultConfig;
+ memset(&defaultConfig, 0, sizeof(defaultConfig));
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+ ResTable table;
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
- Res_value val;
- uint32_t specFlags = 0;
- ssize_t block = table.getResource(base::R::string::test1, &val, MAY_NOT_BE_BAG, 0, &specFlags, NULL);
- EXPECT_GE(block, 0);
+ Res_value val;
+ uint32_t specFlags = 0;
+ ssize_t block = table.getResource(R::string::test1, &val, MAY_NOT_BE_BAG, 0,
+ &specFlags, NULL);
+ EXPECT_GE(block, 0);
- EXPECT_EQ(static_cast<uint32_t>(0), specFlags);
+ EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), specFlags);
- ASSERT_EQ(NO_ERROR, table.add(split_de_fr_arsc, split_de_fr_arsc_len));
+ ASSERT_EQ(NO_ERROR, table.add(basic_de_fr_contents_.data(),
+ basic_de_fr_contents_.size()));
- uint32_t frSpecFlags = 0;
- block = table.getResource(base::R::string::test1, &val, MAY_NOT_BE_BAG, 0, &frSpecFlags, NULL);
- EXPECT_GE(block, 0);
+ uint32_t frSpecFlags = 0;
+ block = table.getResource(R::string::test1, &val, MAY_NOT_BE_BAG, 0,
+ &frSpecFlags, NULL);
+ ASSERT_GE(block, 0);
- EXPECT_EQ(ResTable_config::CONFIG_LOCALE, frSpecFlags);
+ EXPECT_EQ(static_cast<uint32_t>(ResTable_config::CONFIG_LOCALE | ResTable_typeSpec::SPEC_PUBLIC),
+ frSpecFlags);
}
-TEST(SplitTest, SelectBestDensity) {
- ResTable_config baseConfig;
- memset(&baseConfig, 0, sizeof(baseConfig));
- baseConfig.density = ResTable_config::DENSITY_XHIGH;
- baseConfig.sdkVersion = 21;
+TEST_F(SplitTest, SelectBestDensity) {
+ ResTable_config baseConfig;
+ memset(&baseConfig, 0, sizeof(baseConfig));
+ baseConfig.density = ResTable_config::DENSITY_XHIGH;
+ baseConfig.sdkVersion = 21;
- ResTable table;
- table.setParameters(&baseConfig);
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
- ASSERT_EQ(NO_ERROR, table.add(split_hdpi_v4_arsc, split_hdpi_v4_arsc_len));
+ ResTable table;
+ table.setParameters(&baseConfig);
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
+ ASSERT_EQ(NO_ERROR, table.add(basic_hdpi_contents_.data(),
+ basic_hdpi_contents_.size()));
- EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "hdpi"));
+ EXPECT_TRUE(IsStringEqual(table, R::string::density, "hdpi"));
- ASSERT_EQ(NO_ERROR, table.add(split_xhdpi_v4_arsc, split_xhdpi_v4_arsc_len));
+ ASSERT_EQ(NO_ERROR, table.add(basic_xhdpi_contents_.data(),
+ basic_xhdpi_contents_.size()));
- EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "xhdpi"));
+ EXPECT_TRUE(IsStringEqual(table, R::string::density, "xhdpi"));
- ASSERT_EQ(NO_ERROR, table.add(split_xxhdpi_v4_arsc, split_xxhdpi_v4_arsc_len));
+ ASSERT_EQ(NO_ERROR, table.add(basic_xxhdpi_contents_.data(),
+ basic_xxhdpi_contents_.size()));
- EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "xhdpi"));
+ EXPECT_TRUE(IsStringEqual(table, R::string::density, "xhdpi"));
- baseConfig.density = ResTable_config::DENSITY_XXHIGH;
- table.setParameters(&baseConfig);
+ baseConfig.density = ResTable_config::DENSITY_XXHIGH;
+ table.setParameters(&baseConfig);
- EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "xxhdpi"));
+ EXPECT_TRUE(IsStringEqual(table, R::string::density, "xxhdpi"));
}
-TEST(SplitFeatureTest, TestNewResourceIsAccessible) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST_F(SplitTest, TestNewResourceIsAccessible) {
+ ResTable table;
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
- Res_value val;
- ssize_t block = table.getResource(base::R::string::test3, &val, MAY_NOT_BE_BAG);
- EXPECT_LT(block, 0);
+ Res_value val;
+ ssize_t block = table.getResource(R::string::test3, &val, MAY_NOT_BE_BAG);
+ EXPECT_LT(block, 0);
- ASSERT_EQ(NO_ERROR, table.add(feature_arsc, feature_arsc_len));
+ ASSERT_EQ(NO_ERROR,
+ table.add(feature_contents_.data(), feature_contents_.size()));
- block = table.getResource(base::R::string::test3, &val, MAY_NOT_BE_BAG);
- EXPECT_GE(block, 0);
+ block = table.getResource(R::string::test3, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
- EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
+ EXPECT_EQ(Res_value::TYPE_STRING, val.dataType);
}
-TEST(SplitFeatureTest, TestNewResourceNameHasCorrectName) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+TEST_F(SplitTest, TestNewResourceNameHasCorrectName) {
+ ResTable table;
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
- ResTable::resource_name name;
- EXPECT_FALSE(table.getResourceName(base::R::string::test3, false, &name));
+ ResTable::resource_name name;
+ EXPECT_FALSE(table.getResourceName(R::string::test3, false, &name));
- ASSERT_EQ(NO_ERROR, table.add(feature_arsc, feature_arsc_len));
+ ASSERT_EQ(NO_ERROR,
+ table.add(feature_contents_.data(), feature_contents_.size()));
- ASSERT_TRUE(table.getResourceName(base::R::string::test3, false, &name));
+ ASSERT_TRUE(table.getResourceName(R::string::test3, false, &name));
- EXPECT_EQ(String16("com.android.test.basic"),
+ EXPECT_EQ(String16("com.android.basic"),
String16(name.package, name.packageLen));
- EXPECT_EQ(String16("string"),
- String16(name.type, name.typeLen));
+ EXPECT_EQ(String16("string"), String16(name.type, name.typeLen));
- EXPECT_EQ(String16("test3"),
- String16(name.name, name.nameLen));
+ EXPECT_EQ(String16("test3"), String16(name.name, name.nameLen));
}
-TEST(SplitFeatureTest, TestNewResourceIsAccessibleByName) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
- ASSERT_EQ(NO_ERROR, table.add(feature_arsc, feature_arsc_len));
+TEST_F(SplitTest, TestNewResourceIsAccessibleByName) {
+ ResTable table;
+ ASSERT_EQ(NO_ERROR,
+ table.add(basic_contents_.data(), basic_contents_.size()));
+ ASSERT_EQ(NO_ERROR,
+ table.add(feature_contents_.data(), feature_contents_.size()));
- const String16 name("test3");
- const String16 type("string");
- const String16 package("com.android.test.basic");
- ASSERT_EQ(base::R::string::test3, table.identifierForName(name.string(), name.size(),
- type.string(), type.size(),
- package.string(), package.size()));
+ const String16 name("test3");
+ const String16 type("string");
+ const String16 package("com.android.basic");
+ ASSERT_EQ(
+ R::string::test3,
+ table.identifierForName(name.string(), name.size(), type.string(),
+ type.size(), package.string(), package.size()));
}
-} // namespace
+} // namespace
diff --git a/libs/androidfw/tests/TestHelpers.cpp b/libs/androidfw/tests/TestHelpers.cpp
index 702ee5c..2c834b1 100644
--- a/libs/androidfw/tests/TestHelpers.cpp
+++ b/libs/androidfw/tests/TestHelpers.cpp
@@ -19,6 +19,7 @@
#include <unistd.h>
#include "android-base/logging.h"
+#include "ziparchive/zip_archive.h"
namespace android {
@@ -31,8 +32,41 @@
return sTestDataPath;
}
-::testing::AssertionResult IsStringEqual(const ResTable& table,
- uint32_t resource_id,
+::testing::AssertionResult ReadFileFromZipToString(const std::string& zip_path,
+ const std::string& file,
+ std::string* out_contents) {
+ out_contents->clear();
+ ::ZipArchiveHandle handle;
+ int32_t result = OpenArchive(zip_path.c_str(), &handle);
+ if (result != 0) {
+ return ::testing::AssertionFailure() << "Failed to open zip '" << zip_path
+ << "': " << ::ErrorCodeString(result);
+ }
+
+ ::ZipString name(file.c_str());
+ ::ZipEntry entry;
+ result = ::FindEntry(handle, name, &entry);
+ if (result != 0) {
+ ::CloseArchive(handle);
+ return ::testing::AssertionFailure() << "Could not find file '" << file << "' in zip '"
+ << zip_path << "' : " << ::ErrorCodeString(result);
+ }
+
+ out_contents->resize(entry.uncompressed_length);
+ result = ::ExtractToMemory(
+ handle, &entry, const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(out_contents->data())),
+ out_contents->size());
+ if (result != 0) {
+ ::CloseArchive(handle);
+ return ::testing::AssertionFailure() << "Failed to extract file '" << file << "' from zip '"
+ << zip_path << "': " << ::ErrorCodeString(result);
+ }
+
+ ::CloseArchive(handle);
+ return ::testing::AssertionSuccess();
+}
+
+::testing::AssertionResult IsStringEqual(const ResTable& table, uint32_t resource_id,
const char* expected_str) {
Res_value val;
ssize_t block = table.getResource(resource_id, &val, MAY_NOT_BE_BAG);
@@ -46,8 +80,7 @@
const ResStringPool* pool = table.getTableStringBlock(block);
if (pool == NULL) {
- return ::testing::AssertionFailure()
- << "table has no string pool for block " << block;
+ return ::testing::AssertionFailure() << "table has no string pool for block " << block;
}
const String8 actual_str = pool->string8ObjectAt(val.data);
diff --git a/libs/androidfw/tests/TestHelpers.h b/libs/androidfw/tests/TestHelpers.h
index c1e349f..d9cee22 100644
--- a/libs/androidfw/tests/TestHelpers.h
+++ b/libs/androidfw/tests/TestHelpers.h
@@ -25,13 +25,11 @@
#include "utils/String16.h"
#include "utils/String8.h"
-static inline ::std::ostream& operator<<(::std::ostream& out,
- const android::String8& str) {
+static inline ::std::ostream& operator<<(::std::ostream& out, const android::String8& str) {
return out << str.string();
}
-static inline ::std::ostream& operator<<(::std::ostream& out,
- const android::String16& str) {
+static inline ::std::ostream& operator<<(::std::ostream& out, const android::String16& str) {
return out << android::String8(str).string();
}
@@ -43,18 +41,19 @@
const std::string& GetTestDataPath();
-static inline bool operator==(const ResTable_config& a,
- const ResTable_config& b) {
+::testing::AssertionResult ReadFileFromZipToString(const std::string& zip_path,
+ const std::string& file,
+ std::string* out_contents);
+
+static inline bool operator==(const ResTable_config& a, const ResTable_config& b) {
return a.compare(b) == 0;
}
-static inline ::std::ostream& operator<<(::std::ostream& out,
- const ResTable_config& c) {
+static inline ::std::ostream& operator<<(::std::ostream& out, const ResTable_config& c) {
return out << c.toString().string();
}
-::testing::AssertionResult IsStringEqual(const ResTable& table,
- uint32_t resource_id,
+::testing::AssertionResult IsStringEqual(const ResTable& table, uint32_t resource_id,
const char* expected_str);
} // namespace android
diff --git a/libs/androidfw/tests/Theme_test.cpp b/libs/androidfw/tests/Theme_test.cpp
index 4d07130..3774657 100644
--- a/libs/androidfw/tests/Theme_test.cpp
+++ b/libs/androidfw/tests/Theme_test.cpp
@@ -14,55 +14,59 @@
* limitations under the License.
*/
-#include <androidfw/ResourceTypes.h>
+#include "androidfw/ResourceTypes.h"
-#include <utils/String8.h>
-#include <utils/String16.h>
+#include "utils/String16.h"
+#include "utils/String8.h"
+
#include "TestHelpers.h"
-#include "data/system/R.h"
#include "data/app/R.h"
+#include "data/system/R.h"
-#include <gtest/gtest.h>
+namespace app = com::android::app;
-using namespace android;
-
-namespace {
-
-#include "data/system/system_arsc.h"
-#include "data/app/app_arsc.h"
-
-enum { MAY_NOT_BE_BAG = false };
+namespace android {
/**
* TODO(adamlesinski): Enable when fixed.
*/
TEST(ThemeTest, DISABLED_shouldCopyThemeFromDifferentResTable) {
- ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(system_arsc, system_arsc_len));
- ASSERT_EQ(NO_ERROR, table.add(app_arsc, app_arsc_len));
+ ResTable table;
- ResTable::Theme theme1(table);
- ASSERT_EQ(NO_ERROR, theme1.applyStyle(app::R::style::Theme_One));
- Res_value val;
- ASSERT_GE(theme1.getAttribute(android::R::attr::background, &val), 0);
- ASSERT_EQ(Res_value::TYPE_INT_COLOR_RGB8, val.dataType);
- ASSERT_EQ(uint32_t(0xffff0000), val.data);
- ASSERT_GE(theme1.getAttribute(app::R::attr::number, &val), 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(1), val.data);
+ std::string system_contents;
+ ASSERT_TRUE(ReadFileFromZipToString("/system/system.apk", "resources.arsc",
+ &system_contents));
+ ASSERT_EQ(NO_ERROR,
+ table.add(system_contents.data(), system_contents.size()));
- ResTable table2;
- ASSERT_EQ(NO_ERROR, table2.add(system_arsc, system_arsc_len));
- ASSERT_EQ(NO_ERROR, table2.add(app_arsc, app_arsc_len));
+ std::string app_contents;
+ ASSERT_TRUE(ReadFileFromZipToString("/basic/basic.apk", "resources.arsc",
+ &app_contents));
+ ASSERT_EQ(NO_ERROR, table.add(app_contents.data(), app_contents.size()));
- ResTable::Theme theme2(table2);
- ASSERT_EQ(NO_ERROR, theme2.setTo(theme1));
- ASSERT_GE(theme2.getAttribute(android::R::attr::background, &val), 0);
- ASSERT_EQ(Res_value::TYPE_INT_COLOR_RGB8, val.dataType);
- ASSERT_EQ(uint32_t(0xffff0000), val.data);
- ASSERT_GE(theme2.getAttribute(app::R::attr::number, &val), 0);
- ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
- ASSERT_EQ(uint32_t(1), val.data);
+ ResTable::Theme theme1(table);
+ ASSERT_EQ(NO_ERROR, theme1.applyStyle(app::R::style::Theme_One));
+ Res_value val;
+ ASSERT_GE(theme1.getAttribute(android::R::attr::background, &val), 0);
+ ASSERT_EQ(Res_value::TYPE_INT_COLOR_RGB8, val.dataType);
+ ASSERT_EQ(uint32_t(0xffff0000), val.data);
+ ASSERT_GE(theme1.getAttribute(app::R::attr::number, &val), 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(1), val.data);
+
+ ResTable table2;
+ ASSERT_EQ(NO_ERROR,
+ table2.add(system_contents.data(), system_contents.size()));
+ ASSERT_EQ(NO_ERROR, table2.add(app_contents.data(), app_contents.size()));
+
+ ResTable::Theme theme2(table2);
+ ASSERT_EQ(NO_ERROR, theme2.setTo(theme1));
+ ASSERT_GE(theme2.getAttribute(android::R::attr::background, &val), 0);
+ ASSERT_EQ(Res_value::TYPE_INT_COLOR_RGB8, val.dataType);
+ ASSERT_EQ(uint32_t(0xffff0000), val.data);
+ ASSERT_GE(theme2.getAttribute(app::R::attr::number, &val), 0);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+ ASSERT_EQ(uint32_t(1), val.data);
}
-}
+} // namespace android
diff --git a/libs/androidfw/tests/data/app/R.h b/libs/androidfw/tests/data/app/R.h
index 23e68e3..5be2eee 100644
--- a/libs/androidfw/tests/data/app/R.h
+++ b/libs/androidfw/tests/data/app/R.h
@@ -14,25 +14,31 @@
* limitations under the License.
*/
-#ifndef __APP_R_H
-#define __APP_R_H
+#ifndef TEST_DATA_APP_R_H_
+#define TEST_DATA_APP_R_H_
+#include <cstdint>
+
+namespace com {
+namespace android {
namespace app {
-namespace R {
-namespace attr {
- enum {
- number = 0x7f010000, // default
+struct R {
+ struct attr {
+ enum : uint32_t {
+ number = 0x7f010000, // default
};
-}
+ };
-namespace style {
- enum {
- Theme_One = 0x7f020000, // default
+ struct style {
+ enum : uint32_t {
+ Theme_One = 0x7f020000, // default
};
-}
+ };
+};
-} // namespace R
-} // namespace app
+} // namespace app
+} // namespace android
+} // namespace com
-#endif // __APP_R_H
+#endif // TEST_DATA_APP_R_H_
diff --git a/libs/androidfw/tests/data/app/app.apk b/libs/androidfw/tests/data/app/app.apk
new file mode 100644
index 0000000..ccb0824
--- /dev/null
+++ b/libs/androidfw/tests/data/app/app.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/app/app_arsc.h b/libs/androidfw/tests/data/app/app_arsc.h
deleted file mode 100644
index d5d9a3b..0000000
--- a/libs/androidfw/tests/data/app/app_arsc.h
+++ /dev/null
@@ -1,62 +0,0 @@
-unsigned char app_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0xc4, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x9c, 0x02, 0x00, 0x00,
- 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
- 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
- 0x64, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00,
- 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6e, 0x00,
- 0x75, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00,
- 0x2e, 0x00, 0x4f, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00
-};
-unsigned int app_arsc_len = 708;
diff --git a/libs/androidfw/tests/data/app/build b/libs/androidfw/tests/data/app/build
index 62257bc..d418158 100755
--- a/libs/androidfw/tests/data/app/build
+++ b/libs/androidfw/tests/data/app/build
@@ -15,7 +15,6 @@
# limitations under the License.
#
-aapt package -v -I ../system/bundle.apk -M AndroidManifest.xml -S res -F bundle.apk -f && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc app.arsc && \
-xxd -i app.arsc > app_arsc.h
+set -e
+
+aapt package -I ../system/system.apk -M AndroidManifest.xml -S res -F app.apk -f
diff --git a/libs/androidfw/tests/data/appaslib/R.h b/libs/androidfw/tests/data/appaslib/R.h
index 3af921a..5a21327 100644
--- a/libs/androidfw/tests/data/appaslib/R.h
+++ b/libs/androidfw/tests/data/appaslib/R.h
@@ -14,39 +14,53 @@
* limitations under the License.
*/
-#ifndef __APPASLIB_R_H
-#define __APPASLIB_R_H
+#ifndef DATA_APPASLIB_R_H_
+#define DATA_APPASLIB_R_H_
+#include <cstdint>
+
+namespace com {
+namespace android {
namespace appaslib {
-namespace R {
-namespace lib {
-namespace integer {
- enum {
- number1 = 0x02020000, // default
- };
-}
-namespace array {
- enum {
- integerArray1 = 0x02030000, // default
+namespace lib {
+
+struct R {
+ struct integer {
+ enum : uint32_t {
+ number1 = 0x02020000, // default
};
-}
-} // namespace lib
+ };
+
+ struct array {
+ enum : uint32_t {
+ integerArray1 = 0x02030000, // default
+ };
+ };
+};
+
+} // namespace lib
namespace app {
-namespace integer {
- enum {
- number1 = 0x7f020000, // default
- };
-}
-namespace array {
- enum {
- integerArray1 = 0x7f030000, // default
+struct R {
+ struct integer {
+ enum : uint32_t {
+ number1 = 0x7f020000, // default
};
-}
-} // namespace app
-} // namespace R
-} // namespace appaslib
+ };
-#endif // __APPASLIB_R_H
+ struct array {
+ enum : uint32_t {
+ integerArray1 = 0x7f030000, // default
+ };
+ };
+};
+
+} // namespace app
+
+} // namespace appaslib
+} // namespace android
+} // namespace com
+
+#endif // DATA_APPASLIB_R_H_
diff --git a/libs/androidfw/tests/data/appaslib/appaslib.apk b/libs/androidfw/tests/data/appaslib/appaslib.apk
new file mode 100644
index 0000000..6ebd823
--- /dev/null
+++ b/libs/androidfw/tests/data/appaslib/appaslib.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/appaslib/appaslib_arsc.h b/libs/androidfw/tests/data/appaslib/appaslib_arsc.h
deleted file mode 100644
index be176ab..0000000
--- a/libs/androidfw/tests/data/appaslib/appaslib_arsc.h
+++ /dev/null
@@ -1,68 +0,0 @@
-unsigned char appaslib_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x04, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xdc, 0x02, 0x00, 0x00,
- 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
- 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
- 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
- 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00,
- 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00,
- 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x12, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00,
- 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0d, 0x00,
- 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00,
- 0x72, 0x00, 0x41, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x48, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x7f,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x48, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x03, 0x00, 0x00, 0x00
-};
-unsigned int appaslib_arsc_len = 772;
diff --git a/libs/androidfw/tests/data/appaslib/appaslib_lib.apk b/libs/androidfw/tests/data/appaslib/appaslib_lib.apk
new file mode 100644
index 0000000..ee1521c
--- /dev/null
+++ b/libs/androidfw/tests/data/appaslib/appaslib_lib.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/appaslib/appaslib_lib_arsc.h b/libs/androidfw/tests/data/appaslib/appaslib_lib_arsc.h
deleted file mode 100644
index 099285a..0000000
--- a/libs/androidfw/tests/data/appaslib/appaslib_lib_arsc.h
+++ /dev/null
@@ -1,68 +0,0 @@
-unsigned char appaslib_lib_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x04, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xdc, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
- 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
- 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
- 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00,
- 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00,
- 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x12, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00,
- 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0d, 0x00,
- 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00,
- 0x72, 0x00, 0x41, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x48, 0x00, 0x5c, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x48, 0x00,
- 0x80, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x03, 0x00, 0x00, 0x00
-};
-unsigned int appaslib_lib_arsc_len = 772;
diff --git a/libs/androidfw/tests/data/appaslib/build b/libs/androidfw/tests/data/appaslib/build
index e4bd88b..baaf700 100755
--- a/libs/androidfw/tests/data/appaslib/build
+++ b/libs/androidfw/tests/data/appaslib/build
@@ -15,14 +15,9 @@
# limitations under the License.
#
+set -e
+
PATH_TO_FRAMEWORK_RES=$(gettop)/prebuilts/sdk/current/android.jar
-aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES -F bundle.apk -f && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc appaslib.arsc && \
-xxd -i appaslib.arsc > appaslib_arsc.h && \
-aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES -F bundle.apk -f --shared-lib && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc appaslib_lib.arsc && \
-xxd -i appaslib_lib.arsc > appaslib_lib_arsc.h \
-
+aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES -F appaslib.apk -f
+aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES -F appaslib_lib.apk -f --shared-lib
diff --git a/libs/androidfw/tests/data/basic/AndroidManifest.xml b/libs/androidfw/tests/data/basic/AndroidManifest.xml
index a56ac18..b117882 100644
--- a/libs/androidfw/tests/data/basic/AndroidManifest.xml
+++ b/libs/androidfw/tests/data/basic/AndroidManifest.xml
@@ -15,7 +15,6 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.test.basic">
- <application>
- </application>
+ package="com.android.basic">
+ <application />
</manifest>
diff --git a/libs/androidfw/tests/data/basic/R.h b/libs/androidfw/tests/data/basic/R.h
index 6694dd0..9352b5c 100644
--- a/libs/androidfw/tests/data/basic/R.h
+++ b/libs/androidfw/tests/data/basic/R.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,59 +14,67 @@
* limitations under the License.
*/
-#ifndef __BASE_R_H
-#define __BASE_R_H
+#ifndef TESTS_DATA_BASIC_R_H_
+#define TESTS_DATA_BASIC_R_H_
-namespace base {
-namespace R {
+#include <cstdint>
-namespace attr {
- enum {
- attr1 = 0x7f010000, // default
- attr2 = 0x7f010001, // default
+namespace com {
+namespace android {
+namespace basic {
+
+struct R {
+ struct attr {
+ enum : uint32_t {
+ attr1 = 0x7f010000,
+ attr2 = 0x7f010001,
};
-}
+ };
-namespace layout {
- enum {
- main = 0x7f020000, // default, fr-sw600dp-v13
+ struct layout {
+ enum : uint32_t {
+ main = 0x7f020000,
};
-}
+ };
-namespace string {
- enum {
- test1 = 0x7f030000, // default
- test2 = 0x7f030001, // default
- density = 0x7f030002, // default
+ struct string {
+ enum : uint32_t {
+ test1 = 0x7f030000,
+ test2 = 0x7f030001,
+ density = 0x7f030002,
- test3 = 0x7f080000, // default (in feature)
- test4 = 0x7f080001, // default (in feature)
+ // From feature
+ test3 = 0x7f080000,
+ test4 = 0x7f080001,
};
-}
+ };
-namespace integer {
- enum {
- number1 = 0x7f040000, // default, sv, vs
- number2 = 0x7f040001, // default
+ struct integer {
+ enum : uint32_t {
+ number1 = 0x7f040000,
+ number2 = 0x7f040001,
- test3 = 0x7f090000, // default (in feature)
+ // From feature
+ number3 = 0x7f090000,
};
-}
+ };
-namespace style {
- enum {
- Theme1 = 0x7f050000, // default
- Theme2 = 0x7f050001, // default
+ struct style {
+ enum : uint32_t {
+ Theme1 = 0x7f050000,
+ Theme2 = 0x7f050001,
};
-}
+ };
-namespace array {
- enum {
- integerArray1 = 0x7f060000, // default
+ struct array {
+ enum : uint32_t {
+ integerArray1 = 0x7f060000,
};
-}
+ };
+};
-} // namespace R
-} // namespace base
+} // namespace basic
+} // namespace android
+} // namespace com
-#endif // __BASE_R_H
+#endif /* TESTS_DATA_BASIC_R_H_ */
diff --git a/libs/androidfw/tests/data/basic/basic.apk b/libs/androidfw/tests/data/basic/basic.apk
new file mode 100644
index 0000000..2c9771b
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/basic.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/basic_arsc.h b/libs/androidfw/tests/data/basic/basic_arsc.h
deleted file mode 100644
index e497401..0000000
--- a/libs/androidfw/tests/data/basic/basic_arsc.h
+++ /dev/null
@@ -1,175 +0,0 @@
-unsigned char basic_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x13, 0x00, 0x72, 0x00,
- 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x2f, 0x00, 0x6d, 0x00, 0x61, 0x00,
- 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x78, 0x00, 0x6d, 0x00, 0x6c, 0x00,
- 0x00, 0x00, 0x22, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00,
- 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00,
- 0x2d, 0x00, 0x66, 0x00, 0x72, 0x00, 0x2d, 0x00, 0x73, 0x00, 0x77, 0x00,
- 0x36, 0x00, 0x30, 0x00, 0x30, 0x00, 0x64, 0x00, 0x70, 0x00, 0x2d, 0x00,
- 0x76, 0x00, 0x31, 0x00, 0x33, 0x00, 0x2f, 0x00, 0x6d, 0x00, 0x61, 0x00,
- 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x78, 0x00, 0x6d, 0x00, 0x6c, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01,
- 0x44, 0x07, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
- 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
- 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00,
- 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00,
- 0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x20, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
- 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00, 0x6f, 0x00, 0x75, 0x00,
- 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00,
- 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00,
- 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00,
- 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00,
- 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
- 0xec, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
- 0x56, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
- 0x88, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
- 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x74, 0x00,
- 0x74, 0x00, 0x72, 0x00, 0x32, 0x00, 0x00, 0x00, 0x04, 0x00, 0x6d, 0x00,
- 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00,
- 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00,
- 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x32, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00,
- 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00, 0x75, 0x00,
- 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x32, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x06, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00,
- 0x6d, 0x00, 0x65, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x69, 0x00,
- 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
- 0x41, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x31, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x8c, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x08, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x04, 0x24, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
- 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
- 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x66, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x4c, 0x00, 0x78, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x4c, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
- 0xc8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x7f, 0x01, 0x02, 0x4c, 0x00,
- 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x54, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x76, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x58, 0x02, 0x00, 0x00,
- 0x01, 0x02, 0x4c, 0x00, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x73, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
- 0x90, 0x01, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x98, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7f,
- 0x08, 0x00, 0x00, 0x10, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f,
- 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x7f, 0x10, 0x00, 0x01, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x7f, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, 0x2c, 0x01, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
- 0x84, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
- 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02,
- 0x08, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02,
- 0x08, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x00
-};
-unsigned int basic_arsc_len = 2060;
diff --git a/libs/androidfw/tests/data/basic/basic_de_fr.apk b/libs/androidfw/tests/data/basic/basic_de_fr.apk
new file mode 100644
index 0000000..0481444
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/basic_de_fr.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/basic_hdpi-v4.apk b/libs/androidfw/tests/data/basic/basic_hdpi-v4.apk
new file mode 100644
index 0000000..a8d06e7
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/basic_hdpi-v4.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/basic_xhdpi-v4.apk b/libs/androidfw/tests/data/basic/basic_xhdpi-v4.apk
new file mode 100644
index 0000000..d1dfb14
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/basic_xhdpi-v4.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/basic_xxhdpi-v4.apk b/libs/androidfw/tests/data/basic/basic_xxhdpi-v4.apk
new file mode 100644
index 0000000..dca6f2f
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/basic_xxhdpi-v4.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/build b/libs/androidfw/tests/data/basic/build
index fd289fa..af0fd87 100755
--- a/libs/androidfw/tests/data/basic/build
+++ b/libs/androidfw/tests/data/basic/build
@@ -15,25 +15,8 @@
# limitations under the License.
#
-PATH_TO_FRAMEWORK_RES=$(gettop)/prebuilts/sdk/current/android.jar
+set -e
-aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES --split hdpi --split xhdpi --split xxhdpi --split fr,de -F bundle.apk -f && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc basic.arsc && \
-xxd -i basic.arsc > basic_arsc.h && \
-\
-unzip bundle_de_fr.apk resources.arsc && \
-mv resources.arsc split_de_fr.arsc && \
-xxd -i split_de_fr.arsc > split_de_fr_arsc.h && \
-\
-unzip bundle_hdpi-v4.apk resources.arsc && \
-mv resources.arsc split_hdpi_v4.arsc && \
-xxd -i split_hdpi_v4.arsc > split_hdpi_v4_arsc.h && \
-\
-unzip bundle_xhdpi-v4.apk resources.arsc && \
-mv resources.arsc split_xhdpi_v4.arsc && \
-xxd -i split_xhdpi_v4.arsc > split_xhdpi_v4_arsc.h && \
-\
-unzip bundle_xxhdpi-v4.apk resources.arsc && \
-mv resources.arsc split_xxhdpi_v4.arsc && \
-xxd -i split_xxhdpi_v4.arsc > split_xxhdpi_v4_arsc.h \
+PATH_TO_FRAMEWORK_RES=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/android.jar
+
+aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES --split hdpi --split xhdpi --split xxhdpi --split fr,de -F basic.apk -f
diff --git a/libs/androidfw/tests/data/basic/res/values/values.xml b/libs/androidfw/tests/data/basic/res/values/values.xml
index a010cca..11f6b8a 100644
--- a/libs/androidfw/tests/data/basic/res/values/values.xml
+++ b/libs/androidfw/tests/data/basic/res/values/values.xml
@@ -15,24 +15,40 @@
-->
<resources>
+ <public type="attr" name="attr1" id="0x7f010000" />
<attr name="attr1" format="reference|integer" />
+
+ <public type="attr" name="attr2" id="0x7f010001" />
<attr name="attr2" format="reference|integer" />
+ <public type="layout" name="main" id="0x7f020000" />
+
+ <public type="string" name="test1" id="0x7f030000" />
<string name="test1">test1</string>
+
+ <public type="string" name="test2" id="0x7f030001" />
<string name="test2">test2</string>
+ <public type="string" name="density" id="0x7f030002" />
+
+ <public type="integer" name="number1" id="0x7f040000" />
<integer name="number1">200</integer>
+
+ <public type="integer" name="number2" id="0x7f040001" />
<integer name="number2">@array/integerArray1</integer>
+ <public type="style" name="Theme1" id="0x7f050000" />
<style name="Theme1">
- <item name="com.android.test.basic:attr1">100</item>
- <item name="com.android.test.basic:attr2">@integer/number1</item>
+ <item name="com.android.basic:attr1">100</item>
+ <item name="com.android.basic:attr2">@integer/number1</item>
</style>
- <style name="Theme2" parent="@com.android.test.basic:style/Theme1">
- <item name="com.android.test.basic:attr1">300</item>
+ <public type="style" name="Theme2" id="0x7f050001" />
+ <style name="Theme2" parent="@com.android.basic:style/Theme1">
+ <item name="com.android.basic:attr1">300</item>
</style>
+ <public type="array" name="integerArray1" id="0x7f060000" />
<integer-array name="integerArray1">
<item>1</item>
<item>2</item>
diff --git a/libs/androidfw/tests/data/basic/split_de_fr_arsc.h b/libs/androidfw/tests/data/basic/split_de_fr_arsc.h
deleted file mode 100644
index a2aa598..0000000
--- a/libs/androidfw/tests/data/basic/split_de_fr_arsc.h
+++ /dev/null
@@ -1,88 +0,0 @@
-unsigned char split_de_fr_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0xf4, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x76, 0x00,
- 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x75, 0x00, 0x63, 0x00, 0x68, 0x00,
- 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x09, 0x00, 0x76, 0x00, 0x65, 0x00,
- 0x72, 0x00, 0x73, 0x00, 0x75, 0x00, 0x63, 0x00, 0x68, 0x00, 0x20, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x07, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00,
- 0x61, 0x00, 0x69, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00,
- 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x20, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x6c, 0x03, 0x00, 0x00,
- 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
- 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
- 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x90, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
- 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6c, 0x00,
- 0x61, 0x00, 0x79, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00,
- 0x67, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00,
- 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00,
- 0x73, 0x00, 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00,
- 0x73, 0x00, 0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
- 0x78, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
- 0x78, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x66, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
- 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-unsigned int split_de_fr_arsc_len = 1012;
diff --git a/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h
deleted file mode 100644
index 0cc3915..0000000
--- a/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h
+++ /dev/null
@@ -1,69 +0,0 @@
-unsigned char split_hdpi_v4_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x10, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x68, 0x00,
- 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01,
- 0xd8, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
- 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
- 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00,
- 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00,
- 0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x20, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
- 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00, 0x6f, 0x00, 0x75, 0x00,
- 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00,
- 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00,
- 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00,
- 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00,
- 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00,
- 0x73, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x4c, 0x00, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-unsigned int split_hdpi_v4_arsc_len = 784;
diff --git a/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h
deleted file mode 100644
index d44ba96..0000000
--- a/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h
+++ /dev/null
@@ -1,69 +0,0 @@
-unsigned char split_xhdpi_v4_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x14, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x78, 0x00,
- 0x68, 0x00, 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x20, 0x01, 0xd8, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
- 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00,
- 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00,
- 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00,
- 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xb0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00,
- 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00,
- 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x64, 0x00,
- 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x68, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-unsigned int split_xhdpi_v4_arsc_len = 788;
diff --git a/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h
deleted file mode 100644
index 2f3f682..0000000
--- a/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h
+++ /dev/null
@@ -1,69 +0,0 @@
-unsigned char split_xxhdpi_v4_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x14, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x78, 0x00,
- 0x78, 0x00, 0x68, 0x00, 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x20, 0x01, 0xd8, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
- 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00,
- 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00,
- 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00,
- 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0xb0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00,
- 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00,
- 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x64, 0x00,
- 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x68, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-unsigned int split_xxhdpi_v4_arsc_len = 788;
diff --git a/libs/androidfw/tests/data/feature/AndroidManifest.xml b/libs/androidfw/tests/data/feature/AndroidManifest.xml
index c2343b7..c972372 100644
--- a/libs/androidfw/tests/data/feature/AndroidManifest.xml
+++ b/libs/androidfw/tests/data/feature/AndroidManifest.xml
@@ -15,5 +15,5 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.test.basic">
+ package="com.android.basic">
</manifest>
diff --git a/libs/androidfw/tests/data/feature/build b/libs/androidfw/tests/data/feature/build
index 0f3307f..6ed3e41 100755
--- a/libs/androidfw/tests/data/feature/build
+++ b/libs/androidfw/tests/data/feature/build
@@ -15,7 +15,8 @@
# limitations under the License.
#
-aapt package -M AndroidManifest.xml -S res --feature-of ../basic/bundle.apk -F bundle.apk -f && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc feature.arsc && \
-xxd -i feature.arsc > feature_arsc.h
+set -e
+
+PATH_TO_FRAMEWORK_RES=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/android.jar
+
+aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES --feature-of ../basic/basic.apk -F feature.apk -f
diff --git a/libs/androidfw/tests/data/feature/feature.apk b/libs/androidfw/tests/data/feature/feature.apk
new file mode 100644
index 0000000..04940fb
--- /dev/null
+++ b/libs/androidfw/tests/data/feature/feature.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/feature/feature_arsc.h b/libs/androidfw/tests/data/feature/feature_arsc.h
deleted file mode 100644
index cd29910..0000000
--- a/libs/androidfw/tests/data/feature/feature_arsc.h
+++ /dev/null
@@ -1,73 +0,0 @@
-unsigned char feature_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x44, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x33, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xf8, 0x02, 0x00, 0x00,
- 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
- 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
- 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
- 0x1e, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x3c, 0x00,
- 0x65, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x74, 0x00, 0x79, 0x00, 0x3e, 0x00,
- 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
- 0x00, 0x00, 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00,
- 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00,
- 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x58, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x33, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00,
- 0x73, 0x00, 0x74, 0x00, 0x34, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00,
- 0x75, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x33, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
- 0x6c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
- 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x10, 0xc8, 0x00, 0x00, 0x00
-};
-unsigned int feature_arsc_len = 836;
diff --git a/libs/androidfw/tests/data/feature/res/values/values.xml b/libs/androidfw/tests/data/feature/res/values/values.xml
index 343fd6c..59f7d93 100644
--- a/libs/androidfw/tests/data/feature/res/values/values.xml
+++ b/libs/androidfw/tests/data/feature/res/values/values.xml
@@ -15,8 +15,13 @@
-->
<resources>
+ <!-- Features are offset, so 7f020000 will become 7f080000 at runtime. -->
+ <public type="string" name="test3" id="0x7f020000" />
<string name="test3">test3</string>
+
+ <public type="string" name="test4" id="0x7f020001" />
<string name="test4">test4</string>
+ <public type="integer" name="number3" id="0x7f030000" />
<integer name="number3">200</integer>
</resources>
diff --git a/libs/androidfw/tests/data/lib/AndroidManifest.xml b/libs/androidfw/tests/data/lib/AndroidManifest.xml
index a56ac18..02f5d3e 100644
--- a/libs/androidfw/tests/data/lib/AndroidManifest.xml
+++ b/libs/androidfw/tests/data/lib/AndroidManifest.xml
@@ -15,7 +15,6 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.test.basic">
- <application>
- </application>
+ package="com.android.lib">
+ <application />
</manifest>
diff --git a/libs/androidfw/tests/data/lib/R.h b/libs/androidfw/tests/data/lib/R.h
index 6013973..bb22d22 100644
--- a/libs/androidfw/tests/data/lib/R.h
+++ b/libs/androidfw/tests/data/lib/R.h
@@ -14,26 +14,32 @@
* limitations under the License.
*/
-#ifndef __LIB_R_H
-#define __LIB_R_H
+#ifndef TEST_DATA_LIB_R_H_
+#define TEST_DATA_LIB_R_H_
+#include <cstdint>
+
+namespace com {
+namespace android {
namespace lib {
-namespace R {
-namespace attr {
- enum {
- attr1 = 0x02010000, // default
- attr2 = 0x02010001, // default
+struct R {
+ struct attr {
+ enum : uint32_t {
+ attr1 = 0x02010000, // default
+ attr2 = 0x02010001, // default
};
-}
+ };
-namespace style {
- enum {
- Theme = 0x02020000, // default
+ struct style {
+ enum : uint32_t {
+ Theme = 0x02020000, // default
};
-}
+ };
+};
-} // namespace R
-} // namespace lib
+} // namespace lib
+} // namespace android
+} // namespace com
-#endif // __LIB_R_H
+#endif // TEST_DATA_R_H_
diff --git a/libs/androidfw/tests/data/lib/build b/libs/androidfw/tests/data/lib/build
index 4102903..5c3d02c 100755
--- a/libs/androidfw/tests/data/lib/build
+++ b/libs/androidfw/tests/data/lib/build
@@ -15,7 +15,6 @@
# limitations under the License.
#
-aapt package -M AndroidManifest.xml -S res -F bundle.apk -f --shared-lib && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc lib.arsc && \
-xxd -i lib.arsc > lib_arsc.h
+set -e
+
+aapt package -M AndroidManifest.xml -S res -F lib.apk -f --shared-lib
diff --git a/libs/androidfw/tests/data/lib/lib.apk b/libs/androidfw/tests/data/lib/lib.apk
new file mode 100644
index 0000000..44c27c7
--- /dev/null
+++ b/libs/androidfw/tests/data/lib/lib.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/lib/lib_arsc.h b/libs/androidfw/tests/data/lib/lib_arsc.h
deleted file mode 100644
index 62bed65..0000000
--- a/libs/androidfw/tests/data/lib/lib_arsc.h
+++ /dev/null
@@ -1,68 +0,0 @@
-unsigned char lib_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xe4, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
- 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
- 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
- 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00,
- 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
- 0x54, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
- 0x32, 0x00, 0x00, 0x00, 0x05, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00,
- 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
- 0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x54, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
- 0x04, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x4c, 0x00, 0x78, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x10, 0xbc, 0x02, 0x00, 0x00,
- 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00
-};
-unsigned int lib_arsc_len = 780;
diff --git a/libs/androidfw/tests/data/lib/res/values/values.xml b/libs/androidfw/tests/data/lib/res/values/values.xml
index ec8117a7..51e3a40 100644
--- a/libs/androidfw/tests/data/lib/res/values/values.xml
+++ b/libs/androidfw/tests/data/lib/res/values/values.xml
@@ -19,7 +19,7 @@
<attr name="attr2" format="integer" />
<style name="Theme">
- <item name="com.android.test.basic:attr1">700</item>
- <item name="com.android.test.basic:attr2">?com.android.test.basic:attr1</item>
+ <item name="com.android.lib:attr1">700</item>
+ <item name="com.android.lib:attr2">?com.android.lib:attr1</item>
</style>
</resources>
diff --git a/libs/androidfw/tests/data/overlay/build b/libs/androidfw/tests/data/overlay/build
index f737677..112f373 100755
--- a/libs/androidfw/tests/data/overlay/build
+++ b/libs/androidfw/tests/data/overlay/build
@@ -15,7 +15,6 @@
# limitations under the License.
#
-aapt package -M AndroidManifest.xml -S res -F bundle.apk -f && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc overlay.arsc && \
-xxd -i overlay.arsc > overlay_arsc.h
+set -e
+
+aapt package -M AndroidManifest.xml -S res -F overlay.apk -f
diff --git a/libs/androidfw/tests/data/overlay/overlay.apk b/libs/androidfw/tests/data/overlay/overlay.apk
new file mode 100644
index 0000000..e0e0543
--- /dev/null
+++ b/libs/androidfw/tests/data/overlay/overlay.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/overlay/overlay_arsc.h b/libs/androidfw/tests/data/overlay/overlay_arsc.h
deleted file mode 100644
index 5bd98b2..0000000
--- a/libs/androidfw/tests/data/overlay/overlay_arsc.h
+++ /dev/null
@@ -1,69 +0,0 @@
-unsigned char overlay_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0x10, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x74, 0x00,
- 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x6f, 0x00,
- 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xc4, 0x02, 0x00, 0x00,
- 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
- 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
- 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
- 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
- 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x50, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
- 0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x69, 0x00, 0x6e, 0x00,
- 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x41, 0x00,
- 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x31, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x02, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
- 0x0b, 0x00, 0x00, 0x00
-};
-unsigned int overlay_arsc_len = 784;
diff --git a/libs/androidfw/tests/data/styles/R.h b/libs/androidfw/tests/data/styles/R.h
index 6dc6ede..4127aa0 100644
--- a/libs/androidfw/tests/data/styles/R.h
+++ b/libs/androidfw/tests/data/styles/R.h
@@ -1,3 +1,22 @@
+/*
+ * 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.
+ */
+
+#ifndef TEST_DATA_STYLES_R_H_
+#define TEST_DATA_STYLES_R_H_
+
#include <cstdint>
namespace com {
@@ -17,9 +36,9 @@
};
struct string {
- enum : uint32_t {
- string_one = 0x7f030000u,
- };
+ enum : uint32_t {
+ string_one = 0x7f030000u,
+ };
};
struct style {
@@ -33,3 +52,5 @@
} // namespace app
} // namespace android
} // namespace com
+
+#endif // TEST_DATA_STYLES_R_H_
diff --git a/libs/androidfw/tests/data/styles/build b/libs/androidfw/tests/data/styles/build
new file mode 100755
index 0000000..81f78b1
--- /dev/null
+++ b/libs/androidfw/tests/data/styles/build
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+set -e
+
+aapt package -F styles.apk -M AndroidManifest.xml -S res -f
diff --git a/libs/androidfw/tests/data/styles/build.sh b/libs/androidfw/tests/data/styles/build.sh
deleted file mode 100755
index e763421..0000000
--- a/libs/androidfw/tests/data/styles/build.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-set -e
-
-aapt package -F package.apk -M AndroidManifest.xml -S res
-unzip -j package.apk resources.arsc res/layout/layout.xml
-rm package.apk
diff --git a/libs/androidfw/tests/data/styles/layout.xml b/libs/androidfw/tests/data/styles/layout.xml
deleted file mode 100644
index 4997e71..0000000
--- a/libs/androidfw/tests/data/styles/layout.xml
+++ /dev/null
Binary files differ
diff --git a/libs/androidfw/tests/data/styles/resources.arsc b/libs/androidfw/tests/data/styles/resources.arsc
deleted file mode 100644
index 8f65c9a..0000000
--- a/libs/androidfw/tests/data/styles/resources.arsc
+++ /dev/null
Binary files differ
diff --git a/libs/androidfw/tests/data/styles/styles.apk b/libs/androidfw/tests/data/styles/styles.apk
new file mode 100644
index 0000000..6064c48
--- /dev/null
+++ b/libs/androidfw/tests/data/styles/styles.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/system/R.h b/libs/androidfw/tests/data/system/R.h
index 6a31fb8..becb388 100644
--- a/libs/androidfw/tests/data/system/R.h
+++ b/libs/androidfw/tests/data/system/R.h
@@ -14,32 +14,34 @@
* limitations under the License.
*/
-#ifndef __ANDROID_R_H
-#define __ANDROID_R_H
+#ifndef TEST_DATA_SYSTEM_R_H_
+#define TEST_DATA_SYSTEM_R_H_
+
+#include <cstdint>
namespace android {
-namespace R {
-namespace attr {
- enum {
- background = 0x01010000, // default
- foreground = 0x01010001, // default
+struct R {
+ struct attr {
+ enum : uint32_t {
+ background = 0x01010000, // default
+ foreground = 0x01010001, // default
};
-}
+ };
-namespace style {
- enum {
- Theme_One = 0x01020000, // default
+ struct style {
+ enum : uint32_t {
+ Theme_One = 0x01020000, // default
};
-}
+ };
-namespace integer {
- enum {
- number = 0x01030000, // sv
+ struct integer {
+ enum : uint32_t {
+ number = 0x01030000, // sv
};
-}
+ };
+};
-} // namespace R
-} // namespace android
+} // namespace android
-#endif // __ANDROID_R_H
+#endif // TEST_DATA_SYSTEM_R_H_
diff --git a/libs/androidfw/tests/data/system/build b/libs/androidfw/tests/data/system/build
index 1a70e84..bfbdf4c 100755
--- a/libs/androidfw/tests/data/system/build
+++ b/libs/androidfw/tests/data/system/build
@@ -15,7 +15,6 @@
# limitations under the License.
#
-aapt package -x -M AndroidManifest.xml -S res -F bundle.apk -f && \
-unzip bundle.apk resources.arsc && \
-mv resources.arsc system.arsc && \
-xxd -i system.arsc > system_arsc.h
+set -e
+
+aapt package -x -M AndroidManifest.xml -S res -F system.apk -f
diff --git a/libs/androidfw/tests/data/system/system.apk b/libs/androidfw/tests/data/system/system.apk
new file mode 100644
index 0000000..1299016
--- /dev/null
+++ b/libs/androidfw/tests/data/system/system.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/system/system_arsc.h b/libs/androidfw/tests/data/system/system_arsc.h
deleted file mode 100644
index b0dab6b..0000000
--- a/libs/androidfw/tests/data/system/system_arsc.h
+++ /dev/null
@@ -1,88 +0,0 @@
-unsigned char system_arsc[] = {
- 0x02, 0x00, 0x0c, 0x00, 0xf8, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xd0, 0x03, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
- 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x78, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00, 0x65, 0x00,
- 0x00, 0x00, 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00,
- 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x5e, 0x00,
- 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x2d, 0x00, 0x70, 0x00,
- 0x72, 0x00, 0x69, 0x00, 0x76, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x84, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x62, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x67, 0x00,
- 0x72, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x67, 0x00,
- 0x72, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00,
- 0x2e, 0x00, 0x4f, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x00, 0x00, 0x06, 0x00,
- 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00, 0x72, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x00, 0x00, 0x00, 0x40, 0x01, 0x02, 0x4c, 0x00, 0x8c, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x08, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x02, 0x4c, 0x00,
- 0x78, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
- 0x08, 0x00, 0x00, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x01, 0x01,
- 0x08, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x10, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x01, 0x02, 0x4c, 0x00, 0x60, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x76, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-unsigned int system_arsc_len = 1016;
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index cf571e9..18e59e5 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -46,6 +46,7 @@
renderthread/RenderTask.cpp \
renderthread/RenderThread.cpp \
renderthread/TimeLord.cpp \
+ renderthread/Frame.cpp \
thread/TaskManager.cpp \
utils/Blur.cpp \
utils/GLUtils.cpp \
@@ -182,6 +183,7 @@
external/skia/src/core \
external/skia/src/effects \
external/skia/src/image \
+ external/skia/src/utils \
external/harfbuzz_ng/src \
external/freetype/include
@@ -306,6 +308,7 @@
tests/unit/SkiaBehaviorTests.cpp \
tests/unit/SkiaDisplayListTests.cpp \
tests/unit/SkiaPipelineTests.cpp \
+ tests/unit/SkiaRenderPropertiesTests.cpp \
tests/unit/SkiaCanvasTests.cpp \
tests/unit/SnapshotTests.cpp \
tests/unit/StringUtilsTests.cpp \
diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp
index 7e2c28c..dbbf00d 100644
--- a/libs/hwui/CanvasState.cpp
+++ b/libs/hwui/CanvasState.cpp
@@ -202,17 +202,17 @@
// Clip
///////////////////////////////////////////////////////////////////////////////
-bool CanvasState::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
+bool CanvasState::clipRect(float left, float top, float right, float bottom, SkClipOp op) {
mSnapshot->clip(Rect(left, top, right, bottom), op);
return !mSnapshot->clipIsEmpty();
}
-bool CanvasState::clipPath(const SkPath* path, SkRegion::Op op) {
+bool CanvasState::clipPath(const SkPath* path, SkClipOp op) {
mSnapshot->clipPath(*path, op);
return !mSnapshot->clipIsEmpty();
}
-bool CanvasState::clipRegion(const SkRegion* region, SkRegion::Op op) {
+bool CanvasState::clipRegion(const SkRegion* region, SkClipOp op) {
mSnapshot->clipRegionTransformed(*region, op);
return !mSnapshot->clipIsEmpty();
}
@@ -225,7 +225,7 @@
bool outlineIsRounded = MathUtils::isPositive(radius);
if (!outlineIsRounded || currentTransform()->isSimple()) {
// TODO: consider storing this rect separately, so that this can't be replaced with clip ops
- clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, SkRegion::kIntersect_Op);
+ clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, SkClipOp::kIntersect);
}
if (outlineIsRounded) {
setClippingRoundRect(allocator, bounds, radius, false);
diff --git a/libs/hwui/CanvasState.h b/libs/hwui/CanvasState.h
index 22c7e8a..a805597 100644
--- a/libs/hwui/CanvasState.h
+++ b/libs/hwui/CanvasState.h
@@ -18,6 +18,7 @@
#include "Snapshot.h"
+#include <SkClipOp.h>
#include <SkMatrix.h>
#include <SkPath.h>
#include <SkRegion.h>
@@ -121,9 +122,9 @@
bool quickRejectConservative(float left, float top, float right, float bottom) const;
- bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
- bool clipPath(const SkPath* path, SkRegion::Op op);
- bool clipRegion(const SkRegion* region, SkRegion::Op op);
+ bool clipRect(float left, float top, float right, float bottom, SkClipOp op);
+ bool clipPath(const SkPath* path, SkClipOp op);
+ bool clipRegion(const SkRegion* region, SkClipOp op);
/**
* Sets a "clipping outline", which is independent from the regular clip.
diff --git a/libs/hwui/FloatColor.h b/libs/hwui/FloatColor.h
index 9df7338..d8afa35 100644
--- a/libs/hwui/FloatColor.h
+++ b/libs/hwui/FloatColor.h
@@ -38,13 +38,13 @@
}
// "color" is a gamma-encoded sRGB color
- // After calling this method, the color is stored as a pre-multiplied linear color
- // if linear blending is enabled.
- void setSRGB(uint32_t color) {
+ // After calling this method, the color is stored as a linear color. The color
+ // is not pre-multiplied.
+ void setUnPreMultipliedSRGB(uint32_t color) {
a = ((color >> 24) & 0xff) / 255.0f;
- r = a * EOCF_sRGB(((color >> 16) & 0xff) / 255.0f);
- g = a * EOCF_sRGB(((color >> 8) & 0xff) / 255.0f);
- b = a * EOCF_sRGB(((color ) & 0xff) / 255.0f);
+ r = EOCF_sRGB(((color >> 16) & 0xff) / 255.0f);
+ g = EOCF_sRGB(((color >> 8) & 0xff) / 255.0f);
+ b = EOCF_sRGB(((color ) & 0xff) / 255.0f);
}
bool isNotBlack() {
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 245db1d..a53a55a 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -120,7 +120,7 @@
mCanvasState.save(SaveFlags::MatrixClip);
mCanvasState.translate(tx, ty);
mCanvasState.clipRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
- SkRegion::kIntersect_Op);
+ SkClipOp::kIntersect);
deferNodePropsAndOps(renderNode);
mCanvasState.restore();
}
@@ -262,7 +262,7 @@
Rect clipRect;
properties.getClippingRectForFlags(clipFlags, &clipRect);
mCanvasState.clipRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
- SkRegion::kIntersect_Op);
+ SkClipOp::kIntersect);
}
if (properties.getRevealClip().willClip()) {
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 0972ac1..1dad58f 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -188,26 +188,28 @@
void GradientCache::mixBytes(const FloatColor& start, const FloatColor& end,
float amount, uint8_t*& dst) const {
float oppAmount = 1.0f - amount;
- *dst++ = uint8_t(OECF_sRGB(start.r * oppAmount + end.r * amount) * 255.0f);
- *dst++ = uint8_t(OECF_sRGB(start.g * oppAmount + end.g * amount) * 255.0f);
- *dst++ = uint8_t(OECF_sRGB(start.b * oppAmount + end.b * amount) * 255.0f);
- *dst++ = uint8_t( (start.a * oppAmount + end.a * amount) * 255.0f);
+ float a = start.a * oppAmount + end.a * amount;
+ *dst++ = uint8_t(a * OECF_sRGB((start.r * oppAmount + end.r * amount)) * 255.0f);
+ *dst++ = uint8_t(a * OECF_sRGB((start.g * oppAmount + end.g * amount)) * 255.0f);
+ *dst++ = uint8_t(a * OECF_sRGB((start.b * oppAmount + end.b * amount)) * 255.0f);
+ *dst++ = uint8_t(a * 255.0f);
}
void GradientCache::mixFloats(const FloatColor& start, const FloatColor& end,
float amount, uint8_t*& dst) const {
float oppAmount = 1.0f - amount;
+ float a = start.a * oppAmount + end.a * amount;
float* d = (float*) dst;
#ifdef ANDROID_ENABLE_LINEAR_BLENDING
- *d++ = start.r * oppAmount + end.r * amount;
- *d++ = start.g * oppAmount + end.g * amount;
- *d++ = start.b * oppAmount + end.b * amount;
+ *d++ = a * (start.r * oppAmount + end.r * amount);
+ *d++ = a * (start.g * oppAmount + end.g * amount);
+ *d++ = a * (start.b * oppAmount + end.b * amount);
#else
- *d++ = OECF_sRGB(start.r * oppAmount + end.r * amount);
- *d++ = OECF_sRGB(start.g * oppAmount + end.g * amount);
- *d++ = OECF_sRGB(start.b * oppAmount + end.b * amount);
+ *d++ = a * OECF_sRGB(start.r * oppAmount + end.r * amount);
+ *d++ = a * OECF_sRGB(start.g * oppAmount + end.g * amount);
+ *d++ = a * OECF_sRGB(start.b * oppAmount + end.b * amount);
#endif
- *d++ = start.a * oppAmount + end.a * amount;
+ *d++ = a;
dst += 4 * sizeof(float);
}
@@ -217,16 +219,19 @@
uint8_t pixels[rowBytes * height];
static ChannelMixer gMixers[] = {
- &android::uirenderer::GradientCache::mixBytes, // colors are stored gamma-encoded
- &android::uirenderer::GradientCache::mixFloats, // colors are stored in linear
+ // colors are stored gamma-encoded
+ &android::uirenderer::GradientCache::mixBytes,
+ // colors are stored in linear (linear blending on)
+ // or gamma-encoded (linear blending off)
+ &android::uirenderer::GradientCache::mixFloats,
};
ChannelMixer mix = gMixers[mUseFloatTexture];
FloatColor start;
- start.setSRGB(colors[0]);
+ start.setUnPreMultipliedSRGB(colors[0]);
FloatColor end;
- end.setSRGB(colors[1]);
+ end.setUnPreMultipliedSRGB(colors[1]);
int currentPos = 1;
float startPos = positions[0];
@@ -241,7 +246,7 @@
currentPos++;
- end.setSRGB(colors[currentPos]);
+ end.setUnPreMultipliedSRGB(colors[currentPos]);
distance = positions[currentPos] - startPos;
}
diff --git a/libs/hwui/OpenGLReadback.cpp b/libs/hwui/OpenGLReadback.cpp
index 408159b..74a8395 100644
--- a/libs/hwui/OpenGLReadback.cpp
+++ b/libs/hwui/OpenGLReadback.cpp
@@ -82,8 +82,15 @@
return CopyResult::UnknownError;
}
- CopyResult copyResult = copyImageInto(sourceImage, texTransform, graphicBuffer->getWidth(),
- graphicBuffer->getHeight(), srcRect, bitmap);
+ uint32_t width = graphicBuffer->getWidth();
+ uint32_t height = graphicBuffer->getHeight();
+ // If this is a 90 or 270 degree rotation we need to swap width/height
+ // This is a fuzzy way of checking that.
+ if (texTransform[Matrix4::kSkewX] >= 0.5f || texTransform[Matrix4::kSkewX] <= -0.5f) {
+ std::swap(width, height);
+ }
+ CopyResult copyResult = copyImageInto(sourceImage, texTransform, width, height,
+ srcRect, bitmap);
// All we're flushing & finishing is the deletion of the texture since
// copyImageInto already did a major flush & finish as an implicit
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index 52c62cc..983c17e 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -36,8 +36,7 @@
, mSize(0)
, mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity)
, mMeshBuffer(0)
- , mFreeBlocks(nullptr)
- , mGenerationId(0) {}
+ , mFreeBlocks(nullptr) {}
PatchCache::~PatchCache() {
clear();
@@ -158,7 +157,6 @@
mMaxSize, nullptr, GL_DYNAMIC_DRAW);
mSize = 0;
mFreeBlocks = new BufferBlock(0, mMaxSize);
- mGenerationId++;
}
/**
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index 0624c35..aa746c7 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -69,10 +69,6 @@
return mMeshBuffer;
}
- uint32_t getGenerationId() const {
- return mGenerationId;
- }
-
/**
* Removes the entries associated with the specified 9-patch. This is meant
* to be called from threads that are not the EGL context thread (GC thread
@@ -175,8 +171,6 @@
// First available free block inside the mesh buffer
BufferBlock* mFreeBlocks;
- uint32_t mGenerationId;
-
// Garbage tracking, required to handle GC events on the VM side
Vector<Res_png_9patch*> mGarbage;
mutable Mutex mLock;
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index 9c4cb09..e70982f 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -54,6 +54,7 @@
#define PROGRAM_KEY_COLOR_MATRIX 0x20
#define PROGRAM_KEY_COLOR_BLEND 0x40
#define PROGRAM_KEY_BITMAP_NPOT 0x80
+#define PROGRAM_KEY_BITMAP_EXTERNAL 0x100
#define PROGRAM_KEY_SWAP_SRC_DST 0x2000
@@ -133,6 +134,7 @@
// Shaders
bool hasBitmap;
+ bool isShaderBitmapExternal;
bool useShaderBasedWrap;
bool hasVertexAlpha;
@@ -180,6 +182,7 @@
modulate = false;
hasBitmap = false;
+ isShaderBitmapExternal = false;
useShaderBasedWrap = false;
hasGradient = false;
@@ -239,6 +242,9 @@
key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
}
+ if (isShaderBitmapExternal) {
+ key |= PROGRAM_KEY_BITMAP_EXTERNAL;
+ }
}
if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 0c2309f..7107679 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -145,6 +145,8 @@
};
const char* gFS_Uniforms_BitmapSampler =
"uniform sampler2D bitmapSampler;\n";
+const char* gFS_Uniforms_BitmapExternalSampler =
+ "uniform samplerExternalOES bitmapSampler;\n";
const char* gFS_Uniforms_ColorOp[3] = {
// None
"",
@@ -175,10 +177,11 @@
const char* gFS_Gradient_Preamble[2] = {
// Linear framebuffer
"\nvec4 dither(const vec4 color) {\n"
- " return vec4(color.rgb + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0), color.a);"
+ " return vec4(color.rgb + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0), color.a);\n"
"}\n"
"\nvec4 gammaMix(const vec4 a, const vec4 b, float v) {\n"
- " return pow(mix(a, b, v), vec4(vec3(1.0 / 2.2), 1.0));"
+ " vec4 c = pow(mix(a, b, v), vec4(vec3(1.0 / 2.2), 1.0));\n"
+ " return vec4(c.rgb * c.a, c.a);\n"
"}\n",
// sRGB framebuffer
"\nvec4 dither(const vec4 color) {\n"
@@ -186,7 +189,8 @@
" return vec4(dithered * dithered, color.a);\n"
"}\n"
"\nvec4 gammaMix(const vec4 a, const vec4 b, float v) {\n"
- " return mix(a, b, v);"
+ " vec4 c = mix(a, b, v);\n"
+ " return vec4(c.rgb * c.a, c.a);\n"
"}\n"
};
@@ -576,7 +580,8 @@
if (blendFramebuffer) {
shader.append(gFS_Header_Extension_FramebufferFetch);
}
- if (description.hasExternalTexture) {
+ if (description.hasExternalTexture
+ || (description.hasBitmap && description.isShaderBitmapExternal)) {
shader.append(gFS_Header_Extension_ExternalTexture);
}
@@ -693,7 +698,11 @@
}
if (description.hasBitmap) {
- shader.append(gFS_Uniforms_BitmapSampler);
+ if (description.isShaderBitmapExternal) {
+ shader.append(gFS_Uniforms_BitmapExternalSampler);
+ } else {
+ shader.append(gFS_Uniforms_BitmapSampler);
+ }
}
shader.append(gFS_Uniforms_ColorOp[static_cast<int>(description.colorOp)]);
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 9d18484..96c6d29 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -234,13 +234,13 @@
SkRect bounds = path.getBounds();
return mState.quickRejectConservative(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
}
-bool RecordingCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
+bool RecordingCanvas::clipRect(float left, float top, float right, float bottom, SkClipOp op) {
return mState.clipRect(left, top, right, bottom, op);
}
-bool RecordingCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
+bool RecordingCanvas::clipPath(const SkPath* path, SkClipOp op) {
return mState.clipPath(path, op);
}
-bool RecordingCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
+bool RecordingCanvas::clipRegion(const SkRegion* region, SkClipOp op) {
return mState.clipRegion(region, op);
}
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index f93e8b8..5d49385 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -131,9 +131,10 @@
virtual bool quickRejectRect(float left, float top, float right, float bottom) const override;
virtual bool quickRejectPath(const SkPath& path) const override;
- virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op) override;
- virtual bool clipPath(const SkPath* path, SkRegion::Op op) override;
- virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) override;
+ virtual bool clipRect(float left, float top, float right, float bottom,
+ SkClipOp op) override;
+ virtual bool clipPath(const SkPath* path, SkClipOp op) override;
+ virtual bool clipRegion(const SkRegion* region, SkClipOp op) override;
// Misc
virtual SkDrawFilter* getDrawFilter() override { return mDrawFilter.get(); }
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 6786a69..8ab57c9d 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -78,13 +78,13 @@
public:
explicit ClipCopier(SkCanvas* dstCanvas) : m_dstCanvas(dstCanvas) {}
- virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) {
+ virtual void clipRect(const SkRect& rect, SkClipOp op, bool antialias) {
m_dstCanvas->clipRect(rect, op, antialias);
}
- virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) {
+ virtual void clipRRect(const SkRRect& rrect, SkClipOp op, bool antialias) {
m_dstCanvas->clipRRect(rrect, op, antialias);
}
- virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) {
+ virtual void clipPath(const SkPath& path, SkClipOp op, bool antialias) {
m_dstCanvas->clipPath(path, op, antialias);
}
@@ -218,11 +218,11 @@
class SkiaCanvas::Clip {
public:
- Clip(const SkRect& rect, SkRegion::Op op, const SkMatrix& m)
+ Clip(const SkRect& rect, SkClipOp op, const SkMatrix& m)
: mType(Type::Rect), mOp(op), mMatrix(m), mRRect(SkRRect::MakeRect(rect)) {}
- Clip(const SkRRect& rrect, SkRegion::Op op, const SkMatrix& m)
+ Clip(const SkRRect& rrect, SkClipOp op, const SkMatrix& m)
: mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {}
- Clip(const SkPath& path, SkRegion::Op op, const SkMatrix& m)
+ Clip(const SkPath& path, SkClipOp op, const SkMatrix& m)
: mType(Type::Path), mOp(op), mMatrix(m), mPath(&path) {}
void apply(SkCanvas* canvas) const {
@@ -247,9 +247,9 @@
Path,
};
- Type mType;
- SkRegion::Op mOp;
- SkMatrix mMatrix;
+ Type mType;
+ SkClipOp mOp;
+ SkMatrix mMatrix;
// These are logically a union (tracked separately due to non-POD path).
SkTLazy<SkPath> mPath;
@@ -293,7 +293,7 @@
}
template <typename T>
-void SkiaCanvas::recordClip(const T& clip, SkRegion::Op op) {
+void SkiaCanvas::recordClip(const T& clip, SkClipOp op) {
// Only need tracking when in a partial save frame which
// doesn't restore the clip.
const SaveRec* rec = this->currentSaveRec();
@@ -397,14 +397,14 @@
return mCanvas->quickReject(path);
}
-bool SkiaCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
+bool SkiaCanvas::clipRect(float left, float top, float right, float bottom, SkClipOp op) {
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
this->recordClip(rect, op);
mCanvas->clipRect(rect, op);
return !mCanvas->isClipEmpty();
}
-bool SkiaCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
+bool SkiaCanvas::clipPath(const SkPath* path, SkClipOp op) {
SkRRect roundRect;
if (path->isRRect(&roundRect)) {
this->recordClip(roundRect, op);
@@ -416,7 +416,7 @@
return !mCanvas->isClipEmpty();
}
-bool SkiaCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
+bool SkiaCanvas::clipRegion(const SkRegion* region, SkClipOp op) {
SkPath rgnPath;
if (region->getBoundaryPath(&rgnPath)) {
// The region is specified in device space.
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 4f1d857..9639ebd 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -92,9 +92,9 @@
virtual bool quickRejectRect(float left, float top, float right, float bottom) const override;
virtual bool quickRejectPath(const SkPath& path) const override;
virtual bool clipRect(float left, float top, float right, float bottom,
- SkRegion::Op op) override;
- virtual bool clipPath(const SkPath* path, SkRegion::Op op) override;
- virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) override;
+ SkClipOp op) override;
+ virtual bool clipPath(const SkPath* path, SkClipOp op) override;
+ virtual bool clipRegion(const SkRegion* region, SkClipOp op) override;
virtual SkDrawFilter* getDrawFilter() override;
virtual void setDrawFilter(SkDrawFilter* drawFilter) override;
@@ -174,7 +174,7 @@
void recordPartialSave(SaveFlags::Flags flags);
template<typename T>
- void recordClip(const T&, SkRegion::Op);
+ void recordClip(const T&, SkClipOp);
void applyPersistentClips(size_t clipStartIndex);
void drawPoints(const float* points, int count, const SkPaint& paint,
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 5978abc..75396f7 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -430,21 +430,21 @@
}
}
-void SkiaCanvasProxy::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle) {
+void SkiaCanvasProxy::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle) {
mCanvas->clipRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, op);
}
-void SkiaCanvasProxy::onClipRRect(const SkRRect& roundRect, SkRegion::Op op, ClipEdgeStyle) {
+void SkiaCanvasProxy::onClipRRect(const SkRRect& roundRect, SkClipOp op, ClipEdgeStyle) {
SkPath path;
path.addRRect(roundRect);
mCanvas->clipPath(&path, op);
}
-void SkiaCanvasProxy::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle) {
+void SkiaCanvasProxy::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle) {
mCanvas->clipPath(&path, op);
}
-void SkiaCanvasProxy::onClipRegion(const SkRegion& region, SkRegion::Op op) {
+void SkiaCanvasProxy::onClipRegion(const SkRegion& region, SkClipOp op) {
mCanvas->clipRegion(®ion, op);
}
diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h
index 0111815..badcc1d 100644
--- a/libs/hwui/SkiaCanvasProxy.h
+++ b/libs/hwui/SkiaCanvasProxy.h
@@ -90,10 +90,10 @@
const SkPoint texCoords[4], SkBlendMode,
const SkPaint& paint) override;
- virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override;
- virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) override;
- virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) override;
- virtual void onClipRegion(const SkRegion&, SkRegion::Op) override;
+ virtual void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
+ virtual void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
+ virtual void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override;
+ virtual void onClipRegion(const SkRegion&, SkClipOp) override;
private:
Canvas* mCanvas;
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 34e6a06..fadb960 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -81,7 +81,7 @@
}
///////////////////////////////////////////////////////////////////////////////
-// gradient shader matrix helpers
+// Gradient shader matrix helpers
///////////////////////////////////////////////////////////////////////////////
static void toLinearUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
@@ -161,7 +161,7 @@
gradInfo.fColorOffsets = &colorOffsets[0];
shader.asAGradient(&gradInfo);
- if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) {
+ if (CC_UNLIKELY(!description->isSimpleGradient)) {
outData->gradientSampler = (*textureUnit)++;
#ifndef SK_SCALAR_IS_FLOAT
@@ -174,8 +174,8 @@
outData->gradientSampler = 0;
outData->gradientTexture = nullptr;
- outData->startColor.setSRGB(gradInfo.fColors[0]);
- outData->endColor.setSRGB(gradInfo.fColors[1]);
+ outData->startColor.setUnPreMultipliedSRGB(gradInfo.fColors[0]);
+ outData->endColor.setUnPreMultipliedSRGB(gradInfo.fColors[1]);
}
return true;
@@ -218,6 +218,7 @@
const float height = outData->bitmapTexture->height();
description->hasBitmap = true;
+ description->isShaderBitmapExternal = hwuiBitmap->isHardware();
// gralloc doesn't support non-clamp modes
if (hwuiBitmap->isHardware() || (!caches.extensions().hasNPot()
&& (!isPowerOfTwo(width) || !isPowerOfTwo(height))
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index f61c3e9..3f08009 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -72,19 +72,19 @@
// Clipping
///////////////////////////////////////////////////////////////////////////////
-void Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) {
+void Snapshot::clipRegionTransformed(const SkRegion& region, SkClipOp op) {
flags |= Snapshot::kFlagClipSet;
- mClipArea->clipRegion(region, op);
+ mClipArea->clipRegion(region, static_cast<SkRegion::Op>(op));
}
-void Snapshot::clip(const Rect& localClip, SkRegion::Op op) {
+void Snapshot::clip(const Rect& localClip, SkClipOp op) {
flags |= Snapshot::kFlagClipSet;
- mClipArea->clipRectWithTransform(localClip, transform, op);
+ mClipArea->clipRectWithTransform(localClip, transform, static_cast<SkRegion::Op>(op));
}
-void Snapshot::clipPath(const SkPath& path, SkRegion::Op op) {
+void Snapshot::clipPath(const SkPath& path, SkClipOp op) {
flags |= Snapshot::kFlagClipSet;
- mClipArea->clipPathWithTransform(path, transform, op);
+ mClipArea->clipPathWithTransform(path, transform, static_cast<SkRegion::Op>(op));
}
void Snapshot::setClip(float left, float top, float right, float bottom) {
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 4ab5830..4f92657 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -23,6 +23,7 @@
#include <utils/RefBase.h>
#include <ui/Region.h>
+#include <SkClipOp.h>
#include <SkRegion.h>
#include "ClipArea.h"
@@ -107,25 +108,25 @@
* the specified operation. The specified rectangle is transformed
* by this snapshot's trasnformation.
*/
- void clip(const Rect& localClip, SkRegion::Op op);
+ void clip(const Rect& localClip, SkClipOp op);
/**
* Modifies the current clip with the new clip rectangle and
* the specified operation. The specified rectangle is considered
* already transformed.
*/
- void clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op);
+ void clipTransformed(const Rect& r, SkClipOp op = SkClipOp::kIntersect);
/**
* Modifies the current clip with the specified region and operation.
* The specified region is considered already transformed.
*/
- void clipRegionTransformed(const SkRegion& region, SkRegion::Op op);
+ void clipRegionTransformed(const SkRegion& region, SkClipOp op);
/**
* Modifies the current clip with the specified path and operation.
*/
- void clipPath(const SkPath& path, SkRegion::Op op);
+ void clipPath(const SkPath& path, SkClipOp op);
/**
* Sets the current clip.
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index 97b7dd7..208107f 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -308,7 +308,7 @@
void ClipPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath,
float strokeScale, const SkMatrix& matrix, bool useStagingData){
- outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op);
+ outCanvas->clipPath(renderPath);
}
Group::Group(const Group& group) : Node(group) {
@@ -574,7 +574,7 @@
}
bool Tree::canReuseBitmap(Bitmap* bitmap, int width, int height) {
- return bitmap && width == bitmap->width() && height == bitmap->height();
+ return bitmap && width <= bitmap->width() && height <= bitmap->height();
}
void Tree::onPropertyChanged(TreeProperties* prop) {
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index e9a9c71..8244a39 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -630,10 +630,15 @@
}
void setScaledSize(int width, int height) {
- if (mNonAnimatableProperties.scaledWidth != width
- || mNonAnimatableProperties.scaledHeight != height) {
- mNonAnimatableProperties.scaledWidth = width;
- mNonAnimatableProperties.scaledHeight = height;
+ // If the requested size is bigger than what the bitmap was, then
+ // we increase the bitmap size to match. The width and height
+ // are bound by MAX_CACHED_BITMAP_SIZE.
+ if (mNonAnimatableProperties.scaledWidth < width
+ || mNonAnimatableProperties.scaledHeight < height) {
+ mNonAnimatableProperties.scaledWidth = std::max(width,
+ mNonAnimatableProperties.scaledWidth);
+ mNonAnimatableProperties.scaledHeight = std::max(height,
+ mNonAnimatableProperties.scaledHeight);
mNonAnimatablePropertiesDirty = true;
mTree->onPropertyChanged(this);
}
diff --git a/libs/hwui/font/Font.h b/libs/hwui/font/Font.h
index 288f733..504dabb 100644
--- a/libs/hwui/font/Font.h
+++ b/libs/hwui/font/Font.h
@@ -22,14 +22,16 @@
#include <utils/KeyedVector.h>
#include <SkScalar.h>
-#include <SkGlyphCache.h>
#include <SkPaint.h>
#include <SkPathMeasure.h>
+#include <SkTypeface.h>
#include "FontUtil.h"
#include "../Rect.h"
#include "../Matrix.h"
+class SkGlyphCache;
+
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index d3e765d..64ef866 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -16,6 +16,7 @@
#include "Bitmap.h"
#include "Caches.h"
+#include "renderthread/EglManager.h"
#include "renderthread/RenderThread.h"
#include "renderthread/RenderProxy.h"
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index d7839b4..e7b6b2d 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -182,9 +182,9 @@
virtual bool quickRejectPath(const SkPath& path) const = 0;
virtual bool clipRect(float left, float top, float right, float bottom,
- SkRegion::Op op = SkRegion::kIntersect_Op) = 0;
- virtual bool clipPath(const SkPath* path, SkRegion::Op op) = 0;
- virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) = 0;
+ SkClipOp op) = 0;
+ virtual bool clipPath(const SkPath* path, SkClipOp op) = 0;
+ virtual bool clipRegion(const SkRegion* region, SkClipOp op) = 0;
// filters
virtual SkDrawFilter* getDrawFilter() = 0;
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 4b34c7c..117395b 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -68,7 +68,7 @@
if (pendingClip && !pendingClip->contains(rect)) {
canvas->clipRect(*pendingClip);
}
- canvas->clipRRect(SkRRect::MakeRectXY(rect, radius, radius), SkRegion::kIntersect_Op, true);
+ canvas->clipRRect(SkRRect::MakeRectXY(rect, radius, radius), SkClipOp::kIntersect, true);
} else {
if (pendingClip) {
(void)rect.intersect(*pendingClip);
@@ -263,7 +263,7 @@
}
if (properties.getRevealClip().willClip()) {
- canvas->clipPath(*properties.getRevealClip().getPath(), SkRegion::kIntersect_Op, true);
+ canvas->clipPath(*properties.getRevealClip().getPath(), SkClipOp::kIntersect, true);
} else if (properties.getOutline().willClip()) {
clipOutline(properties.getOutline(), canvas, pendingClip);
pendingClip = nullptr;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 7f3474a..c8258f7 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -19,6 +19,7 @@
#include "DeferredLayerUpdater.h"
#include "LayerDrawable.h"
#include "renderthread/EglManager.h"
+#include "renderthread/Frame.h"
#include "renderstate/RenderState.h"
#include "SkiaPipeline.h"
#include "SkiaProfileRenderer.h"
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 0f2d09d..376346f 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -17,6 +17,8 @@
#include "SkiaPipeline.h"
#include "utils/TraceUtils.h"
+#include <SkImageEncoder.h>
+#include <SkImagePriv.h>
#include <SkOSFile.h>
#include <SkOverdrawCanvas.h>
#include <SkOverdrawColorFilter.h>
@@ -98,7 +100,7 @@
int saveCount = layerCanvas->save();
SkASSERT(saveCount == 1);
- layerCanvas->clipRect(layerDamage.toSkRect(), SkRegion::kReplace_Op);
+ layerCanvas->clipRect(layerDamage.toSkRect(), SkClipOp::kReplace);
auto savedLightCenter = mLightCenter;
// map current light center into RenderNode's coordinate space
@@ -166,8 +168,10 @@
public:
bool onUseEncodedData(const void*, size_t) override { return true; }
SkData* onEncode(const SkPixmap& pixmap) override {
- return SkImageEncoder::EncodeData(pixmap.info(), pixmap.addr(), pixmap.rowBytes(),
- SkImageEncoder::kPNG_Type, 100);
+ SkDynamicMemoryWStream buf;
+ return SkEncodeImage(&buf, pixmap, SkEncodedImageFormat::kPNG, 100)
+ ? buf.detachAsData().release()
+ : nullptr;
}
};
@@ -218,67 +222,103 @@
canvas->flush();
}
+namespace {
+static Rect nodeBounds(RenderNode& node) {
+ auto& props = node.properties();
+ return Rect(props.getLeft(), props.getTop(),
+ props.getRight(), props.getBottom());
+}
+}
+
void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect &contentDrawBounds,
SkCanvas* canvas) {
- canvas->clipRect(clip, SkRegion::kReplace_Op);
+ canvas->clipRect(clip, SkClipOp::kReplace);
if (!opaque) {
canvas->clear(SK_ColorTRANSPARENT);
}
- // If there are multiple render nodes, they are laid out as follows:
- // #0 - backdrop (content + caption)
- // #1 - content (positioned at (0,0) and clipped to - its bounds mContentDrawBounds)
- // #2 - additional overlay nodes
- // Usually the backdrop cannot be seen since it will be entirely covered by the content. While
- // resizing however it might become partially visible. The following render loop will crop the
- // backdrop against the content and draw the remaining part of it. It will then draw the content
- // cropped to the backdrop (since that indicates a shrinking of the window).
- //
- // Additional nodes will be drawn on top with no particular clipping semantics.
+ if (1 == nodes.size()) {
+ if (!nodes[0]->nothingToDraw()) {
+ SkAutoCanvasRestore acr(canvas, true);
+ RenderNodeDrawable root(nodes[0].get(), canvas);
+ root.draw(canvas);
+ }
+ } else if (0 == nodes.size()) {
+ //nothing to draw
+ } else {
+ // It there are multiple render nodes, they are laid out as follows:
+ // #0 - backdrop (content + caption)
+ // #1 - content (local bounds are at (0,0), will be translated and clipped to backdrop)
+ // #2 - additional overlay nodes
+ // Usually the backdrop cannot be seen since it will be entirely covered by the content. While
+ // resizing however it might become partially visible. The following render loop will crop the
+ // backdrop against the content and draw the remaining part of it. It will then draw the content
+ // cropped to the backdrop (since that indicates a shrinking of the window).
+ //
+ // Additional nodes will be drawn on top with no particular clipping semantics.
- // The bounds of the backdrop against which the content should be clipped.
- Rect backdropBounds = contentDrawBounds;
- // Usually the contents bounds should be mContentDrawBounds - however - we will
- // move it towards the fixed edge to give it a more stable appearance (for the moment).
- // If there is no content bounds we ignore the layering as stated above and start with 2.
- int layer = (contentDrawBounds.isEmpty() || nodes.size() == 1) ? 2 : 0;
+ // Usually the contents bounds should be mContentDrawBounds - however - we will
+ // move it towards the fixed edge to give it a more stable appearance (for the moment).
+ // If there is no content bounds we ignore the layering as stated above and start with 2.
- for (const sp<RenderNode>& node : nodes) {
- if (node->nothingToDraw()) continue;
+ // Backdrop bounds in render target space
+ const Rect backdrop = nodeBounds(*nodes[0]);
- SkASSERT(node->getDisplayList()->isSkiaDL());
+ // Bounds that content will fill in render target space (note content node bounds may be bigger)
+ Rect content(contentDrawBounds.getWidth(), contentDrawBounds.getHeight());
+ content.translate(backdrop.left, backdrop.top);
+ if (!content.contains(backdrop) && !nodes[0]->nothingToDraw()) {
+ // Content doesn't entirely overlap backdrop, so fill around content (right/bottom)
- int count = canvas->save();
-
- if (layer == 0) {
- const RenderProperties& properties = node->properties();
- Rect targetBounds(properties.getLeft(), properties.getTop(),
- properties.getRight(), properties.getBottom());
- // Move the content bounds towards the fixed corner of the backdrop.
- const int x = targetBounds.left;
- const int y = targetBounds.top;
- // Remember the intersection of the target bounds and the intersection bounds against
- // which we have to crop the content.
- backdropBounds.set(x, y, x + backdropBounds.getWidth(), y + backdropBounds.getHeight());
- backdropBounds.doIntersect(targetBounds);
- } else if (layer == 1) {
- // We shift and clip the content to match its final location in the window.
- const SkRect clip = SkRect::MakeXYWH(contentDrawBounds.left, contentDrawBounds.top,
- backdropBounds.getWidth(), backdropBounds.getHeight());
- const float dx = backdropBounds.left - contentDrawBounds.left;
- const float dy = backdropBounds.top - contentDrawBounds.top;
- canvas->translate(dx, dy);
- // It gets cropped against the bounds of the backdrop to stay inside.
- canvas->clipRect(clip, SkRegion::kIntersect_Op);
+ // Note: in the future, if content doesn't snap to backdrop's left/top, this may need to
+ // also fill left/top. Currently, both 2up and freeform position content at the top/left of
+ // the backdrop, so this isn't necessary.
+ RenderNodeDrawable backdropNode(nodes[0].get(), canvas);
+ if (content.right < backdrop.right) {
+ // draw backdrop to right side of content
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->clipRect(SkRect::MakeLTRB(content.right, backdrop.top,
+ backdrop.right, backdrop.bottom));
+ backdropNode.draw(canvas);
+ }
+ if (content.bottom < backdrop.bottom) {
+ // draw backdrop to bottom of content
+ // Note: bottom fill uses content left/right, to avoid overdrawing left/right fill
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->clipRect(SkRect::MakeLTRB(content.left, content.bottom,
+ content.right, backdrop.bottom));
+ backdropNode.draw(canvas);
+ }
}
- RenderNodeDrawable root(node.get(), canvas);
- root.draw(canvas);
- canvas->restoreToCount(count);
- layer++;
+ RenderNodeDrawable contentNode(nodes[1].get(), canvas);
+ if (!backdrop.isEmpty()) {
+ // content node translation to catch up with backdrop
+ float dx = backdrop.left - contentDrawBounds.left;
+ float dy = backdrop.top - contentDrawBounds.top;
+
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->translate(dx, dy);
+ const SkRect contentLocalClip = SkRect::MakeXYWH(contentDrawBounds.left,
+ contentDrawBounds.top, backdrop.getWidth(), backdrop.getHeight());
+ canvas->clipRect(contentLocalClip);
+ contentNode.draw(canvas);
+ } else {
+ SkAutoCanvasRestore acr(canvas, true);
+ contentNode.draw(canvas);
+ }
+
+ // remaining overlay nodes, simply defer
+ for (size_t index = 2; index < nodes.size(); index++) {
+ if (!nodes[index]->nothingToDraw()) {
+ SkAutoCanvasRestore acr(canvas, true);
+ RenderNodeDrawable overlayNode(nodes[index].get(), canvas);
+ overlayNode.draw(canvas);
+ }
+ }
}
}
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 95db258..dbe0296 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -21,6 +21,7 @@
#include "LayerDrawable.h"
#include "NinePatchUtils.h"
#include "pipeline/skia/AnimatedDrawables.h"
+#include <SkImagePriv.h>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index ca394b2..0d3f4ef 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -17,7 +17,7 @@
#include "SkiaVulkanPipeline.h"
#include "DeferredLayerUpdater.h"
-#include "renderthread/EglManager.h" // needed for Frame
+#include "renderthread/Frame.h"
#include "Readback.h"
#include "renderstate/RenderState.h"
#include "SkiaPipeline.h"
@@ -58,8 +58,7 @@
return Frame(-1, -1, 0);
}
- // TODO: support buffer age if Vulkan API can do it
- Frame frame(backBuffer->width(), backBuffer->height(), 0);
+ Frame frame(backBuffer->width(), backBuffer->height(), mVkManager.getAge(mVkSurface));
return frame;
}
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index c561c86..1b3bf96 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -20,6 +20,7 @@
#include "AnimationContext.h"
#include "Caches.h"
#include "EglManager.h"
+#include "Frame.h"
#include "LayerUpdateQueue.h"
#include "Properties.h"
#include "RenderThread.h"
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index de95bee..02021fc 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -19,6 +19,7 @@
#include "Texture.h"
#include "Caches.h"
#include "DeviceInfo.h"
+#include "Frame.h"
#include "Properties.h"
#include "RenderThread.h"
#include "renderstate/RenderState.h"
@@ -74,24 +75,6 @@
bool setDamage = false;
} EglExtensions;
-void Frame::map(const SkRect& in, EGLint* out) const {
- /* The rectangles are specified relative to the bottom-left of the surface
- * and the x and y components of each rectangle specify the bottom-left
- * position of that rectangle.
- *
- * HWUI does everything with 0,0 being top-left, so need to map
- * the rect
- */
- SkIRect idirty;
- in.roundOut(&idirty);
- EGLint y = mHeight - (idirty.y() + idirty.height());
- // layout: {x, y, width, height}
- out[0] = idirty.x();
- out[1] = y;
- out[2] = idirty.width();
- out[3] = idirty.height();
-}
-
EglManager::EglManager(RenderThread& thread)
: mRenderThread(thread)
, mEglDisplay(EGL_NO_DISPLAY)
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index b12522e..0251925 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -26,36 +26,8 @@
namespace uirenderer {
namespace renderthread {
+class Frame;
class RenderThread;
-class EglManager;
-
-class Frame {
-public:
- Frame(EGLint width, EGLint height, EGLint bufferAge)
- : mWidth(width)
- , mHeight(height)
- , mBufferAge(bufferAge) { }
-
- EGLint width() const { return mWidth; }
- EGLint height() const { return mHeight; }
-
- // See: https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_buffer_age.txt
- // for what this means
- EGLint bufferAge() const { return mBufferAge; }
-
-private:
- Frame() {}
- friend class EglManager;
-
- EGLSurface mSurface;
- EGLint mWidth;
- EGLint mHeight;
- EGLint mBufferAge;
-
- // Maps from 0,0 in top-left to 0,0 in bottom-left
- // If out is not an EGLint[4] you're going to have a bad time
- void map(const SkRect& in, EGLint* out) const;
-};
// This class contains the shared global EGL objects, such as EGLDisplay
// and EGLConfig, which are re-used by CanvasContext
diff --git a/libs/hwui/renderthread/Frame.cpp b/libs/hwui/renderthread/Frame.cpp
new file mode 100644
index 0000000..126bb09
--- /dev/null
+++ b/libs/hwui/renderthread/Frame.cpp
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#include "Frame.h"
+#include <SkRect.h>
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+void Frame::map(const SkRect& in, int32_t* out) const {
+ /* The rectangles are specified relative to the bottom-left of the surface
+ * and the x and y components of each rectangle specify the bottom-left
+ * position of that rectangle.
+ *
+ * HWUI does everything with 0,0 being top-left, so need to map
+ * the rect
+ */
+ SkIRect idirty;
+ in.roundOut(&idirty);
+ int32_t y = mHeight - (idirty.y() + idirty.height());
+ // layout: {x, y, width, height}
+ out[0] = idirty.x();
+ out[1] = y;
+ out[2] = idirty.width();
+ out[3] = idirty.height();
+}
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/Frame.h b/libs/hwui/renderthread/Frame.h
new file mode 100644
index 0000000..99996fe
--- /dev/null
+++ b/libs/hwui/renderthread/Frame.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+struct SkRect;
+typedef void *EGLSurface;
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+class Frame {
+public:
+ Frame(int32_t width, int32_t height, int32_t bufferAge)
+ : mWidth(width)
+ , mHeight(height)
+ , mBufferAge(bufferAge) { }
+
+ int32_t width() const { return mWidth; }
+ int32_t height() const { return mHeight; }
+
+ // See: https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_buffer_age.txt
+ // for what this means
+ int32_t bufferAge() const { return mBufferAge; }
+
+private:
+ Frame() {}
+ friend class EglManager;
+
+ int32_t mWidth;
+ int32_t mHeight;
+ int32_t mBufferAge;
+
+ EGLSurface mSurface;
+
+ // Maps from 0,0 in top-left to 0,0 in bottom-left
+ // If out is not an int32_t[4] you're going to have a bad time
+ void map(const SkRect& in, int32_t* out) const;
+};
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
+
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 0e4000b..45f6718 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -17,7 +17,6 @@
#pragma once
#include "FrameInfoVisualizer.h"
-#include "EglManager.h"
#include <SkRect.h>
#include <utils/RefBase.h>
diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp
index 9dc2b59..df08599 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.cpp
+++ b/libs/hwui/renderthread/OpenGLPipeline.cpp
@@ -18,6 +18,7 @@
#include "DeferredLayerUpdater.h"
#include "EglManager.h"
+#include "Frame.h"
#include "ProfileRenderer.h"
#include "renderstate/RenderState.h"
#include "OpenGLReadback.h"
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 4d239bc..68c04af 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -17,6 +17,7 @@
#include "VulkanManager.h"
#include "DeviceInfo.h"
+#include "Properties.h"
#include "RenderThread.h"
#include <GrContext.h>
@@ -100,6 +101,10 @@
mRenderThread.setGrContext(GrContext::Create(kVulkan_GrBackend,
(GrBackendContext) mBackendContext.get()));
DeviceInfo::initialize(mRenderThread.getGrContext()->caps()->maxRenderTargetSize());
+
+ if (Properties::enablePartialUpdates && Properties::useBufferAge) {
+ mSwapBehavior = SwapBehavior::BufferAge;
+ }
}
// Returns the next BackbufferInfo to use for the next draw. The function will make sure all
@@ -162,7 +167,7 @@
}
// set up layout transfer from initial to color attachment
- VkImageLayout layout = surface->mImageLayouts[backbuffer->mImageIndex];
+ VkImageLayout layout = surface->mImageInfos[backbuffer->mImageIndex].mImageLayout;
SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout || VK_IMAGE_LAYOUT_PRESENT_SRC_KHR == layout);
VkPipelineStageFlags srcStageMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ?
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT :
@@ -215,7 +220,7 @@
// We need to notify Skia that we changed the layout of the wrapped VkImage
GrVkImageInfo* imageInfo;
- sk_sp<SkSurface> skSurface = surface->mSurfaces[backbuffer->mImageIndex];
+ sk_sp<SkSurface> skSurface = surface->mImageInfos[backbuffer->mImageIndex].mSurface;
skSurface->getRenderTargetHandle((GrBackendObject*)&imageInfo,
SkSurface::kFlushRead_BackendHandleAccess);
imageInfo->updateImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
@@ -243,10 +248,8 @@
delete[] surface->mBackbuffers;
surface->mBackbuffers = nullptr;
- delete[] surface->mSurfaces;
- surface->mSurfaces = nullptr;
- delete[] surface->mImageLayouts;
- surface->mImageLayouts = nullptr;
+ delete[] surface->mImageInfos;
+ surface->mImageInfos = nullptr;
delete[] surface->mImages;
surface->mImages = nullptr;
}
@@ -286,8 +289,7 @@
GrPixelConfig config = wantSRGB ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig;
// set up initial image layouts and create surfaces
- surface->mImageLayouts = new VkImageLayout[surface->mImageCount];
- surface->mSurfaces = new sk_sp<SkSurface>[surface->mImageCount];
+ surface->mImageInfos = new VulkanSurface::ImageInfo[surface->mImageCount];
for (uint32_t i = 0; i < surface->mImageCount; ++i) {
GrBackendRenderTargetDesc desc;
GrVkImageInfo info;
@@ -306,9 +308,9 @@
desc.fStencilBits = 0;
desc.fRenderTargetHandle = (GrBackendObject) &info;
- surface->mSurfaces[i] = SkSurface::MakeFromBackendRenderTarget(mRenderThread.getGrContext(),
+ VulkanSurface::ImageInfo& imageInfo = surface->mImageInfos[i];
+ imageInfo.mSurface = SkSurface::MakeFromBackendRenderTarget(mRenderThread.getGrContext(),
desc, &props);
- surface->mImageLayouts[i] = VK_IMAGE_LAYOUT_UNDEFINED;
}
SkASSERT(mCommandPool != VK_NULL_HANDLE);
@@ -595,7 +597,7 @@
VulkanSurface::BackbufferInfo* backbuffer = surface->mBackbuffers +
surface->mCurrentBackbufferIndex;
GrVkImageInfo* imageInfo;
- SkSurface* skSurface = surface->mSurfaces[backbuffer->mImageIndex].get();
+ SkSurface* skSurface = surface->mImageInfos[backbuffer->mImageIndex].mSurface.get();
skSurface->getRenderTargetHandle((GrBackendObject*)&imageInfo,
SkSurface::kFlushRead_BackendHandleAccess);
// Check to make sure we never change the actually wrapped image
@@ -632,7 +634,7 @@
0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
mEndCommandBuffer(backbuffer->mTransitionCmdBuffers[1]);
- surface->mImageLayouts[backbuffer->mImageIndex] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ surface->mImageInfos[backbuffer->mImageIndex].mImageLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
// insert the layout transfer into the queue and wait on the acquire
VkSubmitInfo submitInfo;
@@ -668,6 +670,20 @@
mQueuePresentKHR(mPresentQueue, &presentInfo);
surface->mBackbuffer.reset();
+ surface->mImageInfos[backbuffer->mImageIndex].mLastUsed = surface->mCurrentTime;
+ surface->mImageInfos[backbuffer->mImageIndex].mInvalid = false;
+ surface->mCurrentTime++;
+}
+
+int VulkanManager::getAge(VulkanSurface* surface) {
+ VulkanSurface::BackbufferInfo* backbuffer = surface->mBackbuffers +
+ surface->mCurrentBackbufferIndex;
+ if (mSwapBehavior == SwapBehavior::Discard
+ || surface->mImageInfos[backbuffer->mImageIndex].mInvalid) {
+ return 0;
+ }
+ uint16_t lastUsed = surface->mImageInfos[backbuffer->mImageIndex].mLastUsed;
+ return surface->mCurrentTime - lastUsed;
}
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index f0e3320..d225b3f 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -46,6 +46,13 @@
VkFence mUsageFences[2];
};
+ struct ImageInfo {
+ VkImageLayout mImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ sk_sp<SkSurface> mSurface;
+ uint16_t mLastUsed = 0;
+ bool mInvalid = true;
+ };
+
sk_sp<SkSurface> mBackbuffer;
VkSurfaceKHR mVkSurface = VK_NULL_HANDLE;
@@ -56,8 +63,8 @@
uint32_t mImageCount;
VkImage* mImages;
- VkImageLayout* mImageLayouts;
- sk_sp<SkSurface>* mSurfaces;
+ ImageInfo* mImageInfos;
+ uint16_t mCurrentTime = 0;
};
// This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue,
@@ -87,6 +94,8 @@
// VulkanSurface is passed into them so we just return true here.
bool isCurrent(VulkanSurface* surface) { return true; }
+ int getAge(VulkanSurface* surface);
+
// Returns an SkSurface which wraps the next image returned from vkAcquireNextImageKHR. It also
// will transition the VkImage from a present layout to color attachment so that it can be used
// by the client for drawing.
@@ -161,6 +170,12 @@
uint32_t mPresentQueueIndex;
VkQueue mPresentQueue = VK_NULL_HANDLE;
VkCommandPool mCommandPool = VK_NULL_HANDLE;
+
+ enum class SwapBehavior {
+ Discard,
+ BufferAge,
+ };
+ SwapBehavior mSwapBehavior = SwapBehavior::Discard;
};
} /* namespace renderthread */
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 9530c79..5f6bcb3 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -22,6 +22,9 @@
#include <renderthread/EglManager.h>
#include <renderthread/OpenGLPipeline.h>
#include <utils/Unicode.h>
+#include <SkClipStack.h>
+
+#include <SkGlyphCache.h>
namespace android {
namespace uirenderer {
@@ -164,5 +167,23 @@
return 0;
}
+SkRect TestUtils::getClipBounds(const SkCanvas* canvas) {
+ SkClipStack::BoundsType boundType;
+ SkRect clipBounds;
+ canvas->getClipStack()->getBounds(&clipBounds, &boundType);
+ return clipBounds;
+}
+
+SkRect TestUtils::getLocalClipBounds(const SkCanvas* canvas) {
+ SkMatrix invertedTotalMatrix;
+ if (!canvas->getTotalMatrix().invert(&invertedTotalMatrix)) {
+ return SkRect::MakeEmpty();
+ }
+ SkRect outlineInDeviceCoord = TestUtils::getClipBounds(canvas);
+ SkRect outlineInLocalCoord;
+ invertedTotalMatrix.mapRect(&outlineInLocalCoord, outlineInDeviceCoord);
+ return outlineInLocalCoord;
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 0ce598d..80cbb24 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -118,7 +118,8 @@
static std::unique_ptr<Snapshot> makeSnapshot(const Matrix4& transform, const Rect& clip) {
std::unique_ptr<Snapshot> snapshot(new Snapshot());
- snapshot->clip(clip, SkRegion::kReplace_Op); // store clip first, so it isn't transformed
+ // store clip first, so it isn't transformed
+ snapshot->setClip(clip.left, clip.top, clip.right, clip.bottom);
*(snapshot->transform) = transform;
return snapshot;
}
@@ -292,6 +293,9 @@
static SkColor getColor(const sk_sp<SkSurface>& surface, int x, int y);
+ static SkRect getClipBounds(const SkCanvas* canvas);
+ static SkRect getLocalClipBounds(const SkCanvas* canvas);
+
private:
static void syncHierarchyPropertiesAndDisplayListImpl(RenderNode* node) {
node->syncProperties();
diff --git a/libs/hwui/tests/common/scenes/BitmapShaders.cpp b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
index 9b0b950..e03c9e8 100644
--- a/libs/hwui/tests/common/scenes/BitmapShaders.cpp
+++ b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
@@ -17,6 +17,7 @@
#include "TestSceneBase.h"
#include "utils/Color.h"
#include "tests/common/BitmapAllocationTestUtils.h"
+#include <SkImagePriv.h>
class BitmapShaders;
@@ -70,4 +71,4 @@
void doFrame(int frameNr) override { }
BitmapAllocationTestUtils::BitmapAllocator mAllocator;
-};
\ No newline at end of file
+};
diff --git a/libs/hwui/tests/common/scenes/ClippingAnimation.cpp b/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
index 8f2ba2d..f47e05a 100644
--- a/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
@@ -34,11 +34,11 @@
[](RenderProperties& props, Canvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
{
- canvas.clipRect(0, 0, 200, 200, SkRegion::kIntersect_Op);
+ canvas.clipRect(0, 0, 200, 200, SkClipOp::kIntersect);
canvas.translate(100, 100);
canvas.rotate(45);
canvas.translate(-100, -100);
- canvas.clipRect(0, 0, 200, 200, SkRegion::kIntersect_Op);
+ canvas.clipRect(0, 0, 200, 200, SkClipOp::kIntersect);
canvas.drawColor(Color::Blue_500, SkBlendMode::kSrcOver);
}
canvas.restore();
@@ -47,7 +47,7 @@
{
SkPath clipCircle;
clipCircle.addCircle(100, 300, 100);
- canvas.clipPath(&clipCircle, SkRegion::kIntersect_Op);
+ canvas.clipPath(&clipCircle, SkClipOp::kIntersect);
canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
}
canvas.restore();
diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
new file mode 100644
index 0000000..83b01e9
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#include "TestSceneBase.h"
+#include "utils/Color.h"
+
+#include <gui/IGraphicBufferAlloc.h>
+#include <gui/ISurfaceComposer.h>
+#include <private/gui/ComposerService.h>
+#include <binder/IServiceManager.h>
+#include <ui/PixelFormat.h>
+#include <SkGradientShader.h>
+#include <SkImagePriv.h>
+
+class HwBitmapInCompositeShader;
+
+static TestScene::Registrar _HwBitmapInCompositeShader(TestScene::Info{
+ "hwbitmapcompositeshader",
+ "Draws composite shader with hardware bitmap",
+ TestScene::simpleCreateScene<HwBitmapInCompositeShader>
+});
+
+class HwBitmapInCompositeShader : public TestScene {
+public:
+ sp<RenderNode> card;
+ void createContent(int width, int height, Canvas& canvas) override {
+ canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
+
+ status_t error;
+ sp<ISurfaceComposer> composer(ComposerService::getComposerService());
+ sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
+ uint32_t usage = GraphicBuffer::USAGE_HW_TEXTURE
+ | GraphicBuffer::USAGE_SW_READ_NEVER
+ | GRALLOC_USAGE_SW_WRITE_RARELY;
+ sp<GraphicBuffer> buffer = alloc->createGraphicBuffer(400, 200, PIXEL_FORMAT_RGBA_8888, 1,
+ usage, &error);
+
+ unsigned char* pixels = nullptr;
+ buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, ((void**)&pixels));
+ size_t size = bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride()
+ * buffer->getHeight();
+ memset(pixels, 0, size);
+ for (int i = 0; i < 6000; i++) {
+ pixels[4000 + 4 * i + 0] = 255;
+ pixels[4000 + 4 * i + 1] = 255;
+ pixels[4000 + 4 * i + 2] = 0;
+ pixels[4000 + 4 * i + 3] = 255;
+ }
+ buffer->unlock();
+ sk_sp<Bitmap> hardwareBitmap(Bitmap::createFrom(buffer));
+ sk_sp<SkShader> hardwareShader(createBitmapShader(*hardwareBitmap));
+
+ SkPoint center;
+ center.set(50, 50);
+ SkColor colors[2];
+ colors[0] = Color::Black;
+ colors[1] = Color::White;
+ sk_sp<SkShader> gradientShader = SkGradientShader::MakeRadial(center, 50, colors, nullptr,
+ 2, SkShader::TileMode::kRepeat_TileMode);
+
+ sk_sp<SkShader> compositeShader(
+ SkShader::MakeComposeShader(hardwareShader, gradientShader, SkBlendMode::kDstATop));
+
+ SkPaint paint;
+ paint.setShader(std::move(compositeShader));
+ canvas.drawRoundRect(0, 0, 400, 200, 10.0f, 10.0f, paint);
+ }
+
+ void doFrame(int frameNr) override { }
+
+ sk_sp<SkShader> createBitmapShader(Bitmap& bitmap) {
+ SkBitmap skBitmap;
+ bitmap.getSkBitmapForShaders(&skBitmap);
+ sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skBitmap, kNever_SkCopyPixelsMode);
+ return image->makeShader(SkShader::TileMode::kClamp_TileMode,
+ SkShader::TileMode::kClamp_TileMode);
+ }
+};
\ No newline at end of file
diff --git a/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
index 3630935..7e8a7d9 100644
--- a/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
@@ -36,7 +36,7 @@
// nested clipped saveLayers
canvas.saveLayerAlpha(0, 0, 400, 400, 200, SaveFlags::ClipToLayer);
canvas.drawColor(Color::Green_700, SkBlendMode::kSrcOver);
- canvas.clipRect(50, 50, 350, 350, SkRegion::kIntersect_Op);
+ canvas.clipRect(50, 50, 350, 350, SkClipOp::kIntersect);
canvas.saveLayerAlpha(100, 100, 300, 300, 128, SaveFlags::ClipToLayer);
canvas.drawColor(Color::Blue_500, SkBlendMode::kSrcOver);
canvas.restore();
diff --git a/libs/hwui/tests/common/scenes/ShapeAnimation.cpp b/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
index 5ef8773..09e70eb 100644
--- a/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
@@ -82,7 +82,7 @@
int middleCount = canvas.save(SaveFlags::MatrixClip);
for (auto op : ops) {
int innerCount = canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(0, 0, cellSize, cellSize, SkRegion::kIntersect_Op);
+ canvas.clipRect(0, 0, cellSize, cellSize, SkClipOp::kIntersect);
canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
op(canvas, cellSize, paint);
canvas.restoreToCount(innerCount);
diff --git a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
index bbaf267..f166c5c 100644
--- a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
@@ -177,7 +177,7 @@
// Clip to padding
// Can expect ~25% of views to have clip to padding with a non-null padding
int clipRestoreCount = canvas->save(SaveFlags::MatrixClip);
- canvas->clipRect(1, 1, 199, 199, SkRegion::kIntersect_Op);
+ canvas->clipRect(1, 1, 199, 199, SkClipOp::kIntersect);
canvas->insertReorderBarrier(true);
diff --git a/libs/hwui/tests/unit/CanvasStateTests.cpp b/libs/hwui/tests/unit/CanvasStateTests.cpp
index 0afabd8..43974f6 100644
--- a/libs/hwui/tests/unit/CanvasStateTests.cpp
+++ b/libs/hwui/tests/unit/CanvasStateTests.cpp
@@ -23,7 +23,7 @@
#include <gtest/gtest.h>
#include <SkPath.h>
-#include <SkRegion.h>
+#include <SkClipOp.h>
namespace android {
namespace uirenderer {
@@ -68,13 +68,13 @@
state.initializeSaveStack(200, 200,
0, 0, 200, 200, Vector3());
- state.clipRect(0, 0, 100, 100, SkRegion::kIntersect_Op);
+ state.clipRect(0, 0, 100, 100, SkClipOp::kIntersect);
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(100, 100));
- state.clipRect(10, 10, 200, 200, SkRegion::kIntersect_Op);
+ state.clipRect(10, 10, 200, 200, SkClipOp::kIntersect);
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10, 100, 100));
- state.clipRect(50, 50, 150, 150, SkRegion::kReplace_Op);
+ state.clipRect(50, 50, 150, 150, SkClipOp::kReplace);
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(50, 50, 150, 150));
}
@@ -88,7 +88,7 @@
// rotated clip causes complex clip
state.rotate(10);
EXPECT_TRUE(state.clipIsSimple());
- state.clipRect(0, 0, 200, 200, SkRegion::kIntersect_Op);
+ state.clipRect(0, 0, 200, 200, SkClipOp::kIntersect);
EXPECT_FALSE(state.clipIsSimple());
}
state.restore();
@@ -97,7 +97,7 @@
{
// subtracted clip causes complex clip
EXPECT_TRUE(state.clipIsSimple());
- state.clipRect(50, 50, 150, 150, SkRegion::kDifference_Op);
+ state.clipRect(50, 50, 150, 150, SkClipOp::kDifference);
EXPECT_FALSE(state.clipIsSimple());
}
state.restore();
@@ -108,7 +108,7 @@
SkPath path;
path.addOval(SkRect::MakeWH(200, 200));
EXPECT_TRUE(state.clipIsSimple());
- state.clipPath(&path, SkRegion::kDifference_Op);
+ state.clipPath(&path, SkClipOp::kDifference);
EXPECT_FALSE(state.clipIsSimple());
}
state.restore();
@@ -121,7 +121,7 @@
state.save(SaveFlags::Clip);
{
- state.clipRect(0, 0, 10, 10, SkRegion::kIntersect_Op);
+ state.clipRect(0, 0, 10, 10, SkClipOp::kIntersect);
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));
}
state.restore();
@@ -145,7 +145,7 @@
state.save(SaveFlags::Matrix); // NOTE: clip not saved
{
- state.clipRect(0, 0, 10, 10, SkRegion::kIntersect_Op);
+ state.clipRect(0, 0, 10, 10, SkClipOp::kIntersect);
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));
}
state.restore();
diff --git a/libs/hwui/tests/unit/FatalTestCanvas.h b/libs/hwui/tests/unit/FatalTestCanvas.h
new file mode 100644
index 0000000..4831722
--- /dev/null
+++ b/libs/hwui/tests/unit/FatalTestCanvas.h
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <gtest/gtest.h>
+#include <SkCanvas.h>
+
+namespace {
+
+class TestCanvasBase : public SkCanvas {
+public:
+ TestCanvasBase(int width, int height) : SkCanvas(width, height) {
+ }
+ void onDrawAnnotation(const SkRect&, const char key[], SkData* value) {
+ ADD_FAILURE() << "onDrawAnnotation not expected in this test";
+ }
+ void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) {
+ ADD_FAILURE() << "onDrawDRRect not expected in this test";
+ }
+ void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
+ ADD_FAILURE() << "onDrawText not expected in this test";
+ }
+ void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint& paint) {
+ ADD_FAILURE() << "onDrawPosText not expected in this test";
+ }
+ void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
+ const SkPaint& paint) {
+ ADD_FAILURE() << "onDrawPosTextH not expected in this test";
+ }
+ void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint& paint) {
+ ADD_FAILURE() << "onDrawTextOnPath not expected in this test";
+ }
+ void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
+ const SkRect* cullRect, const SkPaint& paint) {
+ ADD_FAILURE() << "onDrawTextRSXform not expected in this test";
+ }
+ void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) {
+ ADD_FAILURE() << "onDrawTextBlob not expected in this test";
+ }
+ void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4],
+ SkBlendMode, const SkPaint& paint) {
+ ADD_FAILURE() << "onDrawPatch not expected in this test";
+ }
+ void onDrawPaint(const SkPaint&) {
+ ADD_FAILURE() << "onDrawPaint not expected in this test";
+ }
+ void onDrawRect(const SkRect&, const SkPaint&) {
+ ADD_FAILURE() << "onDrawRect not expected in this test";
+ }
+ void onDrawRegion(const SkRegion& region, const SkPaint& paint) {
+ ADD_FAILURE() << "onDrawRegion not expected in this test";
+ }
+ void onDrawOval(const SkRect&, const SkPaint&) {
+ ADD_FAILURE() << "onDrawOval not expected in this test";
+ }
+ void onDrawArc(const SkRect&, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
+ const SkPaint&) {
+ ADD_FAILURE() << "onDrawArc not expected in this test";
+ }
+ void onDrawRRect(const SkRRect&, const SkPaint&) {
+ ADD_FAILURE() << "onDrawRRect not expected in this test";
+ }
+ void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) {
+ ADD_FAILURE() << "onDrawPoints not expected in this test";
+ }
+ void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkBlendMode, const uint16_t indices[], int indexCount,
+ const SkPaint&) {
+ ADD_FAILURE() << "onDrawVertices not expected in this test";
+ }
+ void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int count,
+ SkBlendMode, const SkRect* cull, const SkPaint*) {
+ ADD_FAILURE() << "onDrawAtlas not expected in this test";
+ }
+ void onDrawPath(const SkPath&, const SkPaint&) {
+ ADD_FAILURE() << "onDrawPath not expected in this test";
+ }
+ void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*) {
+ ADD_FAILURE() << "onDrawImage not expected in this test";
+ }
+ void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
+ SrcRectConstraint) {
+ ADD_FAILURE() << "onDrawImageRect not expected in this test";
+ }
+ void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst, const SkPaint*) {
+ ADD_FAILURE() << "onDrawImageNine not expected in this test";
+ }
+ void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
+ const SkPaint*) {
+ ADD_FAILURE() << "onDrawImageLattice not expected in this test";
+ }
+ void onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const SkPaint*) {
+ ADD_FAILURE() << "onDrawBitmap not expected in this test";
+ }
+ void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
+ SrcRectConstraint) {
+ ADD_FAILURE() << "onDrawBitmapRect not expected in this test";
+ }
+ void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
+ const SkPaint*) {
+ ADD_FAILURE() << "onDrawBitmapNine not expected in this test";
+ }
+ void onDrawBitmapLattice(const SkBitmap&, const Lattice& lattice, const SkRect& dst,
+ const SkPaint*) {
+ ADD_FAILURE() << "onDrawBitmapLattice not expected in this test";
+ }
+ void onClipRRect(const SkRRect& rrect, SkClipOp, ClipEdgeStyle) {
+ ADD_FAILURE() << "onClipRRect not expected in this test";
+ }
+ void onClipPath(const SkPath& path, SkClipOp, ClipEdgeStyle) {
+ ADD_FAILURE() << "onClipPath not expected in this test";
+ }
+ void onClipRegion(const SkRegion& deviceRgn, SkClipOp) {
+ ADD_FAILURE() << "onClipRegion not expected in this test";
+ }
+ void onDiscard() {
+ ADD_FAILURE() << "onDiscard not expected in this test";
+ }
+ void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) {
+ ADD_FAILURE() << "onDrawPicture not expected in this test";
+ }
+
+ int mDrawCounter = 0; //counts how may draw calls of any kind were made to this canvas
+};
+
+}
\ No newline at end of file
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index a1c225f..21394ae 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -174,7 +174,7 @@
auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
[](RenderProperties& props, RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op); // intersection should be empty
+ canvas.clipRect(200, 200, 400, 400, SkClipOp::kIntersect); // intersection should be empty
canvas.drawRect(0, 0, 400, 400, SkPaint());
canvas.restore();
});
@@ -453,19 +453,19 @@
sk_sp<Bitmap> bitmap(TestUtils::createBitmap(20, 20));
// left side clipped (to inset left half)
- canvas.clipRect(10, 0, 50, 100, SkRegion::kReplace_Op);
+ canvas.clipRect(10, 0, 50, 100, SkClipOp::kReplace);
canvas.drawBitmap(*bitmap, 0, 40, nullptr);
// top side clipped (to inset top half)
- canvas.clipRect(0, 10, 100, 50, SkRegion::kReplace_Op);
+ canvas.clipRect(0, 10, 100, 50, SkClipOp::kReplace);
canvas.drawBitmap(*bitmap, 40, 0, nullptr);
// right side clipped (to inset right half)
- canvas.clipRect(50, 0, 90, 100, SkRegion::kReplace_Op);
+ canvas.clipRect(50, 0, 90, 100, SkClipOp::kReplace);
canvas.drawBitmap(*bitmap, 80, 40, nullptr);
// bottom not clipped, just abutting (inset bottom half)
- canvas.clipRect(0, 50, 100, 90, SkRegion::kReplace_Op);
+ canvas.clipRect(0, 50, 100, 90, SkClipOp::kReplace);
canvas.drawBitmap(*bitmap, 40, 70, nullptr);
});
@@ -488,7 +488,7 @@
SkPath path;
path.addCircle(200, 200, 200, SkPath::kCW_Direction);
canvas.save(SaveFlags::MatrixClip);
- canvas.clipPath(&path, SkRegion::kIntersect_Op);
+ canvas.clipPath(&path, SkClipOp::kIntersect);
SkPaint paint;
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setAntiAlias(true);
@@ -649,7 +649,7 @@
auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
[&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(50, 50, 150, 150, SkRegion::kIntersect_Op);
+ canvas.clipRect(50, 50, 150, 150, SkClipOp::kIntersect);
canvas.drawLayer(layerUpdater.get());
canvas.restore();
});
@@ -973,7 +973,7 @@
auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
[](RenderProperties& props, RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op);
+ canvas.clipRect(200, 200, 400, 400, SkClipOp::kIntersect);
canvas.saveLayerAlpha(200, 200, 400, 400, 128, SaveFlags::ClipToLayer);
// draw within save layer may still be recorded, but shouldn't be drawn
@@ -1781,7 +1781,7 @@
auto child = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
[&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
// Record time clip will be ignored by projectee
- canvas.clipRect(100, 100, 300, 300, SkRegion::kIntersect_Op);
+ canvas.clipRect(100, 100, 300, 300, SkClipOp::kIntersect);
canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
canvas.drawRenderNode(projectingRipple.get());
@@ -1993,7 +1993,7 @@
[](RenderProperties& props, RecordingCanvas& canvas) {
// Apply a clip before the reorder barrier/shadow casting child is drawn.
// This clip must be applied to the shadow cast by the child.
- canvas.clipRect(25, 25, 75, 75, SkRegion::kIntersect_Op);
+ canvas.clipRect(25, 25, 75, 75, SkClipOp::kIntersect);
canvas.insertReorderBarrier(true);
canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
});
@@ -2252,7 +2252,7 @@
};
auto node = TestUtils::createNode<RecordingCanvas>(20, 20, 30, 30,
[](RenderProperties& props, RecordingCanvas& canvas) {
- canvas.clipRect(0, -20, 10, 30, SkRegion::kReplace_Op);
+ canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace);
canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
});
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index dda432e..4a73383 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -25,6 +25,7 @@
#include <utils/Color.h>
#include <SkGradientShader.h>
+#include <SkImagePriv.h>
#include <SkShader.h>
namespace android {
@@ -57,7 +58,7 @@
TEST(RecordingCanvas, clipRect) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [](RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(0, 0, 100, 100, SkRegion::kIntersect_Op);
+ canvas.clipRect(0, 0, 100, 100, SkClipOp::kIntersect);
canvas.drawRect(0, 0, 50, 50, SkPaint());
canvas.drawRect(50, 50, 100, 100, SkPaint());
canvas.restore();
@@ -73,8 +74,8 @@
TEST(RecordingCanvas, emptyClipRect) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(0, 0, 100, 100, SkRegion::kIntersect_Op);
- canvas.clipRect(100, 100, 200, 200, SkRegion::kIntersect_Op);
+ canvas.clipRect(0, 0, 100, 100, SkClipOp::kIntersect);
+ canvas.clipRect(100, 100, 200, 200, SkClipOp::kIntersect);
canvas.drawRect(0, 0, 50, 50, SkPaint()); // rejected at record time
canvas.restore();
});
@@ -440,7 +441,7 @@
TEST(RecordingCanvas, saveLayer_addClipFlag) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(10, 20, 190, 180, SkRegion::kIntersect_Op);
+ canvas.clipRect(10, 20, 190, 180, SkClipOp::kIntersect);
canvas.saveLayerAlpha(10, 20, 190, 180, 128, (SaveFlags::Flags)0); // unclipped
canvas.drawRect(10, 20, 190, 180, SkPaint());
canvas.restore();
@@ -459,7 +460,7 @@
TEST(RecordingCanvas, saveLayer_viewportCrop) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
// shouldn't matter, since saveLayer will clip to its bounds
- canvas.clipRect(-1000, -1000, 1000, 1000, SkRegion::kReplace_Op);
+ canvas.clipRect(-1000, -1000, 1000, 1000, SkClipOp::kReplace);
canvas.saveLayerAlpha(100, 100, 300, 300, 128, SaveFlags::ClipToLayer);
canvas.drawRect(0, 0, 400, 400, SkPaint());
@@ -549,7 +550,7 @@
canvas.save(SaveFlags::MatrixClip);
canvas.translate(0, -20); // avoid identity case
// empty clip rect should force layer + contents to be rejected
- canvas.clipRect(0, -20, 200, -20, SkRegion::kIntersect_Op);
+ canvas.clipRect(0, -20, 200, -20, SkClipOp::kIntersect);
canvas.saveLayerAlpha(0, 0, 200, 200, 128, SaveFlags::ClipToLayer);
canvas.drawRect(0, 0, 200, 200, SkPaint());
canvas.restore();
@@ -568,7 +569,7 @@
});
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [&child](RecordingCanvas& canvas) {
- canvas.clipRect(0, 0, 0, 0, SkRegion::kIntersect_Op); // empty clip, reject node
+ canvas.clipRect(0, 0, 0, 0, SkClipOp::kIntersect); // empty clip, reject node
canvas.drawRenderNode(child.get()); // shouldn't crash when rejecting node...
});
ASSERT_TRUE(dl->isEmpty());
@@ -621,7 +622,7 @@
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
// since no explicit clip set on canvas, this should be the one observed on op:
- canvas.clipRect(-100, -100, 300, 300, SkRegion::kIntersect_Op);
+ canvas.clipRect(-100, -100, 300, 300, SkClipOp::kIntersect);
SkPaint paint;
paint.setColor(SK_ColorWHITE);
@@ -637,7 +638,7 @@
TEST(RecordingCanvas, replaceClipIntersectWithRoot) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [](RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
- canvas.clipRect(-10, -10, 110, 110, SkRegion::kReplace_Op);
+ canvas.clipRect(-10, -10, 110, 110, SkClipOp::kReplace);
canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
canvas.restore();
});
@@ -675,7 +676,7 @@
canvas.drawRect(0, 0, 400, 400, SkPaint());
// second chunk: no recorded clip, since inorder region
- canvas.clipRect(0, 0, 200, 200, SkRegion::kIntersect_Op);
+ canvas.clipRect(0, 0, 200, 200, SkClipOp::kIntersect);
canvas.insertReorderBarrier(false);
canvas.drawRect(0, 0, 400, 400, SkPaint());
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index f4b686d..65eb169 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -29,6 +29,7 @@
#include <SkSurface_Base.h>
#include <SkLiteRecorder.h>
#include <SkClipStack.h>
+#include "FatalTestCanvas.h"
#include <string.h>
@@ -89,11 +90,11 @@
ZReorderCanvas(int width, int height) : SkCanvas(width, height) {}
void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
int expectedOrder = SkColorGetB(paint.getColor()); // extract order from blue channel
- EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order";
+ EXPECT_EQ(expectedOrder, mDrawCounter++) << "An op was drawn out of order";
}
- int getIndex() { return mIndex; }
+ int getIndex() { return mDrawCounter; }
protected:
- int mIndex = 0;
+ int mDrawCounter = 0;
};
} // end anonymous namespace
@@ -173,21 +174,6 @@
return new AnimationContext(clock);
}
};
-
-inline SkRect getBounds(const SkCanvas* canvas) {
- SkClipStack::BoundsType boundType;
- SkRect clipBounds;
- canvas->getClipStack()->getBounds(&clipBounds, &boundType);
- return clipBounds;
-}
-inline SkRect getLocalBounds(const SkCanvas* canvas) {
- SkMatrix invertedTotalMatrix;
- EXPECT_TRUE(canvas->getTotalMatrix().invert(&invertedTotalMatrix));
- SkRect outlineInDeviceCoord = getBounds(canvas);
- SkRect outlineInLocalCoord;
- invertedTotalMatrix.mapRect(&outlineInLocalCoord, outlineInDeviceCoord);
- return outlineInLocalCoord;
-}
} // end anonymous namespace
RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorder) {
@@ -197,26 +183,26 @@
public:
ProjectionTestCanvas(int width, int height) : SkCanvas(width, height) {}
void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
- const int index = mIndex++;
+ const int index = mDrawCounter++;
SkMatrix expectedMatrix;;
switch (index) {
case 0: //this is node "B"
EXPECT_EQ(SkRect::MakeWH(100, 100), rect);
EXPECT_EQ(SK_ColorWHITE, paint.getColor());
expectedMatrix.reset();
- EXPECT_EQ(SkRect::MakeLTRB(0, 0, 100, 100), getBounds(this));
+ EXPECT_EQ(SkRect::MakeLTRB(0, 0, 100, 100), TestUtils::getClipBounds(this));
break;
case 1: //this is node "P"
EXPECT_EQ(SkRect::MakeLTRB(-10, -10, 60, 60), rect);
EXPECT_EQ(SK_ColorDKGRAY, paint.getColor());
expectedMatrix.setTranslate(50 - SCROLL_X, 50 - SCROLL_Y);
- EXPECT_EQ(SkRect::MakeLTRB(-35, -30, 45, 50), getLocalBounds(this));
+ EXPECT_EQ(SkRect::MakeLTRB(-35, -30, 45, 50), TestUtils::getLocalClipBounds(this));
break;
case 2: //this is node "C"
EXPECT_EQ(SkRect::MakeWH(100, 50), rect);
EXPECT_EQ(SK_ColorBLUE, paint.getColor());
expectedMatrix.setTranslate(-SCROLL_X, 50 - SCROLL_Y);
- EXPECT_EQ(SkRect::MakeLTRB(0, 40, 95, 90), getBounds(this));
+ EXPECT_EQ(SkRect::MakeLTRB(0, 40, 95, 90), TestUtils::getClipBounds(this));
break;
default:
ADD_FAILURE();
@@ -224,9 +210,9 @@
EXPECT_EQ(expectedMatrix, getTotalMatrix());
}
- int getIndex() { return mIndex; }
+ int getIndex() { return mDrawCounter; }
protected:
- int mIndex = 0;
+ int mDrawCounter = 0;
};
/**
@@ -315,23 +301,23 @@
public:
ProjectionTestCanvas(int* drawCounter)
: SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT)
- , mDrawCounter(drawCounter)
+ , mDrawCounter(drawCounter)
{}
void onDrawArc(const SkRect&, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
const SkPaint&) override {
EXPECT_EQ(0, (*mDrawCounter)++); //part of painting the layer
- EXPECT_EQ(SkRect::MakeLTRB(0, 0, LAYER_WIDTH, LAYER_HEIGHT), getBounds(this));
+ EXPECT_EQ(SkRect::MakeLTRB(0, 0, LAYER_WIDTH, LAYER_HEIGHT), TestUtils::getClipBounds(this));
}
void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
EXPECT_EQ(1, (*mDrawCounter)++);
- EXPECT_EQ(SkRect::MakeLTRB(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT), getBounds(this));
+ EXPECT_EQ(SkRect::MakeLTRB(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT), TestUtils::getClipBounds(this));
}
void onDrawOval(const SkRect&, const SkPaint&) override {
EXPECT_EQ(2, (*mDrawCounter)++);
SkMatrix expectedMatrix;
expectedMatrix.setTranslate(100 - SCROLL_X, 100 - SCROLL_Y);
EXPECT_EQ(expectedMatrix, getTotalMatrix());
- EXPECT_EQ(SkRect::MakeLTRB(-85, -80, 295, 300), getLocalBounds(this));
+ EXPECT_EQ(SkRect::MakeLTRB(-85, -80, 295, 300), TestUtils::getLocalClipBounds(this));
}
int* mDrawCounter;
};
@@ -345,7 +331,7 @@
void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {
EXPECT_EQ(3, (*mDrawCounter)++);
EXPECT_EQ(SkRect::MakeLTRB(100 - SCROLL_X, 100 - SCROLL_Y, 300 - SCROLL_X,
- 300 - SCROLL_Y), getBounds(this->getCanvas()));
+ 300 - SCROLL_Y), TestUtils::getClipBounds(this->getCanvas()));
}
SkCanvas* onNewCanvas() override {
return new ProjectionTestCanvas(mDrawCounter);
@@ -440,15 +426,15 @@
public:
ProjectionChildScrollTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {}
void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
- EXPECT_EQ(0, mIndex++);
+ EXPECT_EQ(0, mDrawCounter++);
EXPECT_TRUE(getTotalMatrix().isIdentity());
}
void onDrawOval(const SkRect&, const SkPaint&) override {
- EXPECT_EQ(1, mIndex++);
- EXPECT_EQ(SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), getBounds(this));
+ EXPECT_EQ(1, mDrawCounter++);
+ EXPECT_EQ(SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), TestUtils::getClipBounds(this));
EXPECT_TRUE(getTotalMatrix().isIdentity());
}
- int mIndex = 0;
+ int mDrawCounter = 0;
};
auto receiverBackground = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
@@ -469,7 +455,7 @@
auto child = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
[&projectingRipple](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
// Record time clip will be ignored by projectee
- canvas.clipRect(100, 100, 300, 300, SkRegion::kIntersect_Op);
+ canvas.clipRect(100, 100, 300, 300, SkClipOp::kIntersect);
canvas.translate(-SCROLL_X, -SCROLL_Y); // Apply scroll (note: bg undoes this internally)
canvas.drawRenderNode(projectingRipple.get());
@@ -494,7 +480,7 @@
std::unique_ptr<ProjectionChildScrollTestCanvas> canvas(new ProjectionChildScrollTestCanvas());
RenderNodeDrawable drawable(parent.get(), canvas.get(), true);
canvas->drawDrawable(&drawable);
- EXPECT_EQ(2, canvas->mIndex);
+ EXPECT_EQ(2, canvas->mDrawCounter);
}
namespace {
@@ -787,3 +773,124 @@
}); //nodeA
EXPECT_EQ(5, drawNode(renderThread, nodeA));
}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, simple) {
+ static const int CANVAS_WIDTH = 100;
+ static const int CANVAS_HEIGHT = 200;
+ class SimpleTestCanvas : public TestCanvasBase {
+ public:
+ SimpleTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {
+ }
+ void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
+ EXPECT_EQ(0, mDrawCounter++);
+ }
+ void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*) override {
+ EXPECT_EQ(1, mDrawCounter++);
+ }
+ };
+
+ auto node = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ sk_sp<Bitmap> bitmap(TestUtils::createBitmap(25, 25));
+ canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, SkPaint());
+ canvas.drawBitmap(*bitmap, 10, 10, nullptr);
+ });
+
+ SimpleTestCanvas canvas;
+ RenderNodeDrawable drawable(node.get(), &canvas, true);
+ canvas.drawDrawable(&drawable);
+ EXPECT_EQ(2, canvas.mDrawCounter);
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, colorOp_unbounded) {
+ static const int CANVAS_WIDTH = 200;
+ static const int CANVAS_HEIGHT = 200;
+ class ColorTestCanvas : public TestCanvasBase {
+ public:
+ ColorTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {
+ }
+ void onDrawPaint(const SkPaint&) {
+ switch (mDrawCounter++) {
+ case 0:
+ // While this mirrors FrameBuilder::colorOp_unbounded, this value is different
+ // because there is no root (root is clipped in SkiaPipeline::renderFrame).
+ // SkiaPipeline.clipped and clip_replace verify the root clip.
+ EXPECT_TRUE(TestUtils::getClipBounds(this).isEmpty());
+ break;
+ case 1:
+ EXPECT_EQ(SkRect::MakeWH(10, 10), TestUtils::getClipBounds(this));
+ break;
+ default:
+ ADD_FAILURE();
+ }
+ }
+ };
+
+ auto unclippedColorView = TestUtils::createSkiaNode(0, 0, 10, 10,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ props.setClipToBounds(false);
+ canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
+ });
+
+ auto clippedColorView = TestUtils::createSkiaNode(0, 0, 10, 10,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
+ });
+
+ ColorTestCanvas canvas;
+ RenderNodeDrawable drawable(unclippedColorView.get(), &canvas, true);
+ canvas.drawDrawable(&drawable);
+ EXPECT_EQ(1, canvas.mDrawCounter);
+ RenderNodeDrawable drawable2(clippedColorView.get(), &canvas, true);
+ canvas.drawDrawable(&drawable2);
+ EXPECT_EQ(2, canvas.mDrawCounter);
+}
+
+TEST(RenderNodeDrawable, renderNode) {
+ static const int CANVAS_WIDTH = 200;
+ static const int CANVAS_HEIGHT = 200;
+ class RenderNodeTestCanvas : public TestCanvasBase {
+ public:
+ RenderNodeTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {
+ }
+ void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
+ switch(mDrawCounter++) {
+ case 0:
+ EXPECT_EQ(SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), TestUtils::getClipBounds(this));
+ EXPECT_EQ(SK_ColorDKGRAY, paint.getColor());
+ break;
+ case 1:
+ EXPECT_EQ(SkRect::MakeLTRB(50, 50, 150, 150), TestUtils::getClipBounds(this));
+ EXPECT_EQ(SK_ColorWHITE, paint.getColor());
+ break;
+ default:
+ ADD_FAILURE();
+ }
+ }
+ };
+
+ auto child = TestUtils::createSkiaNode(10, 10, 110, 110,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 100, 100, paint);
+ });
+
+ auto parent = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ [&child](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ SkPaint paint;
+ paint.setColor(SK_ColorDKGRAY);
+ canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, paint);
+
+ canvas.save(SaveFlags::MatrixClip);
+ canvas.translate(40, 40);
+ canvas.drawRenderNode(child.get());
+ canvas.restore();
+ });
+
+ RenderNodeTestCanvas canvas;
+ RenderNodeDrawable drawable(parent.get(), &canvas, true);
+ canvas.drawDrawable(&drawable);
+ EXPECT_EQ(2, canvas.mDrawCounter);
+}
+
diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
index 17801af..9e20498 100644
--- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp
+++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
@@ -26,7 +26,9 @@
#include "renderthread/CanvasContext.h"
#include "tests/common/TestUtils.h"
#include "SkiaCanvas.h"
+#include <SkClipStack.h>
#include <SkLiteRecorder.h>
+#include <SkSurface_Base.h>
#include <string.h>
using namespace android;
@@ -53,44 +55,6 @@
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
}
-RENDERTHREAD_TEST(SkiaPipeline, renderFrameCheckBounds) {
- auto backdropRedNode = TestUtils::createSkiaNode(1, 1, 4, 4,
- [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
- redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
- });
- auto contentGreenNode = TestUtils::createSkiaNode(2, 2, 5, 5,
- [](RenderProperties& props, SkiaRecordingCanvas& blueCanvas) {
- blueCanvas.drawColor(SK_ColorGREEN, SkBlendMode::kSrcOver);
- });
- LayerUpdateQueue layerUpdateQueue;
- SkRect dirty = SkRect::MakeLargest();
- std::vector<sp<RenderNode>> renderNodes;
- renderNodes.push_back(backdropRedNode); //first node is backdrop
- renderNodes.push_back(contentGreenNode); //second node is content drawn on top of the backdrop
- android::uirenderer::Rect contentDrawBounds(1, 1, 3, 3);
- auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
- auto surface = SkSurface::MakeRasterN32Premul(5, 5);
- surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
- ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
- //backdropBounds is (1, 1, 3, 3), content clip is (1, 1, 3, 3), content translate is (0, 0)
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface);
- ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
- ASSERT_EQ(TestUtils::getColor(surface, 1, 1), SK_ColorRED);
- ASSERT_EQ(TestUtils::getColor(surface, 2, 2), SK_ColorGREEN);
- ASSERT_EQ(TestUtils::getColor(surface, 3, 3), SK_ColorRED);
- ASSERT_EQ(TestUtils::getColor(surface, 4, 4), SK_ColorBLUE);
-
- surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
- contentDrawBounds.set(0, 0, 5, 5);
- //backdropBounds is (1, 1, 4, 4), content clip is (0, 0, 3, 3), content translate is (1, 1)
- pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface);
- ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
- ASSERT_EQ(TestUtils::getColor(surface, 1, 1), SK_ColorRED);
- ASSERT_EQ(TestUtils::getColor(surface, 2, 2), SK_ColorRED);
- ASSERT_EQ(TestUtils::getColor(surface, 3, 3), SK_ColorGREEN);
- ASSERT_EQ(TestUtils::getColor(surface, 4, 4), SK_ColorBLUE);
-}
-
RENDERTHREAD_TEST(SkiaPipeline, renderFrameCheckOpaque) {
auto halfGreenNode = TestUtils::createSkiaNode(0, 0, 2, 2,
[](RenderProperties& props, SkiaRecordingCanvas& bottomHalfGreenCanvas) {
@@ -192,7 +156,8 @@
std::vector<sp<RenderNode>> renderNodes;
renderNodes.push_back(whiteNode);
bool opaque = true;
- android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1);
+ //empty contentDrawBounds is avoiding backdrop/content logic, which would lead to less overdraw
+ android::uirenderer::Rect contentDrawBounds(0, 0, 0, 0);
auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
auto surface = SkSurface::MakeRasterN32Premul(1, 1);
@@ -205,7 +170,9 @@
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);
// 1 Overdraw, should be blue blended onto white.
- renderNodes.push_back(whiteNode);
+ renderNodes.push_back(whiteNode); //this is the "content" node
+ renderNodes.push_back(whiteNode); //the "content" node above does not cause an overdraw, because
+ //it clips the first "background" node
pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffd0d0ff);
@@ -229,3 +196,159 @@
pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffff8080);
}
+
+namespace {
+template <typename T>
+class DeferLayer : public SkSurface_Base {
+public:
+ DeferLayer(T *canvas)
+ : SkSurface_Base(canvas->imageInfo(), nullptr)
+ , mCanvas(canvas) {
+ }
+ SkCanvas* onNewCanvas() override {
+ return mCanvas;
+ }
+ sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override {
+ return sk_sp<SkSurface>();
+ }
+ sk_sp<SkImage> onNewImageSnapshot(SkBudgeted, SkCopyPixelsMode) override {
+ return sk_sp<SkImage>();
+ }
+ void onCopyOnWrite(ContentChangeMode) override {}
+ T* mCanvas; // bare pointer, not owned/ref'd
+};
+}
+
+RENDERTHREAD_TEST(SkiaPipeline, deferRenderNodeScene) {
+ class DeferTestCanvas : public SkCanvas {
+ public:
+ DeferTestCanvas() : SkCanvas(800, 600) {}
+ void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
+ SkMatrix expected;
+ switch (mDrawCounter++) {
+ case 0:
+ // background - left side
+ EXPECT_EQ(SkRect::MakeLTRB(600, 100, 700, 500), TestUtils::getClipBounds(this));
+ expected.setTranslate(100, 100);
+ break;
+ case 1:
+ // background - top side
+ EXPECT_EQ(SkRect::MakeLTRB(100, 400, 600, 500), TestUtils::getClipBounds(this));
+ expected.setTranslate(100, 100);
+ break;
+ case 2:
+ // content
+ EXPECT_EQ(SkRect::MakeLTRB(100, 100, 700, 500), TestUtils::getClipBounds(this));
+ expected.setTranslate(-50, -50);
+ break;
+ case 3:
+ // overlay
+ EXPECT_EQ(SkRect::MakeLTRB(0, 0, 800, 600), TestUtils::getClipBounds(this));
+ expected.reset();
+ break;
+ default:
+ ADD_FAILURE() << "Too many rects observed";
+ }
+ EXPECT_EQ(expected, getTotalMatrix());
+ }
+ int mDrawCounter = 0;
+ };
+
+ std::vector<sp<RenderNode>> nodes;
+ SkPaint transparentPaint;
+ transparentPaint.setAlpha(128);
+
+ // backdrop
+ nodes.push_back(TestUtils::createSkiaNode(100, 100, 700, 500, // 600x400
+ [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ canvas.drawRect(0, 0, 600, 400, transparentPaint);
+ }));
+
+ // content
+ android::uirenderer::Rect contentDrawBounds(150, 150, 650, 450); // 500x300
+ nodes.push_back(TestUtils::createSkiaNode(0, 0, 800, 600,
+ [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ canvas.drawRect(0, 0, 800, 600, transparentPaint);
+ }));
+
+ // overlay
+ nodes.push_back(TestUtils::createSkiaNode(0, 0, 800, 600,
+ [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ canvas.drawRect(0, 0, 800, 200, transparentPaint);
+ }));
+
+ LayerUpdateQueue layerUpdateQueue;
+ SkRect dirty = SkRect::MakeWH(800, 600);
+ auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
+ DeferTestCanvas canvas;
+ sk_sp<SkSurface> surface(new DeferLayer<DeferTestCanvas>(&canvas));
+ pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, contentDrawBounds, surface);
+ EXPECT_EQ(4, canvas.mDrawCounter);
+}
+
+RENDERTHREAD_TEST(SkiaPipeline, clipped) {
+ static const int CANVAS_WIDTH = 200;
+ static const int CANVAS_HEIGHT = 200;
+ class ClippedTestCanvas : public SkCanvas {
+ public:
+ ClippedTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {
+ }
+ void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*) override {
+ EXPECT_EQ(0, mDrawCounter++);
+ EXPECT_EQ(SkRect::MakeLTRB(10, 20, 30, 40), TestUtils::getClipBounds(this));
+ EXPECT_TRUE(getTotalMatrix().isIdentity());
+ }
+ int mDrawCounter = 0;
+ };
+
+ std::vector<sp<RenderNode>> nodes;
+ nodes.push_back(TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ sk_sp<Bitmap> bitmap(TestUtils::createBitmap(CANVAS_WIDTH, CANVAS_HEIGHT));
+ canvas.drawBitmap(*bitmap, 0, 0, nullptr);
+ }));
+
+ LayerUpdateQueue layerUpdateQueue;
+ SkRect dirty = SkRect::MakeLTRB(10, 20, 30, 40);
+ auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
+ ClippedTestCanvas canvas;
+ sk_sp<SkSurface> surface(new DeferLayer<ClippedTestCanvas>(&canvas));
+ pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
+ SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
+ EXPECT_EQ(1, canvas.mDrawCounter);
+}
+
+RENDERTHREAD_TEST(SkiaPipeline, clip_replace) {
+ static const int CANVAS_WIDTH = 50;
+ static const int CANVAS_HEIGHT = 50;
+ class ClipReplaceTestCanvas : public SkCanvas {
+ public:
+ ClipReplaceTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {
+ }
+ void onDrawPaint(const SkPaint&) {
+ EXPECT_EQ(0, mDrawCounter++);
+ //TODO: this unit test is failing on the commented check below, because of a missing
+ //feature. In Snapshot::applyClip HWUI is intersecting the clip with the clip root,
+ //even for kReplace_Op clips. We need to implement the same for Skia pipelines.
+ //EXPECT_EQ(SkRect::MakeLTRB(20, 10, 30, 40), TestUtils::getClipBounds(this)) //got instead 20 0 30 50
+ // << "Expect resolved clip to be intersection of viewport clip and clip op";
+ }
+ int mDrawCounter = 0;
+ };
+
+ std::vector<sp<RenderNode>> nodes;
+ nodes.push_back(TestUtils::createSkiaNode(20, 20, 30, 30,
+ [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace);
+ canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
+ }));
+
+ LayerUpdateQueue layerUpdateQueue;
+ SkRect dirty = SkRect::MakeLTRB(10, 10, 40, 40);
+ auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
+ ClipReplaceTestCanvas canvas;
+ sk_sp<SkSurface> surface(new DeferLayer<ClipReplaceTestCanvas>(&canvas));
+ pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
+ SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
+ EXPECT_EQ(1, canvas.mDrawCounter);
+}
diff --git a/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp b/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp
new file mode 100644
index 0000000..e7171c8
--- /dev/null
+++ b/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+#include <VectorDrawable.h>
+
+#include "AnimationContext.h"
+#include "DamageAccumulator.h"
+#include "IContextFactory.h"
+#include "pipeline/skia/SkiaDisplayList.h"
+#include "pipeline/skia/SkiaPipeline.h"
+#include "pipeline/skia/SkiaRecordingCanvas.h"
+#include "renderthread/CanvasContext.h"
+#include "tests/common/TestUtils.h"
+#include "SkiaCanvas.h"
+#include <SkSurface_Base.h>
+#include <SkLiteRecorder.h>
+#include <SkClipStack.h>
+#include "FatalTestCanvas.h"
+#include <string.h>
+
+using namespace android;
+using namespace android::uirenderer;
+using namespace android::uirenderer::renderthread;
+using namespace android::uirenderer::skiapipeline;
+
+namespace {
+
+static void testProperty(std::function<void(RenderProperties&)> propSetupCallback,
+ std::function<void(const SkCanvas&)> opValidateCallback) {
+ static const int CANVAS_WIDTH = 100;
+ static const int CANVAS_HEIGHT = 100;
+ class PropertyTestCanvas : public TestCanvasBase {
+ public:
+ PropertyTestCanvas(std::function<void(const SkCanvas&)> callback)
+ : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT), mCallback(callback) {}
+ void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
+ EXPECT_EQ(mDrawCounter++, 0);
+ mCallback(*this);
+ }
+ void onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle style) {
+ SkCanvas::onClipRRect(rrect, op, style);
+ }
+ std::function<void(const SkCanvas&)> mCallback;
+ };
+
+ auto node = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ [propSetupCallback](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ propSetupCallback(props);
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, paint);
+ });
+
+ PropertyTestCanvas canvas(opValidateCallback);
+ RenderNodeDrawable drawable(node.get(), &canvas, true);
+ canvas.drawDrawable(&drawable);
+ EXPECT_EQ(1, canvas.mDrawCounter);
+}
+
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, renderPropClipping) {
+ testProperty([](RenderProperties& properties) {
+ properties.setClipToBounds(true);
+ properties.setClipBounds(android::uirenderer::Rect(10, 20, 300, 400));
+ }, [](const SkCanvas& canvas) {
+ EXPECT_EQ(SkRect::MakeLTRB(10, 20, 100, 100), TestUtils::getClipBounds(&canvas))
+ << "Clip rect should be intersection of node bounds and clip bounds";
+ });
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, renderPropRevealClip) {
+ testProperty([](RenderProperties& properties) {
+ properties.mutableRevealClip().set(true, 50, 50, 25);
+ }, [](const SkCanvas& canvas) {
+ SkClipStack::Iter it(*canvas.getClipStack(), SkClipStack::Iter::kBottom_IterStart);
+ const SkClipStack::Element *top = it.next();
+ ASSERT_NE(nullptr, top);
+ SkPath clip;
+ top->asPath(&clip);
+ SkRect rect;
+ EXPECT_TRUE(clip.isOval(&rect));
+ EXPECT_EQ(SkRect::MakeLTRB(25, 25, 75, 75), rect);
+ });
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, renderPropOutlineClip) {
+ testProperty([](RenderProperties& properties) {
+ properties.mutableOutline().setShouldClip(true);
+ properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f);
+ }, [](const SkCanvas& canvas) {
+ SkClipStack::Iter it(*canvas.getClipStack(), SkClipStack::Iter::kBottom_IterStart);
+ const SkClipStack::Element *top = it.next();
+ ASSERT_NE(nullptr, top);
+ SkPath clip;
+ top->asPath(&clip);
+ SkRRect rrect;
+ EXPECT_TRUE(clip.isRRect(&rrect));
+ EXPECT_EQ(SkRRect::MakeRectXY(SkRect::MakeLTRB(10, 20, 30, 40), 5.0f, 5.0f), rrect);
+ });
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, renderPropTransform) {
+ testProperty([](RenderProperties& properties) {
+ properties.setLeftTopRightBottom(10, 10, 110, 110);
+
+ SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f);
+ properties.setStaticMatrix(&staticMatrix);
+
+ // ignored, since static overrides animation
+ SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15);
+ properties.setAnimationMatrix(&animationMatrix);
+
+ properties.setTranslationX(10);
+ properties.setTranslationY(20);
+ properties.setScaleX(0.5f);
+ properties.setScaleY(0.7f);
+ }, [](const SkCanvas& canvas) {
+ Matrix4 matrix;
+ matrix.loadTranslate(10, 10, 0); // left, top
+ matrix.scale(1.2f, 1.2f, 1); // static matrix
+ // ignore animation matrix, since static overrides it
+
+ // translation xy
+ matrix.translate(10, 20);
+
+ // scale xy (from default pivot - center)
+ matrix.translate(50, 50);
+ matrix.scale(0.5f, 0.7f, 1);
+ matrix.translate(-50, -50);
+ Matrix4 actual(canvas.getTotalMatrix());
+ EXPECT_MATRIX_APPROX_EQ(matrix, actual)
+ << "Op draw matrix must match expected combination of transformation properties";
+ });
+}
diff --git a/libs/hwui/utils/TestWindowContext.cpp b/libs/hwui/utils/TestWindowContext.cpp
index fa3e13d..8b80d69 100644
--- a/libs/hwui/utils/TestWindowContext.cpp
+++ b/libs/hwui/utils/TestWindowContext.cpp
@@ -93,8 +93,7 @@
SkCanvas* prepareToDraw() {
//mCanvas->reset(mSize.width(), mSize.height());
- mCanvas->clipRect(0, 0, mSize.width(), mSize.height(),
- SkRegion::Op::kReplace_Op);
+ mCanvas->clipRect(0, 0, mSize.width(), mSize.height(), SkClipOp::kReplace);
return mCanvas->asSkCanvas();
}
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 93e86af..4c39c30 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -131,14 +131,11 @@
public String text;
public int requestorIdEncoding;
public int textEncoding;
- public Bundle extras;
};
public static class GpsNiResponse {
/* User response, one of the values in GpsUserResponseType */
int userResponse;
- /* Optional extra data to pass with the user response */
- Bundle extras;
};
private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
diff --git a/media/java/android/media/AsyncPlayer.java b/media/java/android/media/AsyncPlayer.java
index dd5f6ba..c1a178a 100644
--- a/media/java/android/media/AsyncPlayer.java
+++ b/media/java/android/media/AsyncPlayer.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.content.Context;
+import android.media.PlayerBase;
import android.net.Uri;
import android.os.PowerManager;
import android.os.SystemClock;
@@ -163,6 +164,7 @@
* @deprecated use {@link #play(Context, Uri, boolean, AudioAttributes)} instead
*/
public void play(Context context, Uri uri, boolean looping, int stream) {
+ PlayerBase.deprecateStreamTypeForPlayback(stream, "AsyncPlayer", "play()");
if (context == null || uri == null) {
return;
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 43fb4b9..16b3315 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -359,6 +359,9 @@
* for an AudioTrack instance in streaming mode.
* @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
* @throws java.lang.IllegalArgumentException
+ * @deprecated use {@link Builder} or
+ * {@link #AudioTrack(AudioAttributes, AudioFormat, int, int, int)} to specify the
+ * {@link AudioAttributes} instead of the stream type which is only for volume control.
*/
public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
int bufferSizeInBytes, int mode)
@@ -414,6 +417,9 @@
* @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
* @param sessionId Id of audio session the AudioTrack must be attached to
* @throws java.lang.IllegalArgumentException
+ * @deprecated use {@link Builder} or
+ * {@link #AudioTrack(AudioAttributes, AudioFormat, int, int, int)} to specify the
+ * {@link AudioAttributes} instead of the stream type which is only for volume control.
*/
public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
int bufferSizeInBytes, int mode, int sessionId)
@@ -429,6 +435,7 @@
.build(),
bufferSizeInBytes,
mode, sessionId);
+ deprecateStreamTypeForPlayback(streamType, "AudioTrack", "AudioTrack()");
}
/**
@@ -1044,11 +1051,12 @@
}
/**
- * Returns the type of audio stream this AudioTrack is configured for.
+ * Returns the volume stream type of this AudioTrack.
* Compare the result against {@link AudioManager#STREAM_VOICE_CALL},
* {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING},
* {@link AudioManager#STREAM_MUSIC}, {@link AudioManager#STREAM_ALARM},
- * {@link AudioManager#STREAM_NOTIFICATION}, or {@link AudioManager#STREAM_DTMF}.
+ * {@link AudioManager#STREAM_NOTIFICATION}, {@link AudioManager#STREAM_DTMF} or
+ * {@link AudioManager#STREAM_ACCESSIBILITY}.
*/
public int getStreamType() {
return mStreamType;
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index bbb7184..52d5b7ca 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -2765,23 +2765,28 @@
tag != null ? tag.name : null, dataFormat, numberOfComponents));
}
- if (tag == null || dataFormat <= 0 ||
- dataFormat >= IFD_FORMAT_BYTES_PER_FORMAT.length) {
- // Skip if the parsed tag number is not defined or invalid data format.
- if (DEBUG) {
- if (tag == null) {
- Log.w(TAG, "Skip tag entry since tag number is not defined: " + tagNumber);
- } else {
- Log.w(TAG, "Skip tag entry since data format is invalid: " + dataFormat);
- }
+ long byteCount = 0;
+ boolean valid = false;
+ if (tag == null) {
+ Log.w(TAG, "Skip the tag entry since tag number is not defined: " + tagNumber);
+ } else if (dataFormat <= 0 || dataFormat >= IFD_FORMAT_BYTES_PER_FORMAT.length) {
+ Log.w(TAG, "Skip the tag entry since data format is invalid: " + dataFormat);
+ } else {
+ byteCount = (long) numberOfComponents * IFD_FORMAT_BYTES_PER_FORMAT[dataFormat];
+ if (byteCount < 0 || byteCount > Integer.MAX_VALUE) {
+ Log.w(TAG, "Skip the tag entry since the number of components is invalid: "
+ + numberOfComponents);
+ } else {
+ valid = true;
}
+ }
+ if (!valid) {
dataInputStream.seek(nextEntryOffset);
continue;
}
// Read a value from data field or seek to the value offset which is stored in data
// field if the size of the entry value is bigger than 4.
- int byteCount = numberOfComponents * IFD_FORMAT_BYTES_PER_FORMAT[dataFormat];
if (byteCount > 4) {
int offset = dataInputStream.readInt();
if (DEBUG) {
@@ -2871,7 +2876,7 @@
continue;
}
- byte[] bytes = new byte[byteCount];
+ byte[] bytes = new byte[(int) byteCount];
dataInputStream.readFully(bytes);
ExifAttribute attribute = new ExifAttribute(dataFormat, numberOfComponents, bytes);
mAttributes[ifdType].put(tag.name, attribute);
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index eff5aac..78da59c 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -124,7 +124,7 @@
* is called. It is a programming error to invoke methods such
* as {@link #getCurrentPosition()},
* {@link #getDuration()}, {@link #getVideoHeight()},
- * {@link #getVideoWidth()}, {@link #setAudioStreamType(int)},
+ * {@link #getVideoWidth()}, {@link #setAudioAttributes(AudioAttributes)},
* {@link #setLooping(boolean)},
* {@link #setVolume(float, float)}, {@link #pause()}, {@link #start()},
* {@link #stop()}, {@link #seekTo(int, int)}, {@link #prepare()} or
@@ -410,7 +410,7 @@
* Error} </p></td>
* <td>This method must be called in idle state as the audio session ID must be known before
* calling setDataSource. Calling it does not change the object state. </p></td></tr>
- * <tr><td>setAudioStreamType </p></td>
+ * <tr><td>setAudioStreamType (deprecated)</p></td>
* <td>{Idle, Initialized, Stopped, Prepared, Started, Paused,
* PlaybackCompleted}</p></td>
* <td>{Error}</p></td>
@@ -822,7 +822,7 @@
* to free the resources. If not released, too many MediaPlayer instances will
* result in an exception.</p>
* <p>Note that since {@link #prepare()} is called automatically in this method,
- * you cannot change the audio stream type (see {@link #setAudioStreamType(int)}), audio
+ * you cannot change the audio
* session ID (see {@link #setAudioSessionId(int)}) or audio attributes
* (see {@link #setAudioAttributes(AudioAttributes)} of the new MediaPlayer.</p>
*
@@ -841,7 +841,7 @@
* to free the resources. If not released, too many MediaPlayer instances will
* result in an exception.</p>
* <p>Note that since {@link #prepare()} is called automatically in this method,
- * you cannot change the audio stream type (see {@link #setAudioStreamType(int)}), audio
+ * you cannot change the audio
* session ID (see {@link #setAudioSessionId(int)}) or audio attributes
* (see {@link #setAudioAttributes(AudioAttributes)} of the new MediaPlayer.</p>
*
@@ -904,7 +904,7 @@
* to free the resources. If not released, too many MediaPlayer instances will
* result in an exception.</p>
* <p>Note that since {@link #prepare()} is called automatically in this method,
- * you cannot change the audio stream type (see {@link #setAudioStreamType(int)}), audio
+ * you cannot change the audio
* session ID (see {@link #setAudioSessionId(int)}) or audio attributes
* (see {@link #setAudioAttributes(AudioAttributes)} of the new MediaPlayer.</p>
*
@@ -1843,9 +1843,11 @@
* thereafter.
*
* @param streamtype the audio stream type
+ * @deprecated use {@link #setAudioAttributes(AudioAttributes)}
* @see android.media.AudioManager
*/
public void setAudioStreamType(int streamtype) {
+ deprecateStreamTypeForPlayback(streamtype, "MediaPlayer", "setAudioStreamType()");
baseUpdateAudioAttributes(
new AudioAttributes.Builder().setInternalLegacyStreamType(streamtype).build());
_setAudioStreamType(streamtype);
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index 690a553..42f6b83 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -236,4 +236,28 @@
*/
abstract void playerSetVolume(boolean muting, float leftVolume, float rightVolume);
abstract int playerSetAuxEffectSendLevel(boolean muting, float level);
+
+ //=====================================================================
+ // Utilities
+
+ /**
+ * Use to generate warning or exception in legacy code paths that allowed passing stream types
+ * to qualify audio playback.
+ * @param streamType the stream type to check
+ * @throws IllegalArgumentException
+ */
+ public static void deprecateStreamTypeForPlayback(int streamType, String className,
+ String opName) throws IllegalArgumentException {
+ // STREAM_ACCESSIBILITY was introduced at the same time the use of stream types
+ // for audio playback was deprecated, so it is not allowed at all to qualify a playback
+ // use case
+ if (streamType == AudioManager.STREAM_ACCESSIBILITY) {
+ throw new IllegalArgumentException("Use of STREAM_ACCESSIBILITY is reserved for "
+ + "volume control");
+ }
+ Log.e(className, "Use of stream types is deprecated for operations other than " +
+ "volume control.");
+ Log.e(className, "See the documentation of " + opName + " for what to use instead with " +
+ "android.media.AudioAttributes to qualify your playback use case");
+ }
}
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 7767712..209ec42 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -103,6 +103,7 @@
*/
@Deprecated
public void setStreamType(int streamType) {
+ PlayerBase.deprecateStreamTypeForPlayback(streamType, "Ringtone", "setStreamType()");
setAudioAttributes(new AudioAttributes.Builder()
.setInternalLegacyStreamType(streamType)
.build());
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 3cb01de..de9f020 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -297,7 +297,7 @@
}
/**
- * Infers the playback stream type based on what type of ringtones this
+ * Infers the volume stream type based on what type of ringtones this
* manager is returning.
*
* @return The stream type.
@@ -616,6 +616,7 @@
return getRingtone(context, ringtoneUri, -1);
}
+ //FIXME bypass the notion of stream types within the class
/**
* Returns a {@link Ringtone} for a given sound URI on the given stream
* type. Normally, if you change the stream type on the returned
@@ -630,6 +631,7 @@
try {
final Ringtone r = new Ringtone(context, true);
if (streamType >= 0) {
+ //FIXME deprecated call
r.setStreamType(streamType);
}
r.setUri(ringtoneUri);
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index b429e22..838767c 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -24,6 +24,7 @@
import android.app.AppOpsManager;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
+import android.media.PlayerBase;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -146,6 +147,7 @@
public SoundPool(int maxStreams, int streamType, int srcQuality) {
this(maxStreams,
new AudioAttributes.Builder().setInternalLegacyStreamType(streamType).build());
+ PlayerBase.deprecateStreamTypeForPlayback(streamType, "SoundPool", "SoundPool()");
}
private SoundPool(int maxStreams, AudioAttributes attributes) {
diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java
index 99f93e4..9801949 100644
--- a/media/java/android/mtp/MtpServer.java
+++ b/media/java/android/mtp/MtpServer.java
@@ -72,6 +72,11 @@
native_remove_storage(storage.getStorageId());
}
+ public static void configure(boolean usePtp) {
+ native_configure(usePtp);
+ }
+
+ public static native final void native_configure(boolean usePtp);
private native final void native_setup(MtpDatabase database, boolean usePtp);
private native final void native_run();
private native final void native_cleanup();
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index d13187c..afd3082 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -56,17 +56,16 @@
return (MtpServer*)env->GetLongField(thiz, field_MtpServer_nativeContext);
}
+static void android_mtp_configure(JNIEnv *, jobject, jboolean usePtp) {
+ MtpServer::configure(usePtp);
+}
+
static void
android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jboolean usePtp)
{
- int fd = open("/dev/mtp_usb", O_RDWR);
- if (fd >= 0) {
- MtpServer* server = new MtpServer(fd, getMtpDatabase(env, javaDatabase),
- usePtp, AID_MEDIA_RW, 0664, 0775);
- env->SetLongField(thiz, field_MtpServer_nativeContext, (jlong)server);
- } else {
- ALOGE("could not open MTP driver, errno: %d", errno);
- }
+ MtpServer* server = new MtpServer(getMtpDatabase(env, javaDatabase),
+ usePtp, AID_MEDIA_RW, 0664, 0775);
+ env->SetLongField(thiz, field_MtpServer_nativeContext, (jlong)server);
}
static void
@@ -180,6 +179,7 @@
// ----------------------------------------------------------------------------
static const JNINativeMethod gMethods[] = {
+ {"native_configure", "(Z)V", (void *)android_mtp_configure},
{"native_setup", "(Landroid/mtp/MtpDatabase;Z)V",
(void *)android_mtp_MtpServer_setup},
{"native_run", "()V", (void *)android_mtp_MtpServer_run},
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index bb8eb2c..03f0b4d 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -55,12 +55,14 @@
import java.util.Random;
public class CaptivePortalLoginActivity extends Activity {
- private static final String TAG = "CaptivePortalLogin";
+ private static final String TAG = CaptivePortalLoginActivity.class.getSimpleName();
+ private static final boolean DBG = true;
+
private static final int SOCKET_TIMEOUT_MS = 10000;
private enum Result { DISMISSED, UNWANTED, WANTED_AS_IS };
- private URL mURL;
+ private URL mUrl;
private Network mNetwork;
private CaptivePortal mCaptivePortal;
private NetworkCallback mNetworkCallback;
@@ -72,17 +74,18 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCm = ConnectivityManager.from(this);
- String url = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL);
- if (url == null) url = mCm.getCaptivePortalServerUrl();
- try {
- mURL = new URL(url);
- } catch (MalformedURLException e) {
- // System misconfigured, bail out in a way that at least provides network access.
- Log.e(TAG, "Invalid captive portal URL, url=" + url);
- done(Result.WANTED_AS_IS);
- }
mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
+ mUrl = getUrl();
+ if (mUrl == null) {
+ // getUrl() failed to parse the url provided in the intent: bail out in a way that
+ // at least provides network access.
+ done(Result.WANTED_AS_IS);
+ return;
+ }
+ if (DBG) {
+ Log.d(TAG, String.format("onCreate for %s", mUrl.toString()));
+ }
// Also initializes proxy system properties.
mCm.bindProcessToNetwork(mNetwork);
@@ -149,6 +152,9 @@
}
private void done(Result result) {
+ if (DBG) {
+ Log.d(TAG, String.format("Result %s for %s", result.name(), mUrl.toString()));
+ }
if (mNetworkCallback != null) {
mCm.unregisterNetworkCallback(mNetworkCallback);
mNetworkCallback = null;
@@ -185,22 +191,31 @@
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- int id = item.getItemId();
- if (id == R.id.action_use_network) {
- done(Result.WANTED_AS_IS);
- return true;
+ final Result result;
+ final String action;
+ final int id = item.getItemId();
+ switch (id) {
+ case R.id.action_use_network:
+ result = Result.WANTED_AS_IS;
+ action = "USE_NETWORK";
+ break;
+ case R.id.action_do_not_use_network:
+ result = Result.UNWANTED;
+ action = "DO_NOT_USE_NETWORK";
+ break;
+ default:
+ return super.onOptionsItemSelected(item);
}
- if (id == R.id.action_do_not_use_network) {
- done(Result.UNWANTED);
- return true;
+ if (DBG) {
+ Log.d(TAG, String.format("onOptionsItemSelect %s for %s", action, mUrl.toString()));
}
- return super.onOptionsItemSelected(item);
+ done(result);
+ return true;
}
@Override
public void onDestroy() {
super.onDestroy();
-
if (mNetworkCallback != null) {
mCm.unregisterNetworkCallback(mNetworkCallback);
mNetworkCallback = null;
@@ -215,10 +230,27 @@
} catch (InterruptedException e) {
}
}
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(mURL.toString())));
+ final String url = mUrl.toString();
+ if (DBG) {
+ Log.d(TAG, "starting activity with intent ACTION_VIEW for " + url);
+ }
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
}
}
+ private URL getUrl() {
+ String url = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL);
+ if (url == null) {
+ url = mCm.getCaptivePortalServerUrl();
+ }
+ try {
+ return new URL(url);
+ } catch (MalformedURLException e) {
+ Log.e(TAG, "Invalid captive portal URL " + url);
+ }
+ return null;
+ }
+
private void testForCaptivePortal() {
new Thread(new Runnable() {
public void run() {
@@ -230,7 +262,7 @@
HttpURLConnection urlConnection = null;
int httpResponseCode = 500;
try {
- urlConnection = (HttpURLConnection) mURL.openConnection();
+ urlConnection = (HttpURLConnection) mUrl.openConnection();
urlConnection.setInstanceFollowRedirects(false);
urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
@@ -292,7 +324,7 @@
// settings. Now prompt the WebView read the Network-specific proxy settings.
setWebViewProxy();
// Load the real page.
- view.loadUrl(mURL.toString());
+ view.loadUrl(mUrl.toString());
return;
} else if (mPagesLoaded == 2) {
// Prevent going back to empty first page.
diff --git a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
index a7c9105..edcea0e 100644
--- a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
@@ -24,6 +24,7 @@
android:name=".SampleTrustAgent"
android:label="@string/app_name"
android:permission="android.permission.BIND_TRUST_AGENT"
+ android:directBootAware="true"
android:exported="true">
<intent-filter>
<action android:name="android.service.trust.TrustAgentService" />
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/layout-v26/sample_trust_agent_settings.xml b/packages/Keyguard/test/SampleTrustAgent/res/layout-v26/sample_trust_agent_settings.xml
new file mode 100644
index 0000000..4669971
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/res/layout-v26/sample_trust_agent_settings.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2014 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <Button android:id="@+id/enable_trust"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Grant trust for 30 seconds" />
+ <Button android:id="@+id/revoke_trust"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Revoke trust" />
+ <Button android:id="@+id/crash"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Crash" />
+ <CheckBox android:id="@+id/managing_trust"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="Managing trust" />
+ <CheckBox android:id="@+id/managing_trust_direct_boot"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="Managing trust direct boot"/>
+
+ <CheckBox android:id="@+id/report_unlock_attempts"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="Report unlock attempts" />
+ <CheckBox android:id="@+id/report_device_locked"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="Report device locked or unlocked" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <Button android:id="@+id/check_device_locked"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Device locked?" />
+ <TextView android:id="@+id/check_device_locked_result"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+ </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/qs_tile_text.xml b/packages/Keyguard/test/SampleTrustAgent/res/xml-v26/sample_trust_agent.xml
similarity index 67%
rename from packages/SystemUI/res/color/qs_tile_text.xml
rename to packages/Keyguard/test/SampleTrustAgent/res/xml-v26/sample_trust_agent.xml
index 90e0bce..26d5aa0 100644
--- a/packages/SystemUI/res/color/qs_tile_text.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/res/xml-v26/sample_trust_agent.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-
<!--
- ~ Copyright (C) 2015 The Android Open Source Project
+ ~ Copyright (C) 2014 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.
@@ -15,8 +14,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_enabled="false" android:color="@color/qs_tile_disabled_color" />
- <item android:color="#B3FFFFFF" /> <!-- 70% white -->
-</selector>
\ No newline at end of file
+<trust-agent xmlns:android="http://schemas.android.com/apk/res/android"
+ android:settingsActivity=".SampleTrustAgentSettings"
+ android:unlockProfile="true" />
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml b/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml
index b363ab4..6cd34bb 100644
--- a/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml
@@ -15,4 +15,4 @@
~ limitations under the License
-->
<trust-agent xmlns:android="http://schemas.android.com/apk/res/android"
- android:settingsActivity=".SampleTrustAgentSettings" />
+ android:settingsActivity=".SampleTrustAgentSettings" />
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
index b8f16e7..4b50cf8 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
@@ -22,6 +22,7 @@
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.PersistableBundle;
+import android.os.UserManager;
import android.preference.PreferenceManager;
import android.service.trust.TrustAgentService;
import android.support.v4.content.LocalBroadcastManager;
@@ -57,26 +58,47 @@
= "preference.report_unlock_attempts";
private static final String PREFERENCE_MANAGING_TRUST
= "preference.managing_trust";
+ private static final String PREFERENCE_MANAGING_TRUST_DIRECT_BOOT
+ = "preference.managing_trust_direct_boot";
private static final String PREFERENCE_REPORT_DEVICE_LOCKED = "preference.report_device_locked";
private static final String TAG = "SampleTrustAgent";
+ private static final BroadcastReceiver mUnlockReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+
+ }
+ };
+
+ private boolean mIsUserUnlocked;
+
@Override
public void onCreate() {
super.onCreate();
+ UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
+ mIsUserUnlocked = um.isUserUnlocked();
+ Log.i(TAG,, "onCreate, is user unlocked=" + mIsUserUnlocked);
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_GRANT_TRUST);
filter.addAction(ACTION_REVOKE_TRUST);
+ if (!mIsUserUnlocked) {
+ filter.addAction(Intent.ACTION_BOOT_COMPLETED);
+ }
mLocalBroadcastManager.registerReceiver(mReceiver, filter);
if (ALLOW_EXTERNAL_BROADCASTS) {
registerReceiver(mReceiver, filter);
}
- setManagingTrust(getIsManagingTrust(this));
- PreferenceManager.getDefaultSharedPreferences(this)
- .registerOnSharedPreferenceChangeListener(this);
+ if (!mIsUserUnlocked) {
+ boolean trustManaged = getIsManagingTrustDirectBoot(this);
+ Log.i(TAG, "in Direct boot." + (trustManaged ? "manage" : "cannot manage") + "trust");
+ setManagingTrust(getIsManagingTrustDirectBoot(this));
+ } else {
+ onBootCompleted();
+ }
}
@Override
@@ -137,6 +159,12 @@
.unregisterOnSharedPreferenceChangeListener(this);
}
+ private void onBootCompleted() {
+ PreferenceManager.getDefaultSharedPreferences(this)
+ .registerOnSharedPreferenceChangeListener(this);
+ setManagingTrust(getIsManagingTrust(this));
+ }
+
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -158,6 +186,9 @@
}
} else if (ACTION_REVOKE_TRUST.equals(action)) {
revokeTrust();
+ } else if (intent.ACTION_BOOT_COMPLETED.equals(action)) {
+ Log.d(TAG, "User unlocked and boot completed.");
+ onBootCompleted();
}
}
};
@@ -203,6 +234,7 @@
public static void setIsManagingTrust(Context context, boolean enabled) {
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(context);
+ Log.d("AAAA", "save manage trust preference. Enabled=" + enabled);
sharedPreferences.edit().putBoolean(PREFERENCE_MANAGING_TRUST, enabled).apply();
}
@@ -212,6 +244,21 @@
return sharedPreferences.getBoolean(PREFERENCE_MANAGING_TRUST, false);
}
+ public static void setIsManagingTrustDirectBoot(Context context, boolean enabled) {
+ Context directBootContext = context.createDeviceProtectedStorageContext();
+ SharedPreferences sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(directBootContext);
+ Log.d("AAAA", "save to direct boot preference. Enabled=" + enabled);
+ sharedPreferences.edit().putBoolean(PREFERENCE_MANAGING_TRUST_DIRECT_BOOT, enabled).apply();
+ }
+
+ public static boolean getIsManagingTrustDirectBoot(Context context) {
+ Context directBootContext = context.createDeviceProtectedStorageContext();
+ SharedPreferences sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(directBootContext);
+ return sharedPreferences.getBoolean(PREFERENCE_MANAGING_TRUST_DIRECT_BOOT, false);
+ }
+
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (PREFERENCE_MANAGING_TRUST.equals(key)) {
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
index 29b15cb..1b17169 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
@@ -33,6 +33,7 @@
private CheckBox mReportUnlockAttempts;
private CheckBox mReportDeviceLocked;
private CheckBox mManagingTrust;
+ private CheckBox mManagingTrustDirectBoot;
private TextView mCheckDeviceLockedResult;
private KeyguardManager mKeyguardManager;
@@ -59,6 +60,8 @@
mManagingTrust = (CheckBox) findViewById(R.id.managing_trust);
mManagingTrust.setOnCheckedChangeListener(this);
+ mManagingTrustDirectBoot = (CheckBox) findViewById(R.id.managing_trust_direct_boot);
+ mManagingTrustDirectBoot.setOnCheckedChangeListener(this);
mCheckDeviceLockedResult = (TextView) findViewById(R.id.check_device_locked_result);
}
@@ -68,6 +71,8 @@
super.onResume();
mReportUnlockAttempts.setChecked(SampleTrustAgent.getReportUnlockAttempts(this));
mManagingTrust.setChecked(SampleTrustAgent.getIsManagingTrust(this));
+ mManagingTrustDirectBoot.setChecked(
+ SampleTrustAgent.getIsManagingTrustDirectBoot(this));
updateTrustedState();
}
@@ -94,6 +99,8 @@
SampleTrustAgent.setIsManagingTrust(this, isChecked);
} else if (buttonView == mReportDeviceLocked) {
SampleTrustAgent.setReportDeviceLocked(this, isChecked);
+ } else if (buttonView == mManagingTrustDirectBoot) {
+ SampleTrustAgent.setIsManagingTrustDirectBoot(this, isChecked);
}
}
diff --git a/packages/MtpDocumentsProvider/res/values-in/strings.xml b/packages/MtpDocumentsProvider/res/values-in/strings.xml
index 905daec..6f65337 100644
--- a/packages/MtpDocumentsProvider/res/values-in/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values-in/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="6271216747302322594">"Host MTP"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Unduhan"</string>
+ <string name="downloads_app_label" msgid="7120690641874849726">"Download"</string>
<string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
<string name="accessing_notification_title" msgid="3030133609230917944">"Mengakses file dari <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
<string name="error_busy_device" msgid="3997316850357386589">"Perangkat lainnya sedang sibuk. Anda dapat mentransfer file jika telah tersedia."</string>
diff --git a/packages/MtpDocumentsProvider/res/values-uz-rUZ/strings.xml b/packages/MtpDocumentsProvider/res/values-uz-rUZ/strings.xml
index dea4cff..c511172 100644
--- a/packages/MtpDocumentsProvider/res/values-uz-rUZ/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values-uz-rUZ/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="6271216747302322594">"MTP Host"</string>
- <string name="downloads_app_label" msgid="7120690641874849726">"Yuklanishlar"</string>
+ <string name="downloads_app_label" msgid="7120690641874849726">"Yuklanmalar"</string>
<string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g><xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
<string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> qurilmasidan fayllar o‘qilmoqda"</string>
<string name="error_busy_device" msgid="3997316850357386589">"Ulangan qurilma band. U bo‘shamaguncha fayllarni o‘tkazib bo‘lmaydi."</string>
diff --git a/packages/PrintRecommendationService/res/values/donottranslate.xml b/packages/PrintRecommendationService/res/values/donottranslate.xml
index e9b97a3..2cce56d8a 100644
--- a/packages/PrintRecommendationService/res/values/donottranslate.xml
+++ b/packages/PrintRecommendationService/res/values/donottranslate.xml
@@ -32,13 +32,6 @@
<item>Hewlett Packard</item>
</string-array>
- <!-- Samsung plugin -->
- <string-array name="known_print_vendor_info_for_samsung" translatable="false">
- <item>com.sec.app.samsungprintservice</item>
- <item>Samsung Electronics</item>
- <item>Samsung</item>
- </string-array>
-
<!-- Xerox plugin -->
<string-array name="known_print_vendor_info_for_xerox" translatable="false">
<item>com.xerox.printservice</item>
@@ -49,6 +42,8 @@
<array name="known_print_plugin_vendors" translatable="false">
<item>@array/known_print_vendor_info_for_mopria</item>
<item>@array/known_print_vendor_info_for_hp</item>
- <item>@array/known_print_vendor_info_for_samsung</item>
</array>
+
+ <!-- Samsung plugin -->
+ <string name="plugin_package_samsung">com.sec.app.samsungprintservice</string>
</resources>
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
index 3eedefd..d048396 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
@@ -78,7 +78,7 @@
try {
mPlugins.add(new RemotePrintServicePlugin(new SamsungRecommendationPlugin(this), this,
- false));
+ true));
} catch (Exception e) {
Log.e(LOG_TAG, "Could not initiate " + getString(R.string.plugin_vendor_samsung) +
" plugin", e);
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
index a2c0485..d60a25f 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
@@ -16,30 +16,52 @@
package com.android.printservice.recommendation.plugin.mdnsFilter;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.StringRes;
import android.content.Context;
-import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
-import android.util.Log;
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
+import android.annotation.NonNull;
+import android.annotation.StringRes;
+
import com.android.printservice.recommendation.PrintServicePlugin;
-import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer;
-import com.android.printservice.recommendation.util.NsdResolveQueue;
+import com.android.printservice.recommendation.util.MDNSFilteredDiscovery;
+import com.android.printservice.recommendation.util.MDNSUtils;
import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* A plugin listening for mDNS results and only adding the ones that {@link
* MDNSUtils#isVendorPrinter match} configured list
*/
-public class MDNSFilterPlugin implements PrintServicePlugin, NsdManager.DiscoveryListener {
- private static final String LOG_TAG = "MDNSFilterPlugin";
+public class MDNSFilterPlugin implements PrintServicePlugin {
- private static final String PRINTER_SERVICE_TYPE = "_ipp._tcp";
+ /** The mDNS service types supported */
+ private static final Set<String> PRINTER_SERVICE_TYPES = new HashSet<String>() {{
+ add("_ipp._tcp");
+ }};
+
+ /**
+ * The printer filter for {@link MDNSFilteredDiscovery} passing only mDNS results
+ * that {@link MDNSUtils#isVendorPrinter match} configured list
+ */
+ private static class VendorNameFilter implements MDNSFilteredDiscovery.PrinterFilter {
+ /** mDNS names handled by the print service this plugin is for */
+ private final @NonNull Set<String> mMDNSNames;
+
+ /**
+ * Filter constructor
+ *
+ * @param vendorNames The vendor names to pass
+ */
+ VendorNameFilter(@NonNull Set<String> vendorNames) {
+ mMDNSNames = new HashSet<>(vendorNames);
+ }
+
+ @Override
+ public boolean matchesCriteria(NsdServiceInfo nsdServiceInfo) {
+ return MDNSUtils.isVendorPrinter(nsdServiceInfo, mMDNSNames);
+ }
+ }
/** Name of the print service this plugin is for */
private final @StringRes int mName;
@@ -47,26 +69,8 @@
/** Package name of the print service this plugin is for */
private final @NonNull CharSequence mPackageName;
- /** mDNS names handled by the print service this plugin is for */
- private final @NonNull HashSet<String> mMDNSNames;
-
- /** Printer identifiers of the mPrinters found. */
- @GuardedBy("mLock")
- private final @NonNull HashSet<String> mPrinters;
-
- /** Context of the user of this plugin */
- private final @NonNull Context mContext;
-
- /**
- * Call back to report the number of mPrinters found.
- *
- * We assume that {@link #start} and {@link #stop} are never called in parallel, hence it is
- * safe to not synchronize access to this field.
- */
- private @Nullable PrinterDiscoveryCallback mCallback;
-
- /** Queue used to resolve nsd infos */
- private final @NonNull NsdResolveQueue mResolveQueue;
+ /** The mDNS filtered discovery */
+ private final MDNSFilteredDiscovery mMDNSFilteredDiscovery;
/**
* Create new stub that assumes that a print service can be used to print on all mPrinters
@@ -79,16 +83,11 @@
*/
public MDNSFilterPlugin(@NonNull Context context, @NonNull String name,
@NonNull CharSequence packageName, @NonNull List<String> mDNSNames) {
- mContext = Preconditions.checkNotNull(context, "context");
- mName = mContext.getResources().getIdentifier(Preconditions.checkStringNotEmpty(name,
- "name"), null, "com.android.printservice.recommendation");
- mPackageName = Preconditions.checkStringNotEmpty(packageName);
- mMDNSNames = new HashSet<>(Preconditions
- .checkCollectionNotEmpty(Preconditions.checkCollectionElementsNotNull(mDNSNames,
- "mDNSNames"), "mDNSNames"));
-
- mResolveQueue = NsdResolveQueue.getInstance();
- mPrinters = new HashSet<>();
+ mName = context.getResources().getIdentifier(name, null,
+ "com.android.printservice.recommendation");
+ mPackageName = packageName;
+ mMDNSFilteredDiscovery = new MDNSFilteredDiscovery(context, PRINTER_SERVICE_TYPES,
+ new VendorNameFilter(new HashSet<>(mDNSNames)));
}
@Override
@@ -96,18 +95,9 @@
return mPackageName;
}
- /**
- * @return The NDS manager
- */
- private NsdManager getNDSManager() {
- return (NsdManager) mContext.getSystemService(Context.NSD_SERVICE);
- }
-
@Override
public void start(@NonNull PrinterDiscoveryCallback callback) throws Exception {
- mCallback = callback;
-
- DiscoveryListenerMultiplexer.addListener(getNDSManager(), PRINTER_SERVICE_TYPE, this);
+ mMDNSFilteredDiscovery.start(callback);
}
@Override
@@ -117,82 +107,6 @@
@Override
public void stop() throws Exception {
- mCallback.onChanged(0);
- mCallback = null;
-
- DiscoveryListenerMultiplexer.removeListener(getNDSManager(), this);
- }
-
- @Override
- public void onStartDiscoveryFailed(String serviceType, int errorCode) {
- Log.w(LOG_TAG, "Failed to start network discovery for type " + serviceType + ": "
- + errorCode);
- }
-
- @Override
- public void onStopDiscoveryFailed(String serviceType, int errorCode) {
- Log.w(LOG_TAG, "Failed to stop network discovery for type " + serviceType + ": "
- + errorCode);
- }
-
- @Override
- public void onDiscoveryStarted(String serviceType) {
- // empty
- }
-
- @Override
- public void onDiscoveryStopped(String serviceType) {
- mPrinters.clear();
- }
-
- @Override
- public void onServiceFound(NsdServiceInfo serviceInfo) {
- mResolveQueue.resolve(getNDSManager(), serviceInfo,
- new NsdManager.ResolveListener() {
- @Override
- public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
- Log.w(LOG_TAG, "Service found: could not resolve " + serviceInfo + ": " +
- errorCode);
- }
-
- @Override
- public void onServiceResolved(NsdServiceInfo serviceInfo) {
- if (MDNSUtils.isVendorPrinter(serviceInfo, mMDNSNames)) {
- if (mCallback != null) {
- boolean added = mPrinters.add(serviceInfo.getHost().getHostAddress());
-
- if (added) {
- mCallback.onChanged(mPrinters.size());
- }
- }
- }
- }
- });
- }
-
- @Override
- public void onServiceLost(NsdServiceInfo serviceInfo) {
- mResolveQueue.resolve(getNDSManager(), serviceInfo,
- new NsdManager.ResolveListener() {
- @Override
- public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
- Log.w(LOG_TAG, "Service lost: Could not resolve " + serviceInfo + ": "
- + errorCode);
- }
-
- @Override
- public void onServiceResolved(NsdServiceInfo serviceInfo) {
- if (MDNSUtils.isVendorPrinter(serviceInfo, mMDNSNames)) {
- if (mCallback != null) {
- boolean removed = mPrinters
- .remove(serviceInfo.getHost().getHostAddress());
-
- if (removed) {
- mCallback.onChanged(mPrinters.size());
- }
- }
- }
- }
- });
+ mMDNSFilteredDiscovery.stop();
}
}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/MDnsUtils.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/MDnsUtils.java
deleted file mode 100644
index 963e09b..0000000
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/MDnsUtils.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printservice.recommendation.plugin.samsung;
-
-import android.net.nsd.NsdServiceInfo;
-import android.text.TextUtils;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Locale;
-import java.util.Map;
-
-public class MDnsUtils {
- public static final String ATTRIBUTE__TY = "ty";
- public static final String ATTRIBUTE__PRODUCT = "product";
- public static final String ATTRIBUTE__USB_MFG = "usb_MFG";
- public static final String ATTRIBUTE__MFG = "mfg";
-
- public static String getString(byte[] value) {
- if (value != null) return new String(value,StandardCharsets.UTF_8);
- return null;
- }
-
- public static boolean isVendorPrinter(NsdServiceInfo networkDevice, String[] vendorValues) {
-
- Map<String,byte[]> attributes = networkDevice.getAttributes();
- String product = getString(attributes.get(ATTRIBUTE__PRODUCT));
- String ty = getString(attributes.get(ATTRIBUTE__TY));
- String usbMfg = getString(attributes.get(ATTRIBUTE__USB_MFG));
- String mfg = getString(attributes.get(ATTRIBUTE__MFG));
- return containsVendor(product, vendorValues) || containsVendor(ty, vendorValues) || containsVendor(usbMfg, vendorValues) || containsVendor(mfg, vendorValues);
-
- }
-
- public static String getVendor(NsdServiceInfo networkDevice) {
- String vendor;
-
- Map<String,byte[]> attributes = networkDevice.getAttributes();
- vendor = getString(attributes.get(ATTRIBUTE__MFG));
- if (!TextUtils.isEmpty(vendor)) return vendor;
- vendor = getString(attributes.get(ATTRIBUTE__USB_MFG));
- if (!TextUtils.isEmpty(vendor)) return vendor;
-
- return null;
- }
-
- private static boolean containsVendor(String container, String[] vendorValues) {
- if ((container == null) || (vendorValues == null)) return false;
- for (String value : vendorValues) {
- if (containsString(container, value)
- || containsString(container.toLowerCase(Locale.US), value.toLowerCase(Locale.US))
- || containsString(container.toUpperCase(Locale.US), value.toUpperCase(Locale.US)))
- return true;
- }
- return false;
- }
-
- private static boolean containsString(String container, String contained) {
- return (container != null) && (contained != null) && (container.equalsIgnoreCase(contained) || container.contains(contained + " "));
- }
-}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterMopria.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterMopria.java
new file mode 100644
index 0000000..d03bb1d
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterMopria.java
@@ -0,0 +1,63 @@
+/*
+ * (c) Copyright 2016 Samsung Electronics
+ * (c) Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.printservice.recommendation.plugin.samsung;
+
+import android.net.nsd.NsdServiceInfo;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.printservice.recommendation.util.MDNSFilteredDiscovery;
+import com.android.printservice.recommendation.util.MDNSUtils;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Printer filter for Mopria printer models supported by the print service plugin
+ */
+class PrinterFilterMopria implements MDNSFilteredDiscovery.PrinterFilter {
+ private static final String TAG = "PrinterFilterMopria";
+
+ static final Set<String> MOPRIA_MDNS_SERVICES = new HashSet<String>() {{
+ add("_ipp._tcp");
+ add("_ipps._tcp");
+ }};
+
+ private static final String PDL__PDF = "application/pdf";
+ private static final String PDL__PCLM = "application/PCLm";
+ private static final String PDL__PWG_RASTER = "image/pwg-raster";
+
+ private static final String PDL_ATTRIBUTE = "pdl";
+
+ @Override
+ public boolean matchesCriteria(NsdServiceInfo nsdServiceInfo) {
+ if (!MDNSUtils.isSupportedServiceType(nsdServiceInfo, MOPRIA_MDNS_SERVICES)) {
+ return false;
+ }
+
+ String pdls = MDNSUtils.getString(nsdServiceInfo.getAttributes().get(PDL_ATTRIBUTE));
+ boolean isMatch = !TextUtils.isEmpty(pdls)
+ && (pdls.contains(PDL__PDF)
+ || pdls.contains(PDL__PCLM)
+ || pdls.contains(PDL__PWG_RASTER));
+
+ if (isMatch) {
+ Log.d(TAG, "Mopria printer found: " + nsdServiceInfo.getServiceName());
+ }
+ return isMatch;
+ }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterSamsung.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterSamsung.java
new file mode 100644
index 0000000..5b049ef
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterSamsung.java
@@ -0,0 +1,117 @@
+/*
+ * (c) Copyright 2016 Samsung Electronics
+ * (c) Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.printservice.recommendation.plugin.samsung;
+
+import android.net.nsd.NsdServiceInfo;
+import android.annotation.NonNull;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.printservice.recommendation.util.MDNSFilteredDiscovery;
+import com.android.printservice.recommendation.util.MDNSUtils;
+
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Printer filter for Samsung printer models supported by the print service plugin
+ */
+class PrinterFilterSamsung implements MDNSFilteredDiscovery.PrinterFilter {
+ private static final String TAG = "PrinterFilterSamsung";
+
+ static final Set<String> SAMSUNG_MDNS_SERVICES = new HashSet<String>() {{
+ add("_pdl-datastream._tcp");
+ }};
+
+ private static final String[] NOT_SUPPORTED_MODELS = new String[]{
+ "SCX-5x15",
+ "SF-555P",
+ "CF-555P",
+ "SCX-4x16",
+ "SCX-4214F",
+ "CLP-500",
+ "CJX-",
+ "MJC-"
+ };
+ private static final String ATTR_USB_MFG = "usb_MFG";
+ private static final String ATTR_MFG = "mfg";
+ private static final String ATTR_USB_MDL = "usb_MDL";
+ private static final String ATTR_MDL = "mdl";
+ private static final String ATTR_PRODUCT = "product";
+ private static final String ATTR_TY = "ty";
+
+ private static Set<String> SAMUNG_VENDOR_SET = new HashSet<String>() {{
+ add("samsung");
+ }};
+
+ @Override
+ public boolean matchesCriteria(NsdServiceInfo nsdServiceInfo) {
+ if (!MDNSUtils.isSupportedServiceType(nsdServiceInfo, SAMSUNG_MDNS_SERVICES)) {
+ return false;
+ }
+
+ if (!MDNSUtils.isVendorPrinter(nsdServiceInfo, SAMUNG_VENDOR_SET)) {
+ return false;
+ }
+
+ String modelName = getSamsungModelName(nsdServiceInfo);
+ if (modelName != null && isSupportedSamsungModel(modelName)) {
+ Log.d(TAG, "Samsung printer found: " + nsdServiceInfo.getServiceName());
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isSupportedSamsungModel(String model) {
+ if (!TextUtils.isEmpty(model)) {
+ String modelToUpper = model.toUpperCase(Locale.US);
+ for (String unSupportedPrinter : NOT_SUPPORTED_MODELS) {
+ if (modelToUpper.contains(unSupportedPrinter)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private String getSamsungModelName(@NonNull NsdServiceInfo resolvedDevice) {
+ Map<String,byte[]> attributes = resolvedDevice.getAttributes();
+ String usb_mfg = MDNSUtils.getString(attributes.get(ATTR_USB_MFG));
+ if (TextUtils.isEmpty(usb_mfg)) {
+ usb_mfg = MDNSUtils.getString(attributes.get(ATTR_MFG));
+ }
+
+ String usb_mdl = MDNSUtils.getString(attributes.get(ATTR_USB_MDL));
+ if (TextUtils.isEmpty(usb_mdl)) {
+ usb_mdl = MDNSUtils.getString(attributes.get(ATTR_MDL));
+ }
+
+ String modelName;
+ if (!TextUtils.isEmpty(usb_mfg) && !TextUtils.isEmpty(usb_mdl)) {
+ modelName = usb_mfg.trim() + " " + usb_mdl.trim();
+ } else {
+ modelName = MDNSUtils.getString(attributes.get(ATTR_PRODUCT));
+ if (TextUtils.isEmpty(modelName)) {
+ modelName = MDNSUtils.getString(attributes.get(ATTR_TY));
+ }
+ }
+
+ return modelName;
+ }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterHashMap.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterHashMap.java
deleted file mode 100644
index 032fe22..0000000
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterHashMap.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printservice.recommendation.plugin.samsung;
-
-import android.net.nsd.NsdServiceInfo;
-
-import java.util.HashMap;
-
-final class PrinterHashMap extends HashMap<String, NsdServiceInfo> {
- public static String getKey(NsdServiceInfo serviceInfo) {
- return serviceInfo.getServiceName();
- }
- public NsdServiceInfo addPrinter(NsdServiceInfo device) {
- return put(getKey(device), device);
- }
- public NsdServiceInfo removePrinter(NsdServiceInfo device) {
- return remove(getKey(device));
- }
-}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java
index e5b8a0f..eeb5122 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java
@@ -1,102 +1,69 @@
-/*
-(c) Copyright 2016 Samsung Electronics..
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-
-package com.android.printservice.recommendation.plugin.samsung;
-
-import android.content.Context;
-import android.net.nsd.NsdServiceInfo;
-import android.text.TextUtils;
-
-import java.util.Locale;
-import java.util.Map;
-
-import com.android.printservice.recommendation.R;
-
-public class SamsungRecommendationPlugin extends ServiceRecommendationPlugin {
-
- private static final String TAG = "SamsungRecommendation";
-
- private static final String ATTR_USB_MFG = "usb_MFG";
- private static final String ATTR_MFG = "mfg";
- private static final String ATTR_USB_MDL = "usb_MDL";
- private static final String ATTR_MDL = "mdl";
- private static final String ATTR_PRODUCT = "product";
- private static final String ATTR_TY = "ty";
-
- private static String[] mNotSupportedDevices = new String[]{
- "SCX-5x15",
- "SF-555P",
- "CF-555P",
- "SCX-4x16",
- "SCX-4214F",
- "CLP-500",
- "CJX-",
- "MJC-"
- };
-
- private static boolean isSupportedModel(String model) {
- if (!TextUtils.isEmpty(model)) {
- String modelToUpper = model.toUpperCase(Locale.US);
- for (String unSupportedPrinter : mNotSupportedDevices) {
- if (modelToUpper.contains(unSupportedPrinter)) {
- return false;
- }
- }
- }
- return true;
- }
-
- public SamsungRecommendationPlugin(Context context) {
- super(context, R.string.plugin_vendor_samsung, new VendorInfo(context.getResources(), R.array.known_print_vendor_info_for_samsung), new String[]{"_pdl-datastream._tcp"});
- }
-
- @Override
- public boolean matchesCriteria(String vendor, NsdServiceInfo nsdServiceInfo) {
- if (!TextUtils.equals(vendor, mVendorInfo.mVendorID)) return false;
-
- String modelName = getModelName(nsdServiceInfo);
- if (modelName != null) {
- return (isSupportedModel(modelName));
- }
- return false;
- }
-
- private String getModelName(NsdServiceInfo resolvedDevice) {
- Map<String,byte[]> attributes = resolvedDevice.getAttributes();
- String usb_mfg = MDnsUtils.getString(attributes.get(ATTR_USB_MFG));
- if (TextUtils.isEmpty(usb_mfg)) {
- usb_mfg = MDnsUtils.getString(attributes.get(ATTR_MFG));
- }
-
- String usb_mdl = MDnsUtils.getString(attributes.get(ATTR_USB_MDL));
- if (TextUtils.isEmpty(usb_mdl)) {
- usb_mdl = MDnsUtils.getString(attributes.get(ATTR_MDL));
- }
-
- String modelName = null;
- if (!TextUtils.isEmpty(usb_mfg) && !TextUtils.isEmpty(usb_mdl)) {
- modelName = usb_mfg.trim() + " " + usb_mdl.trim();
- } else {
- modelName = MDnsUtils.getString(attributes.get(ATTR_PRODUCT));
- if (TextUtils.isEmpty(modelName)) {
- modelName = MDnsUtils.getString(attributes.get(ATTR_TY));
- }
- }
-
- return modelName;
- }
-}
+/*
+ * (c) Copyright 2016 Samsung Electronics
+ * (c) Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.printservice.recommendation.plugin.samsung;
+
+import android.content.Context;
+import android.net.nsd.NsdServiceInfo;
+import android.annotation.NonNull;
+
+import com.android.printservice.recommendation.PrintServicePlugin;
+import com.android.printservice.recommendation.R;
+import com.android.printservice.recommendation.util.MDNSFilteredDiscovery;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class SamsungRecommendationPlugin implements PrintServicePlugin {
+ private static final Set<String> ALL_MDNS_SERVICES = new HashSet<String>() {{
+ addAll(PrinterFilterMopria.MOPRIA_MDNS_SERVICES);
+ addAll(PrinterFilterSamsung.SAMSUNG_MDNS_SERVICES);
+ }};
+
+ private final @NonNull Context mContext;
+ private final @NonNull MDNSFilteredDiscovery mMDNSFilteredDiscovery;
+
+ private final @NonNull PrinterFilterSamsung mPrinterFilterSamsung = new PrinterFilterSamsung();
+ private final @NonNull PrinterFilterMopria mPrinterFilterMopria = new PrinterFilterMopria();
+
+ public SamsungRecommendationPlugin(@NonNull Context context) {
+ mContext = context;
+ mMDNSFilteredDiscovery = new MDNSFilteredDiscovery(context, ALL_MDNS_SERVICES,
+ (NsdServiceInfo nsdServiceInfo) ->
+ mPrinterFilterSamsung.matchesCriteria(nsdServiceInfo) ||
+ mPrinterFilterMopria.matchesCriteria(nsdServiceInfo));
+ }
+
+ @Override
+ public int getName() {
+ return R.string.plugin_vendor_samsung;
+ }
+
+ @Override
+ public @NonNull CharSequence getPackageName() {
+ return mContext.getString(R.string.plugin_package_samsung);
+ }
+
+ @Override
+ public void start(@NonNull PrinterDiscoveryCallback callback) throws Exception {
+ mMDNSFilteredDiscovery.start(callback);
+ }
+
+ @Override
+ public void stop() throws Exception {
+ mMDNSFilteredDiscovery.stop();
+ }
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceListener.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceListener.java
deleted file mode 100644
index 7bb83c9..0000000
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceListener.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printservice.recommendation.plugin.samsung;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.net.nsd.NsdManager;
-import android.net.nsd.NsdServiceInfo;
-import android.text.TextUtils;
-import android.util.Pair;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import com.android.printservice.recommendation.R;
-import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer;
-
-public class ServiceListener implements ServiceResolveQueue.ResolveCallback {
-
- private final NsdManager mNSDManager;
- private final Map<String, VendorInfo> mVendorInfoHashMap;
- private final String[] mServiceType;
- private final Observer mObserver;
- private final ServiceResolveQueue mResolveQueue;
- private List<NsdManager.DiscoveryListener> mListeners = new ArrayList<>();
- public HashMap<String, PrinterHashMap> mVendorHashMap = new HashMap<>();
-
- public interface Observer {
- boolean matchesCriteria(String vendor, NsdServiceInfo serviceInfo);
- void dataSetChanged();
- }
-
- public ServiceListener(Context context, Observer observer, String[] serviceTypes) {
- mObserver = observer;
- mServiceType = serviceTypes;
- mNSDManager = (NsdManager)context.getSystemService(Context.NSD_SERVICE);
- mResolveQueue = ServiceResolveQueue.getInstance(mNSDManager);
-
- Map<String, VendorInfo> vendorInfoMap = new HashMap<>();
- TypedArray testArray = context.getResources().obtainTypedArray(R.array.known_print_plugin_vendors);
- for(int i = 0; i < testArray.length(); i++) {
- int arrayID = testArray.getResourceId(i, 0);
- if (arrayID != 0) {
- VendorInfo info = new VendorInfo(context.getResources(), arrayID);
- vendorInfoMap.put(info.mVendorID, info);
- vendorInfoMap.put(info.mPackageName, info);
- }
- }
- testArray.recycle();
- mVendorInfoHashMap = vendorInfoMap;
- }
-
- @Override
- public void serviceResolved(NsdServiceInfo nsdServiceInfo) {
- printerFound(nsdServiceInfo);
- }
-
- private synchronized void printerFound(NsdServiceInfo nsdServiceInfo) {
- if (nsdServiceInfo == null) return;
- if (TextUtils.isEmpty(PrinterHashMap.getKey(nsdServiceInfo))) return;
- String vendor = MDnsUtils.getVendor(nsdServiceInfo);
- if (vendor == null) vendor = "";
- for(Map.Entry<String,VendorInfo> entry : mVendorInfoHashMap.entrySet()) {
- for(String vendorValues : entry.getValue().mDNSValues) {
- if (vendor.equalsIgnoreCase(vendorValues)) {
- vendor = entry.getValue().mVendorID;
- break;
- }
- }
- // intentional pointer check
- //noinspection StringEquality
- if ((vendor != entry.getValue().mVendorID) &&
- MDnsUtils.isVendorPrinter(nsdServiceInfo, entry.getValue().mDNSValues)) {
- vendor = entry.getValue().mVendorID;
- }
- // intentional pointer check
- //noinspection StringEquality
- if (vendor == entry.getValue().mVendorID) break;
- }
-
- if (TextUtils.isEmpty(vendor)) {
- return;
- }
-
- if (!mObserver.matchesCriteria(vendor, nsdServiceInfo))
- return;
- boolean mapsChanged;
-
- PrinterHashMap vendorHash = mVendorHashMap.get(vendor);
- if (vendorHash == null) {
- vendorHash = new PrinterHashMap();
- }
- mapsChanged = (vendorHash.addPrinter(nsdServiceInfo) == null);
- mVendorHashMap.put(vendor, vendorHash);
-
- if (mapsChanged) {
- mObserver.dataSetChanged();
- }
- }
-
- private synchronized void printerRemoved(NsdServiceInfo nsdServiceInfo) {
- boolean wasRemoved = false;
- Set<String> vendors = mVendorHashMap.keySet();
- for(String vendor : vendors) {
- PrinterHashMap map = mVendorHashMap.get(vendor);
- wasRemoved |= (map.removePrinter(nsdServiceInfo) != null);
- if (map.isEmpty()) wasRemoved |= (mVendorHashMap.remove(vendor) != null);
- }
- if (wasRemoved) {
- mObserver.dataSetChanged();
- }
- }
-
- public void start() {
- stop();
- for(final String service :mServiceType) {
- NsdManager.DiscoveryListener listener = new NsdManager.DiscoveryListener() {
- @Override
- public void onStartDiscoveryFailed(String s, int i) {
-
- }
-
- @Override
- public void onStopDiscoveryFailed(String s, int i) {
-
- }
-
- @Override
- public void onDiscoveryStarted(String s) {
-
- }
-
- @Override
- public void onDiscoveryStopped(String s) {
-
- }
-
- @Override
- public void onServiceFound(NsdServiceInfo nsdServiceInfo) {
- mResolveQueue.queueRequest(nsdServiceInfo, ServiceListener.this);
- }
-
- @Override
- public void onServiceLost(NsdServiceInfo nsdServiceInfo) {
- mResolveQueue.removeRequest(nsdServiceInfo, ServiceListener.this);
- printerRemoved(nsdServiceInfo);
- }
- };
- DiscoveryListenerMultiplexer.addListener(mNSDManager, service, listener);
- mListeners.add(listener);
- }
- }
-
- public void stop() {
- for(NsdManager.DiscoveryListener listener : mListeners) {
- DiscoveryListenerMultiplexer.removeListener(mNSDManager, listener);
- }
- mVendorHashMap.clear();
- mListeners.clear();
- }
-
- public Pair<Integer, Integer> getCount() {
- int count = 0;
- for (PrinterHashMap map : mVendorHashMap.values()) {
- count += map.size();
- }
- return Pair.create(mVendorHashMap.size(), count);
- }
-}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceRecommendationPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceRecommendationPlugin.java
deleted file mode 100644
index 9d15f30..0000000
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceRecommendationPlugin.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printservice.recommendation.plugin.samsung;
-
-import android.content.Context;
-import android.net.nsd.NsdManager;
-import android.net.nsd.NsdServiceInfo;
-import android.annotation.NonNull;
-import android.text.TextUtils;
-import com.android.printservice.recommendation.PrintServicePlugin;
-
-public abstract class ServiceRecommendationPlugin implements PrintServicePlugin, ServiceListener.Observer {
-
- protected static final String PDL_ATTRIBUTE = "pdl";
-
- protected final Object mLock = new Object();
- protected PrinterDiscoveryCallback mCallback = null;
- protected final ServiceListener mListener;
- protected final NsdManager mNSDManager;
- protected final VendorInfo mVendorInfo;
- private final int mVendorStringID;
-
- protected ServiceRecommendationPlugin(Context context, int vendorStringID, VendorInfo vendorInfo, String[] services) {
- mNSDManager = (NsdManager)context.getSystemService(Context.NSD_SERVICE);
- mVendorStringID = vendorStringID;
- mVendorInfo = vendorInfo;
- mListener = new ServiceListener(context, this, services);
- }
-
- @Override
- public int getName() {
- return mVendorStringID;
- }
-
- @NonNull
- @Override
- public CharSequence getPackageName() {
- return mVendorInfo.mPackageName;
- }
-
- @Override
- public void start(@NonNull PrinterDiscoveryCallback callback) throws Exception {
- synchronized (mLock) {
- mCallback = callback;
- }
- mListener.start();
- }
-
- @Override
- public void stop() throws Exception {
- synchronized (mLock) {
- mCallback = null;
- }
- mListener.stop();
- }
-
- @Override
- public void dataSetChanged() {
- synchronized (mLock) {
- if (mCallback != null) mCallback.onChanged(getCount());
- }
- }
-
- @Override
- public boolean matchesCriteria(String vendor, NsdServiceInfo nsdServiceInfo) {
- return TextUtils.equals(vendor, mVendorInfo.mVendorID);
- }
-
- public int getCount() {
- return mListener.getCount().second;
- }
-}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceResolveQueue.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceResolveQueue.java
deleted file mode 100644
index e5691b7..0000000
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/ServiceResolveQueue.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printservice.recommendation.plugin.samsung;
-
-import android.net.nsd.NsdManager;
-import android.net.nsd.NsdServiceInfo;
-import android.util.Pair;
-import com.android.printservice.recommendation.util.NsdResolveQueue;
-
-import java.util.LinkedList;
-
-final class ServiceResolveQueue {
-
- private final NsdManager mNsdManager;
- private final LinkedList<Pair<NsdServiceInfo, ResolveCallback>> mQueue = new LinkedList<>();
- private final Object mLock = new Object();
-
- private static Object sLock = new Object();
- private static ServiceResolveQueue sInstance = null;
- private final NsdResolveQueue mNsdResolveQueue;
- private Pair<NsdServiceInfo, ResolveCallback> mCurrentRequest = null;
-
- public static void createInstance(NsdManager nsdManager) {
- if (sInstance == null) sInstance = new ServiceResolveQueue(nsdManager);
- }
-
- public static ServiceResolveQueue getInstance(NsdManager nsdManager) {
- synchronized (sLock) {
- createInstance(nsdManager);
- return sInstance;
- }
- }
-
- public static void destroyInstance() {
- sInstance = null;
- }
-
- public interface ResolveCallback {
- void serviceResolved(NsdServiceInfo nsdServiceInfo);
- }
-
- public ServiceResolveQueue(NsdManager nsdManager) {
- mNsdManager = nsdManager;
- mNsdResolveQueue = NsdResolveQueue.getInstance();
- }
-
- public void queueRequest(NsdServiceInfo serviceInfo, ResolveCallback callback) {
- synchronized (mLock) {
- Pair<NsdServiceInfo, ResolveCallback> newRequest = Pair.create(serviceInfo, callback);
- if (mQueue.contains(newRequest)) return;
- mQueue.add(newRequest);
- makeNextRequest();
- }
- }
-
- public void removeRequest(NsdServiceInfo serviceInfo, ResolveCallback callback) {
- synchronized (mLock) {
- Pair<NsdServiceInfo, ResolveCallback> newRequest = Pair.create(serviceInfo, callback);
- mQueue.remove(newRequest);
- if ((mCurrentRequest != null) && newRequest.equals(mCurrentRequest)) mCurrentRequest = null;
- }
- }
-
- private void makeNextRequest() {
- synchronized (mLock) {
- if (mCurrentRequest != null) return;
- if (mQueue.isEmpty()) return;
- mCurrentRequest = mQueue.removeFirst();
- mNsdResolveQueue.resolve(mNsdManager, mCurrentRequest.first,
- new NsdManager.ResolveListener() {
- @Override
- public void onResolveFailed(NsdServiceInfo nsdServiceInfo, int i) {
- synchronized (mLock) {
- if (mCurrentRequest != null) mQueue.add(mCurrentRequest);
- makeNextRequest();
- }
- }
-
- @Override
- public void onServiceResolved(NsdServiceInfo nsdServiceInfo) {
- synchronized (mLock) {
- if (mCurrentRequest != null) {
- mCurrentRequest.second.serviceResolved(nsdServiceInfo);
- mCurrentRequest = null;
- }
- makeNextRequest();
- }
- }
- });
-
- }
- }
-
-
-}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/VendorInfo.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/VendorInfo.java
deleted file mode 100644
index 0ebb4e4..0000000
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/VendorInfo.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printservice.recommendation.plugin.samsung;
-
-import android.content.res.Resources;
-
-import java.util.Arrays;
-
-public final class VendorInfo {
-
- public final String mPackageName;
- public final String mVendorID;
- public final String[] mDNSValues;
- public final int mID;
-
- public VendorInfo(Resources resources, int vendor_info_id) {
- mID = vendor_info_id;
- String[] data = resources.getStringArray(vendor_info_id);
- if ((data == null) || (data.length < 2)) {
- data = new String[] { null, null };
- }
- mPackageName = data[0];
- mVendorID = data[1];
- mDNSValues = (data.length > 2) ? Arrays.copyOfRange(data, 2, data.length) : new String[]{};
- }
-}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java
new file mode 100644
index 0000000..c5dbc8c
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.printservice.recommendation.util;
+
+import android.content.Context;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
+import com.android.printservice.recommendation.PrintServicePlugin;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A discovery listening for mDNS results and only adding the ones that {@link
+ * PrinterFilter#matchesCriteria match} configured list
+ */
+public class MDNSFilteredDiscovery implements NsdManager.DiscoveryListener {
+ private static final String LOG_TAG = "MDNSFilteredDiscovery";
+
+ /**
+ * mDNS service filter interface.
+ * Implement {@link PrinterFilter#matchesCriteria} to filter out supported services
+ */
+ public interface PrinterFilter {
+ /**
+ * Main filter method. Should return true if mDNS service is supported
+ * by the print service plugin
+ *
+ * @param nsdServiceInfo The service info to check
+ *
+ * @return True if service is supported by the print service plugin
+ */
+ boolean matchesCriteria(NsdServiceInfo nsdServiceInfo);
+ }
+
+ /** Printer identifiers of the mPrinters found. */
+ @GuardedBy("mLock")
+ private final @NonNull HashSet<String> mPrinters;
+
+ /** Service types discovered by this plugin */
+ private final @NonNull HashSet<String> mServiceTypes;
+
+ /** Context of the user of this plugin */
+ private final @NonNull Context mContext;
+
+ /** mDNS services filter */
+ private final @NonNull PrinterFilter mPrinterFilter;
+
+ /**
+ * Call back to report the number of mPrinters found.
+ *
+ * We assume that {@link #start} and {@link #stop} are never called in parallel, hence it is
+ * safe to not synchronize access to this field.
+ */
+ private @Nullable PrintServicePlugin.PrinterDiscoveryCallback mCallback;
+
+ /** Queue used to resolve nsd infos */
+ private final @NonNull NsdResolveQueue mResolveQueue;
+
+ /**
+ * Create new stub that assumes that a print service can be used to print on all mPrinters
+ * matching some mDNS names.
+ *
+ * @param context The context the plugin runs in
+ * @param serviceTypes The mDNS service types to listen to.
+ * @param printerFilter The filter for mDNS services
+ */
+ public MDNSFilteredDiscovery(@NonNull Context context,
+ @NonNull Set<String> serviceTypes,
+ @NonNull PrinterFilter printerFilter) {
+ mContext = Preconditions.checkNotNull(context, "context");
+ mServiceTypes = new HashSet<>(Preconditions
+ .checkCollectionNotEmpty(Preconditions.checkCollectionElementsNotNull(serviceTypes,
+ "serviceTypes"), "serviceTypes"));
+ mPrinterFilter = Preconditions.checkNotNull(printerFilter, "printerFilter");
+
+ mResolveQueue = NsdResolveQueue.getInstance();
+ mPrinters = new HashSet<>();
+ }
+
+ /**
+ * @return The NDS manager
+ */
+ private NsdManager getNDSManager() {
+ return (NsdManager) mContext.getSystemService(Context.NSD_SERVICE);
+ }
+
+ /**
+ * Start the discovery.
+ *
+ * @param callback Callbacks used by this plugin.
+ */
+ public void start(@NonNull PrintServicePlugin.PrinterDiscoveryCallback callback) {
+ mCallback = callback;
+ mCallback.onChanged(mPrinters.size());
+
+ for (String serviceType : mServiceTypes) {
+ DiscoveryListenerMultiplexer.addListener(getNDSManager(), serviceType, this);
+ }
+ }
+
+ /**
+ * Stop the discovery. This can only return once the plugin is completely finished and cleaned up.
+ */
+ public void stop() {
+ mCallback.onChanged(0);
+ mCallback = null;
+
+ for (int i = 0; i < mServiceTypes.size(); ++i) {
+ DiscoveryListenerMultiplexer.removeListener(getNDSManager(), this);
+ }
+ }
+
+ /**
+ *
+ * @return The number of discovered printers
+ */
+ public int getCount() {
+ return mPrinters.size();
+ }
+
+ @Override
+ public void onStartDiscoveryFailed(String serviceType, int errorCode) {
+ Log.w(LOG_TAG, "Failed to start network discovery for type " + serviceType + ": "
+ + errorCode);
+ }
+
+ @Override
+ public void onStopDiscoveryFailed(String serviceType, int errorCode) {
+ Log.w(LOG_TAG, "Failed to stop network discovery for type " + serviceType + ": "
+ + errorCode);
+ }
+
+ @Override
+ public void onDiscoveryStarted(String serviceType) {
+ // empty
+ }
+
+ @Override
+ public void onDiscoveryStopped(String serviceType) {
+ mPrinters.clear();
+ }
+
+ @Override
+ public void onServiceFound(NsdServiceInfo serviceInfo) {
+ mResolveQueue.resolve(getNDSManager(), serviceInfo,
+ new NsdManager.ResolveListener() {
+ @Override
+ public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
+ Log.w(LOG_TAG, "Service found: could not resolve " + serviceInfo + ": " +
+ errorCode);
+ }
+
+ @Override
+ public void onServiceResolved(NsdServiceInfo serviceInfo) {
+ if (mPrinterFilter.matchesCriteria(serviceInfo)) {
+ if (mCallback != null) {
+ boolean added = mPrinters.add(serviceInfo.getHost().getHostAddress());
+ if (added) {
+ mCallback.onChanged(mPrinters.size());
+ }
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onServiceLost(NsdServiceInfo serviceInfo) {
+ mResolveQueue.resolve(getNDSManager(), serviceInfo,
+ new NsdManager.ResolveListener() {
+ @Override
+ public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
+ Log.w(LOG_TAG, "Service lost: Could not resolve " + serviceInfo + ": "
+ + errorCode);
+ }
+
+ @Override
+ public void onServiceResolved(NsdServiceInfo serviceInfo) {
+ if (mPrinterFilter.matchesCriteria(serviceInfo)) {
+ if (mCallback != null) {
+ boolean removed = mPrinters
+ .remove(serviceInfo.getHost().getHostAddress());
+
+ if (removed) {
+ mCallback.onChanged(mPrinters.size());
+ }
+ }
+ }
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSUtils.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSUtils.java
similarity index 75%
rename from packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSUtils.java
rename to packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSUtils.java
index 4c27a47..a6df3c8 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSUtils.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSUtils.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.android.printservice.recommendation.plugin.mdnsFilter;
+package com.android.printservice.recommendation.util;
import android.annotation.NonNull;
import android.net.nsd.NsdServiceInfo;
@@ -27,12 +27,15 @@
/**
* Utils for dealing with mDNS attributes
*/
-class MDNSUtils {
+public class MDNSUtils {
public static final String ATTRIBUTE_TY = "ty";
public static final String ATTRIBUTE_PRODUCT = "product";
public static final String ATTRIBUTE_USB_MFG = "usb_mfg";
public static final String ATTRIBUTE_MFG = "mfg";
+ private MDNSUtils() {
+ }
+
/**
* Check if the service has any of a set of vendor names.
*
@@ -95,4 +98,35 @@
private static boolean containsString(@NonNull String container, @NonNull String contained) {
return container.equalsIgnoreCase(contained) || container.contains(contained + " ");
}
+
+ /**
+ * Return String from mDNS attribute byte array
+ *
+ * @param value the byte array with string data
+ *
+ * @return constructed string
+ */
+ public static String getString(byte[] value) {
+ if (value != null) return new String(value, StandardCharsets.UTF_8);
+ return null;
+ }
+
+ /**
+ * Check if service has a type of supported types set
+ *
+ * @param serviceInfo The service
+ * @param serviceTypes The supported service types set
+ *
+ * @return true if service has a type of supported types set
+ */
+ public static boolean isSupportedServiceType(@NonNull NsdServiceInfo serviceInfo,
+ @NonNull Set<String> serviceTypes) {
+ String curType = serviceInfo.getServiceType().toLowerCase();
+ for (String type : serviceTypes) {
+ if (curType.contains(type.toLowerCase())) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index 5808b30..235ff3d 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -32,7 +32,7 @@
<string name="template_page_range" msgid="428638530038286328">"Mfululizo wa <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
<string name="pages_range_example" msgid="8558694453556945172">"k.m. 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Chungulia kwanza kabla ya kuchapisha"</string>
- <string name="install_for_print_preview" msgid="6366303997385509332">"Sakinisha kitazamaji cha PDF kwa onyesho la kuchungulia"</string>
+ <string name="install_for_print_preview" msgid="6366303997385509332">"Sakinisha Kifungua PDF ili uweze kuchungulia"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Programu ya kuchapisha imeacha kufanya kazi"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Inaleta kazi ya kuchapisha"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Hifadhi kama PDF"</string>
diff --git a/packages/SettingsLib/res/drawable/ic_menu.xml b/packages/SettingsLib/res/drawable/ic_menu.xml
index 910a3d0..b77db08 100644
--- a/packages/SettingsLib/res/drawable/ic_menu.xml
+++ b/packages/SettingsLib/res/drawable/ic_menu.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M3.0,18.0l18.0,0.0l0.0,-2.0L3.0,16.0l0.0,2.0zm0.0,-5.0l18.0,0.0l0.0,-2.0L3.0,11.0l0.0,2.0zm0.0,-7.0l0.0,2.0l18.0,0.0L21.0,6.0L3.0,6.0z"/>
diff --git a/packages/SettingsLib/res/layout/restricted_switch_preference.xml b/packages/SettingsLib/res/layout/restricted_switch_preference.xml
index bb1d906..0e4ef6b 100644
--- a/packages/SettingsLib/res/layout/restricted_switch_preference.xml
+++ b/packages/SettingsLib/res/layout/restricted_switch_preference.xml
@@ -24,7 +24,7 @@
android:clipToPadding="false">
<LinearLayout
- android:id="@+id/icon_frame"
+ android:id="@+id/icon_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="60dp"
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 34d236b..fcda1d1 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Gepasmaak (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Hulp en terugvoer"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Kieslys"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"MGT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index c0b776e..a53e97a 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Fərdi (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Yardım və rəy"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menyu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 23adb5a..b32388e 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Персонализирано (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Помощ и отзиви"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"Средно време по Гринуич (GMT)"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index 09988ed..3ee2642e 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"কাস্টম (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"সহায়তা ও মতামত"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"মেনু"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml
index 561af92..b207129 100644
--- a/packages/SettingsLib/res/values-bs-rBA/strings.xml
+++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Prilagodi (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Pomoć i povratne informacije"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Meni"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 5276b3a..159a939 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Vlastní (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Nápověda a zpětná vazba"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Nabídka"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 0c56b8d..49f1899 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tilpasset (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Hjælp og feedback"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 60f373b..95ac313 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Benutzerdefiniert (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Hilfe & Feedback"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index e0b5bb7..9127b2a 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Ayuda y comentarios"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 4353282..2d89b00 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -31,7 +31,7 @@
<string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"No se establecerá conexión automáticamente"</string>
<string name="wifi_no_internet" msgid="3880396223819116454">"No se ha detectado acceso a Internet"</string>
<string name="saved_network" msgid="4352716707126620811">"Guardadas por <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="connected_via_wfa" msgid="3805736726317410714">"Conectado a través de asistente Wi‑Fi"</string>
+ <string name="connected_via_wfa" msgid="3805736726317410714">"Conectado a través del asistente de Wi‑Fi"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"Conectado a través de %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Disponible a través de %1$s"</string>
<string name="wifi_connected_no_internet" msgid="3149853966840874992">"Conexión sin Internet"</string>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index 7d70efe..f979db8 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Kohandatud (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Abi ja tagasiside"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menüü"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index e998b69..4a741f07 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"سفارشی (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"راهنما و بازخورد"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"منو"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index e2eb10d..afd343c 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personnalisée (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Aide et commentaires"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 282ae4a..4d9d90c 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personnalisé (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Aide et commentaires"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index f4bb7ad..1110fe2 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Axuda e suxestións"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index a2a6e04..eefdff1 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"कस्टम (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"सहायता और फ़ीडबैक"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"मेनू"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 76f04bd..9b38b61 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Prilagođeno (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Pomoć i povratne informacije"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Izbornik"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index f5f6916..a373545 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Egyéni (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Súgó és visszajelzés"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 6dcb745..03bac7a 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Հատուկ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Օգնություն և հետադարձ կապ"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Ընտրացանկ"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 2ee38ef..aa3dc13 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"מותאם אישית (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"עזרה ומשוב"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"תפריט"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 8b2d784..f760d934 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -343,6 +343,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"カスタム(<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"ヘルプとフィードバック"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"メニュー"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index 92d7783..920b810 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Арнаулы (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Анықтама және пікір"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Mәзір"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index 46cc6ce..d162bd1 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ផ្ទាល់ខ្លួន (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"ជំនួយ និងមតិស្ថាបនា"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"ម៉ឺនុយ"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index 20d8ae9..ca0ba0a 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ಕಸ್ಟಮ್ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"ಸಹಾಯ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯೆ"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"ಮೆನು"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 03c0edf..2732853 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"맞춤(<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"고객센터"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"메뉴"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index 41a8eef..7b16fd9 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ປັບແຕ່ງເອງ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"ຊ່ວຍເຫຼືອ & ຄຳຕິຊົມ"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"ເມນູ"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 6930c7a..85e044f 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tinkintas (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Pagalba ir atsiliepimai"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Meniu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 7734881..36378f2 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Pielāgots (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Palīdzība un atsauksmes"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Izvēlne"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index 8bcbf79..09c07ea 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ഇഷ്ടാനുസൃതം ( <xliff:g id="DENSITYDPI">%d</xliff:g> )"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"സഹായവും പ്രതികരണവും"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"മെനു"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index 4fa3779..86a62a2 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Тогтмол утга (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Тусламж, санал хүсэлт"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Цэс"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"Гринвичийн цаг"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index cf77254..8935581 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tersuai (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Bantuan & maklum balas"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index 9db8348..5f4dc50 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"စိတ်ကြိုက် (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"အကူအညီနှင့် အကြံပြုချက်"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"မီနူး"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"ဂရင်းနစ်စံတော်ချိန်"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index cc4e5678..76ff94f 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Egendefinert (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Hjelp og tilbakemelding"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Meny"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index 834580b..8199cde 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -22,7 +22,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"सञ्जालका लागि स्क्यान गर्न सक्दैन"</string>
<string name="wifi_security_none" msgid="7985461072596594400">"कुनै पनि होइन"</string>
- <string name="wifi_remembered" msgid="4955746899347821096">"बचत गरियो"</string>
+ <string name="wifi_remembered" msgid="4955746899347821096">"सुरक्षित गरियो"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"असक्षम पारियो"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP विन्यास असफल"</string>
<string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"वाईफाई जडान असफल"</string>
@@ -338,7 +338,7 @@
<string name="screen_zoom_summary_large" msgid="4835294730065424084">"ठूलो"</string>
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"अझ ठूलो"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"सबैभन्दा ठूलो"</string>
- <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"अनुकूलन (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"आफू अनुकूल (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"मद्दत र प्रतिक्रिया"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"मेनु"</string>
<string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index f19ba3e..cb46376 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"ਮਦਦ ਅਤੇ ਪ੍ਰਤੀਕਰਮ"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"ਮੀਨੂ"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 5d0b965..da2f76f 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizat (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Ajutor și feedback"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Meniu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index d301ce1..9600027 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Другой (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Справка/отзыв"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index f21793b..b775db6 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"අභිරුචි (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"උදව් සහ ප්රතිපෝෂණ"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"මෙනුව"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index b478ecf..8130866 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Vlastné (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Pomocník a spätná väzba"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Ponuka"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index b9da0eb..a3b666ca 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Po meri (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Pomoč in povratne informacije"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Meni"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index c17376b..232ca0a 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"I personalizuar (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Ndihma dhe komentet"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menyja"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index f14cbdd..3c06d72 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Kiwango maalum (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Usaidizi na maoni"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menyu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index 2640122..daf3ff2 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"தனிப்பயன் (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"உதவி & கருத்து"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"மெனு"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index 60a4d72..31defb6 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"అనుకూలం (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"సహాయం & అభిప్రాయం"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"మెను"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index fbb67bc..5ec5871 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"กำหนดเอง (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"ความช่วยเหลือและความคิดเห็น"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"เมนู"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 50c43bb..07e1c8bd 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Tulong at feedback"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index c5ae71c..78b4a61 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Özel (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Yardım ve geri bildirim"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index 0b5e8a0..e1b545f 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"حسب ضرورت (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"مدد اور تاثرات"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"مینو"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 21e5b75..28dbe51 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tùy chỉnh (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Trợ giúp và phản hồi"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index ba657c6..7c8bb20 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自定义 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"帮助和反馈"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"菜单"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 60f56f1..62c7715 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自訂 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"說明和意見反映"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"選單"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 6bb7308..17a62e1 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自訂 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"說明與意見回饋"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"選單"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 6714b27..7e982ee 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -341,6 +341,5 @@
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Ngokwezifiso (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
<string name="help_feedback_label" msgid="6815040660801785649">"Usizo nempendulo"</string>
<string name="content_description_menu_button" msgid="8182594799812351266">"Imenyu"</string>
- <!-- no translation found for time_zone_gmt (2587097992671450782) -->
- <skip />
+ <string name="time_zone_gmt" msgid="2587097992671450782">"I-GMT"</string>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index 6bd8a87..99d7f1e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -16,6 +16,7 @@
package com.android.settingslib;
+import android.annotation.UserIdInt;
import android.app.AppGlobals;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
@@ -118,21 +119,25 @@
*/
public static EnforcedAdmin checkIfKeyguardFeaturesDisabled(Context context,
int keyguardFeatures, int userId) {
+ final LockSettingCheck check =
+ (DevicePolicyManager dpm, ComponentName admin, @UserIdInt int checkUser) ->
+ (dpm.getKeyguardDisabledFeatures(admin, checkUser) & keyguardFeatures) != 0;
+
final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
Context.DEVICE_POLICY_SERVICE);
if (dpm == null) {
return null;
}
+
final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
- LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
- EnforcedAdmin enforcedAdmin = null;
if (um.getUserInfo(userId).isManagedProfile()) {
final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
if (admins == null) {
return null;
}
+ EnforcedAdmin enforcedAdmin = null;
for (ComponentName admin : admins) {
- if ((dpm.getKeyguardDisabledFeatures(admin, userId) & keyguardFeatures) != 0) {
+ if (check.isEnforcing(dpm, admin, userId)) {
if (enforcedAdmin == null) {
enforcedAdmin = new EnforcedAdmin(admin, userId);
} else {
@@ -140,49 +145,10 @@
}
}
}
+ return enforcedAdmin;
} else {
- // Consider all admins for this user and the profiles that are visible from this
- // user that do not use a separate work challenge.
- for (UserInfo userInfo : um.getProfiles(userId)) {
- final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
- if (admins == null) {
- continue;
- }
- final boolean isSeparateProfileChallengeEnabled =
- lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
- for (ComponentName admin : admins) {
- if (!isSeparateProfileChallengeEnabled) {
- if ((dpm.getKeyguardDisabledFeatures(admin, userInfo.id)
- & keyguardFeatures) != 0) {
- if (enforcedAdmin == null) {
- enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
- } else {
- return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
- }
- // This same admins could have set policies both on the managed profile
- // and on the parent. So, if the admin has set the policy on the
- // managed profile here, we don't need to further check if that admin
- // has set policy on the parent admin.
- continue;
- }
- }
- if (userInfo.isManagedProfile()) {
- // If userInfo.id is a managed profile, we also need to look at
- // the policies set on the parent.
- DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
- if ((parentDpm.getKeyguardDisabledFeatures(admin, userInfo.id)
- & keyguardFeatures) != 0) {
- if (enforcedAdmin == null) {
- enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
- } else {
- return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
- }
- }
- }
- }
- }
+ return checkForLockSetting(context, userId, check);
}
- return enforcedAdmin;
}
public static EnforcedAdmin checkIfUninstallBlocked(Context context,
@@ -383,6 +349,11 @@
*
*/
public static EnforcedAdmin checkIfPasswordQualityIsSet(Context context, int userId) {
+ final LockSettingCheck check =
+ (DevicePolicyManager dpm, ComponentName admin, @UserIdInt int checkUser) ->
+ dpm.getPasswordQuality(admin, checkUser)
+ > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+
final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
Context.DEVICE_POLICY_SERVICE);
if (dpm == null) {
@@ -390,7 +361,6 @@
}
LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
- EnforcedAdmin enforcedAdmin = null;
if (lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
// userId is managed profile and has a separate challenge, only consider
// the admins in that user.
@@ -398,9 +368,9 @@
if (admins == null) {
return null;
}
+ EnforcedAdmin enforcedAdmin = null;
for (ComponentName admin : admins) {
- if (dpm.getPasswordQuality(admin, userId)
- > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+ if (check.isEnforcing(dpm, admin, userId)) {
if (enforcedAdmin == null) {
enforcedAdmin = new EnforcedAdmin(admin, userId);
} else {
@@ -408,50 +378,10 @@
}
}
}
+ return enforcedAdmin;
} else {
- // Return all admins for this user and the profiles that are visible from this
- // user that do not use a separate work challenge.
- final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
- for (UserInfo userInfo : um.getProfiles(userId)) {
- final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
- if (admins == null) {
- continue;
- }
- final boolean isSeparateProfileChallengeEnabled =
- lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
- for (ComponentName admin : admins) {
- if (!isSeparateProfileChallengeEnabled) {
- if (dpm.getPasswordQuality(admin, userInfo.id)
- > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
- if (enforcedAdmin == null) {
- enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
- } else {
- return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
- }
- // This same admins could have set policies both on the managed profile
- // and on the parent. So, if the admin has set the policy on the
- // managed profile here, we don't need to further check if that admin
- // has set policy on the parent admin.
- continue;
- }
- }
- if (userInfo.isManagedProfile()) {
- // If userInfo.id is a managed profile, we also need to look at
- // the policies set on the parent.
- DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
- if (parentDpm.getPasswordQuality(admin, userInfo.id)
- > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
- if (enforcedAdmin == null) {
- enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
- } else {
- return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
- }
- }
- }
- }
- }
+ return checkForLockSetting(context, userId, check);
}
- return enforcedAdmin;
}
/**
@@ -512,6 +442,65 @@
return enforcedAdmin;
}
+ private interface LockSettingCheck {
+ boolean isEnforcing(DevicePolicyManager dpm, ComponentName admin, @UserIdInt int userId);
+ }
+
+ /**
+ * Checks whether any of the user's profiles enforce the lock setting. A managed profile is only
+ * included if it does not have a separate challenege but the settings for it's parent (i.e. the
+ * user being checked) are always included.
+ */
+ private static EnforcedAdmin checkForLockSetting(
+ Context context, @UserIdInt int userId, LockSettingCheck check) {
+ final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ if (dpm == null) {
+ return null;
+ }
+ final LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
+ EnforcedAdmin enforcedAdmin = null;
+ // Return all admins for this user and the profiles that are visible from this
+ // user that do not use a separate work challenge.
+ for (UserInfo userInfo : UserManager.get(context).getProfiles(userId)) {
+ final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
+ if (admins == null) {
+ continue;
+ }
+ final boolean isSeparateProfileChallengeEnabled =
+ lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
+ for (ComponentName admin : admins) {
+ if (!isSeparateProfileChallengeEnabled) {
+ if (check.isEnforcing(dpm, admin, userInfo.id)) {
+ if (enforcedAdmin == null) {
+ enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
+ } else {
+ return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+ }
+ // This same admins could have set policies both on the managed profile
+ // and on the parent. So, if the admin has set the policy on the
+ // managed profile here, we don't need to further check if that admin
+ // has set policy on the parent admin.
+ continue;
+ }
+ }
+ if (userInfo.isManagedProfile()) {
+ // If userInfo.id is a managed profile, we also need to look at
+ // the policies set on the parent.
+ final DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
+ if (check.isEnforcing(parentDpm, admin, userInfo.id)) {
+ if (enforcedAdmin == null) {
+ enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
+ } else {
+ return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+ }
+ }
+ }
+ }
+ }
+ return enforcedAdmin;
+ }
+
public static EnforcedAdmin getProfileOrDeviceOwner(Context context, int userId) {
if (userId == UserHandle.USER_NULL) {
return null;
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/AnimatedImageView.java b/packages/SettingsLib/src/com/android/settingslib/widget/AnimatedImageView.java
index f5e39be..a8cd655 100644
--- a/packages/SettingsLib/src/com/android/settingslib/widget/AnimatedImageView.java
+++ b/packages/SettingsLib/src/com/android/settingslib/widget/AnimatedImageView.java
@@ -55,7 +55,7 @@
private void updateAnimating() {
if (mDrawable != null) {
- if (isShown() && mAnimating) {
+ if (getVisibility() == View.VISIBLE && mAnimating) {
mDrawable.start();
} else {
mDrawable.stop();
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index c2161ae..aee6c3c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -839,16 +839,19 @@
if (state == DetailedState.CONNECTED) {
IWifiManager wifiManager = IWifiManager.Stub.asInterface(
ServiceManager.getService(Context.WIFI_SERVICE));
- Network nw;
+ NetworkCapabilities nc = null;
try {
- nw = wifiManager.getCurrentNetwork();
- } catch (RemoteException e) {
- nw = null;
- }
- NetworkCapabilities nc = cm.getNetworkCapabilities(nw);
- if (nc != null && !nc.hasCapability(nc.NET_CAPABILITY_VALIDATED)) {
- return context.getString(R.string.wifi_connected_no_internet);
+ nc = cm.getNetworkCapabilities(wifiManager.getCurrentNetwork());
+ } catch (RemoteException e) {}
+
+ if (nc != null) {
+ if (nc.hasCapability(nc.NET_CAPABILITY_CAPTIVE_PORTAL)) {
+ return context.getString(
+ com.android.internal.R.string.network_available_sign_in);
+ } else if (!nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
+ return context.getString(R.string.wifi_connected_no_internet);
+ }
}
}
if (state == null) {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
new file mode 100644
index 0000000..025bbc2
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.UserManager;
+
+import com.android.internal.util.ArrayUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import java.util.Arrays;
+
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT;
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class RestrictedLockUtilsTest {
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private DevicePolicyManager mDevicePolicyManager;
+ @Mock
+ private UserManager mUserManager;
+
+ private static final int mUserId = 194;
+ private static final ComponentName mAdmin1 = new ComponentName("admin1", "admin1class");
+ private static final ComponentName mAdmin2 = new ComponentName("admin2", "admin2class");
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
+ .thenReturn(mDevicePolicyManager);
+ when(mContext.getSystemService(Context.USER_SERVICE))
+ .thenReturn(mUserManager);
+ }
+
+ @Test
+ public void checkIfKeyguardFeaturesDisabled_noEnforcedAdminForManagedProfile() {
+ setUpManagedProfile(mUserId);
+ setUpActiveAdmins(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
+
+ final EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_FINGERPRINT, mUserId);
+
+ assertThat(enforcedAdmin).isEqualTo(null);
+ }
+
+ @Test
+ public void checkIfKeyguardFeaturesDisabled_oneEnforcedAdminForManagedProfile() {
+ setUpManagedProfile(mUserId);
+ setUpActiveAdmins(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
+
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
+ .thenReturn(KEYGUARD_DISABLE_FINGERPRINT);
+
+ final EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_FINGERPRINT, mUserId);
+
+ assertThat(enforcedAdmin).isEqualTo(new EnforcedAdmin(mAdmin1, mUserId));
+ }
+
+ @Test
+ public void checkIfKeyguardFeaturesDisabled_multipleEnforcedAdminForManagedProfile() {
+ setUpManagedProfile(mUserId);
+ setUpActiveAdmins(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
+
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
+ .thenReturn(KEYGUARD_DISABLE_REMOTE_INPUT);
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin2, mUserId))
+ .thenReturn(KEYGUARD_DISABLE_REMOTE_INPUT);
+
+ final EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+ mContext, KEYGUARD_DISABLE_REMOTE_INPUT, mUserId);
+
+ assertThat(enforcedAdmin).isEqualTo(EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN);
+ }
+
+ private UserInfo setUpManagedProfile(int userId) {
+ final UserInfo userInfo = new UserInfo(userId, "myuser", UserInfo.FLAG_MANAGED_PROFILE);
+ when(mUserManager.getUserInfo(userId)).thenReturn(userInfo);
+ return userInfo;
+ }
+
+ private void setUpActiveAdmins(int userId, ComponentName[] activeAdmins) {
+ when(mDevicePolicyManager.getActiveAdminsAsUser(userId))
+ .thenReturn(Arrays.asList(activeAdmins));
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java
new file mode 100644
index 0000000..2c9c868
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.widget;
+
+import android.app.Activity;
+import android.graphics.drawable.AnimatedRotateDrawable;
+import android.view.View;
+import com.android.settingslib.TestConfig;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AnimatedImageViewTest {
+ private AnimatedImageView mAnimatedImageView;
+
+ @Before
+ public void setUp() {
+ Activity activity = Robolectric.setupActivity(Activity.class);
+ mAnimatedImageView = new AnimatedImageView(activity);
+ mAnimatedImageView.setImageDrawable(new AnimatedRotateDrawable());
+ }
+
+ @Test
+ public void testAnimation_ViewVisible_AnimationRunning() {
+ mAnimatedImageView.setVisibility(View.VISIBLE);
+ mAnimatedImageView.setAnimating(true);
+ AnimatedRotateDrawable drawable = (AnimatedRotateDrawable) mAnimatedImageView.getDrawable();
+ assertThat(drawable.isRunning()).isTrue();
+ }
+
+}
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index bb85de2..7206127 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -51,6 +51,7 @@
<bool name="def_wifi_on">false</bool>
<!-- 0 == never, 1 == only when plugged in, 2 == always -->
<integer name="def_wifi_sleep_policy">2</integer>
+ <bool name="def_wifi_wakeup_enabled">false</bool>
<bool name="def_networks_available_notification_on">true</bool>
<bool name="def_backup_enabled">false</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
index 222cc5c..3e6c3f2 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
@@ -119,7 +119,7 @@
// and twice max user count for system and secure.
final int size = 1 + 2 + 10 + 2 * UserManager.getMaxSupportedUsers();
try {
- mBackingStore = new MemoryIntArray(size, false);
+ mBackingStore = new MemoryIntArray(size);
if (DEBUG) {
Slog.e(LOG_TAG, "Created backing store " + mBackingStore);
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
index 461573f..cbeb878 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
@@ -243,8 +243,8 @@
return lines;
}
try {
- final Cursor cursor = provider.query(resolveCallingPackage(), uri, null, null, null,
- null, null);
+ final Cursor cursor = provider.query(resolveCallingPackage(), uri, null, null,
+ null);
try {
while (cursor != null && cursor.moveToNext()) {
lines.add(cursor.getString(1) + "=" + cursor.getString(2));
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
index 09879d8..d54e33f 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java
@@ -26,7 +26,7 @@
public static final String ACTION = "com.android.systemui.action.PLUGIN_NAV_BUTTON";
- public static final int VERSION = 1;
+ public static final int VERSION = 2;
/**
* Returns a view in the nav bar. If the id is set "back", "home", "recent_apps", "menu",
@@ -38,14 +38,15 @@
* Interface for button actions.
*/
interface ButtonInterface {
- void setImageResource(@DrawableRes int resId);
void setImageDrawable(@Nullable Drawable drawable);
void abortCurrentGesture();
- void setLandscape(boolean landscape);
+ void setVertical(boolean vertical);
void setCarMode(boolean carMode);
+
+ void setDarkIntensity(float intensity);
}
}
diff --git a/packages/SystemUI/res/color/qs_detail_empty.xml b/packages/SystemUI/res/color/qs_detail_empty.xml
deleted file mode 100644
index 4be39c7..0000000
--- a/packages/SystemUI/res/color/qs_detail_empty.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:alpha="0.14" android:color="@*android:color/quaternary_device_default_settings" />
-</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..0a6074b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..64bc40a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..fb44f22a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..a665e23
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..4f65660
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..c57face
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..bbaab44
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..dba0040
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..2b64b80
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..151a3c0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..3456a97
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..94cb032
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..5383215
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..3a22912
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..c7e4731
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..d2949f3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..06e4c26
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..1c855c4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..fbdc93c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_ime.png
new file mode 100644
index 0000000..419518c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home.png
new file mode 100644
index 0000000..a2406b1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_menu.png
new file mode 100644
index 0000000..50043eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..c449449
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp/ic_ime_switcher_default.xml b/packages/SystemUI/res/drawable-sw900dp/ic_ime_switcher_default.xml
new file mode 100644
index 0000000..bcf9cac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp/ic_ime_switcher_default.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="28.0dp"
+ android:height="28.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M20.000000,5.000000L4.000000,5.000000C2.900000,5.000000 2.000000,5.900000 2.000000,7.000000l0.000000,10.000000c0.000000,1.100000 0.900000,2.000000 2.000000,2.000000l16.000000,0.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000L22.000000,7.000000C22.000000,5.900000 21.100000,5.000000 20.000000,5.000000zM11.000000,8.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000L11.000000,8.000000zM11.000000,11.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000L11.000000,11.000000zM8.000000,8.000000l2.000000,0.000000l0.000000,2.000000L8.000000,10.000000L8.000000,8.000000zM8.000000,11.000000l2.000000,0.000000l0.000000,2.000000L8.000000,13.000000L8.000000,11.000000zM7.000000,13.000000L5.000000,13.000000l0.000000,-2.000000l2.000000,0.000000L7.000000,13.000000zM7.000000,10.000000L5.000000,10.000000L5.000000,8.000000l2.000000,0.000000L7.000000,10.000000zM16.000000,17.000000L8.000000,17.000000l0.000000,-2.000000l8.000000,0.000000L16.000000,17.000000zM16.000000,13.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L16.000000,13.000000zM16.000000,10.000000l-2.000000,0.000000L14.000000,8.000000l2.000000,0.000000L16.000000,10.000000zM19.000000,13.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L19.000000,13.000000zM19.000000,10.000000l-2.000000,0.000000L17.000000,8.000000l2.000000,0.000000L19.000000,10.000000z"
+ android:fillColor="@color/navigation_bar_icon_color"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..371a84d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..360ed77
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..96cecc9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..9ff9825
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..e505f5e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..472c55b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..c04d650
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..0f6d206
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..58bf920
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..f47533ec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..f299d97
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..84d6dc8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..d813bc7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..30e8782
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..83fc662
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..71101a1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..4a477ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..bc24c00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
index 24ac018..604e918 100644
--- a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
+++ b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
@@ -22,6 +22,6 @@
android:pathData="m18.250000,12.000000a6.250000,6.250000 0.000000,1.000000 1.000000,-12.500000 0.000000,6.250000 6.250000,0.000000 1.000000,1.000000 12.500000,0.000000z"
android:fillColor="?android:attr/colorPrimary" />
<path
- android:fillColor="#FFFFFFFF"
+ android:fillColor="?android:attr/colorControlNormal"
android:pathData="M20.000000,8.700000L20.000000,4.000000L15.300000,4.000000L12.000000,0.700000 8.700000,4.000000L4.000000,4.000000L4.000000,8.700000L0.700000,12.000000 4.000000,15.300000L4.000000,20.000000L8.700000,20.000000L12.000000,23.299999 15.300000,20.000000L20.000000,20.000000L20.000000,15.300000L23.299999,12.000000 20.000000,8.700000zM12.000000,18.000000C8.700000,18.000000 6.000000,15.300000 6.000000,12.000000 6.000000,8.700000 8.700000,6.000000 12.000000,6.000000c3.300000,0.000000 6.000000,2.700000 6.000000,6.000000 0.000000,3.300000 -2.700000,6.000000 -6.000000,6.000000zM12.000000,8.000000c-2.200000,0.000000 -4.000000,1.800000 -4.000000,4.000000 0.000000,2.200000 1.800000,4.000000 4.000000,4.000000 2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000 0.000000,-2.200000 -1.800000,-4.000000 -4.000000,-4.000000z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_data_saver.xml b/packages/SystemUI/res/drawable/ic_data_saver.xml
index 7356772..9c3bd3a 100644
--- a/packages/SystemUI/res/drawable/ic_data_saver.xml
+++ b/packages/SystemUI/res/drawable/ic_data_saver.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12.0,19.0c-3.9,0.0 -7.0,-3.1 -7.0,-7.0c0.0,-3.5 2.6,-6.4 6.0,-6.9L11.0,2.0C5.9,2.5 2.0,6.8 2.0,12.0c0.0,5.5 4.5,10.0 10.0,10.0c3.3,0.0 6.2,-1.6 8.1,-4.1l-2.6,-1.5C16.2,18.0 14.2,19.0 12.0,19.0z"/>
diff --git a/packages/SystemUI/res/drawable/ic_data_saver_off.xml b/packages/SystemUI/res/drawable/ic_data_saver_off.xml
index fd9701e..918c61c 100644
--- a/packages/SystemUI/res/drawable/ic_data_saver_off.xml
+++ b/packages/SystemUI/res/drawable/ic_data_saver_off.xml
@@ -18,11 +18,11 @@
android:height="24.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
- android:tint="#4DFFFFFF">
+ android:tint="?android:attr/colorControlNormal">
<path
- android:fillColor="#FFFFFFFF"
+ android:fillColor="#4DFFFFFF"
android:pathData="M12.0,19.0c-3.9,0.0 -7.0,-3.1 -7.0,-7.0c0.0,-3.5 2.6,-6.4 6.0,-6.9L11.0,2.0C5.9,2.5 2.0,6.8 2.0,12.0c0.0,5.5 4.5,10.0 10.0,10.0c3.3,0.0 6.2,-1.6 8.1,-4.1l-2.6,-1.5C16.2,18.0 14.2,19.0 12.0,19.0z"/>
<path
- android:fillColor="#FFFFFFFF"
+ android:fillColor="#4DFFFFFF"
android:pathData="M13.0,2.0l0.0,3.0c3.4,0.5 6.0,3.4 6.0,6.9c0.0,0.9 -0.2,1.8 -0.5,2.5l2.6,1.5c0.6,-1.2 0.9,-2.6 0.9,-4.1C22.0,6.8 18.0,2.6 13.0,2.0z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_hotspot_disable.xml b/packages/SystemUI/res/drawable/ic_hotspot_disable.xml
index 8249609..2570483 100644
--- a/packages/SystemUI/res/drawable/ic_hotspot_disable.xml
+++ b/packages/SystemUI/res/drawable/ic_hotspot_disable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_hotspot"
android:translateX="23.9778"
diff --git a/packages/SystemUI/res/drawable/ic_hotspot_enable.xml b/packages/SystemUI/res/drawable/ic_hotspot_enable.xml
index 5043bdf..31e7fe1 100644
--- a/packages/SystemUI/res/drawable/ic_hotspot_enable.xml
+++ b/packages/SystemUI/res/drawable/ic_hotspot_enable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_hotspot"
android:translateX="23.97354"
diff --git a/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml b/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml
index 4d9ca88..3345f61 100644
--- a/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml
+++ b/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml
@@ -21,5 +21,5 @@
android:viewportHeight="24.0">
<path
android:pathData="M20.000000,5.000000L4.000000,5.000000C2.900000,5.000000 2.000000,5.900000 2.000000,7.000000l0.000000,10.000000c0.000000,1.100000 0.900000,2.000000 2.000000,2.000000l16.000000,0.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000L22.000000,7.000000C22.000000,5.900000 21.100000,5.000000 20.000000,5.000000zM11.000000,8.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000L11.000000,8.000000zM11.000000,11.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000L11.000000,11.000000zM8.000000,8.000000l2.000000,0.000000l0.000000,2.000000L8.000000,10.000000L8.000000,8.000000zM8.000000,11.000000l2.000000,0.000000l0.000000,2.000000L8.000000,13.000000L8.000000,11.000000zM7.000000,13.000000L5.000000,13.000000l0.000000,-2.000000l2.000000,0.000000L7.000000,13.000000zM7.000000,10.000000L5.000000,10.000000L5.000000,8.000000l2.000000,0.000000L7.000000,10.000000zM16.000000,17.000000L8.000000,17.000000l0.000000,-2.000000l8.000000,0.000000L16.000000,17.000000zM16.000000,13.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L16.000000,13.000000zM16.000000,10.000000l-2.000000,0.000000L14.000000,8.000000l2.000000,0.000000L16.000000,10.000000zM19.000000,13.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L19.000000,13.000000zM19.000000,10.000000l-2.000000,0.000000L17.000000,8.000000l2.000000,0.000000L19.000000,10.000000z"
- android:fillColor="@color/navigation_bar_icon_color"/>
+ android:fillColor="?attr/singleToneColor"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_disable.xml b/packages/SystemUI/res/drawable/ic_invert_colors_disable.xml
index f901e86..49ee48b 100644
--- a/packages/SystemUI/res/drawable/ic_invert_colors_disable.xml
+++ b/packages/SystemUI/res/drawable/ic_invert_colors_disable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="icon"
android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml b/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml
index 994cf8c..5aeceba 100644
--- a/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml
+++ b/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="icon"
android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml
index bc545ba..8b2585b 100644
--- a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml
+++ b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml
@@ -18,7 +18,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_screen_rotation_48px_outlines"
android:translateX="24"
diff --git a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
index 0bd75d1..603d0bf 100644
--- a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
+++ b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
@@ -18,7 +18,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_screen_rotation_48px_outlines"
android:translateX="24"
diff --git a/packages/SystemUI/res/drawable/ic_mode_edit.xml b/packages/SystemUI/res/drawable/ic_mode_edit.xml
index 8a73686..f32da59 100644
--- a/packages/SystemUI/res/drawable/ic_mode_edit.xml
+++ b/packages/SystemUI/res/drawable/ic_mode_edit.xml
@@ -17,7 +17,8 @@
android:width="20.0dp"
android:height="20.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFF"
android:pathData="M3.0,17.25L3.0,21.0l3.75,0.0L17.81,9.94l-3.75,-3.75L3.0,17.25zM20.71,7.04c0.39,-0.3 0.39,-1.02 0.0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0.0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml
index 0ac6795..17185a7c 100644
--- a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml
+++ b/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml
@@ -18,7 +18,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="icon"
android:translateX="24"
diff --git a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml
index 0cca6e3..88bf486 100644
--- a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml
+++ b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml
@@ -18,7 +18,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="icon"
android:translateX="24"
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
index 0c65389..8a3e975 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml
index b9a315c..1dadc05 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_detail_empty.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_detail_empty.xml
index dd92126..33a4047 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_detail_empty.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_detail_empty.xml
@@ -17,9 +17,11 @@
android:width="56dp"
android:height="56dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:alpha="0.14"
+ android:tint="?android:attr/colorForeground">
<path
- android:fillColor="@color/qs_detail_empty"
+ android:fillColor="#FFFFFF"
android:pathData="M35.4,15.4L24.0,4.0l-2.0,0.0l0.0,15.2L12.8,10.0L10.0,12.8L21.2,24.0L10.0,35.2l2.8,2.8l9.2,-9.2L22.0,44.0l2.0,0.0l11.4,-11.4L26.8,24.0L35.4,15.4zM26.0,11.7l3.8,3.8L26.0,19.2L26.0,11.7zM29.8,32.6L26.0,36.3l0.0,-7.5L29.8,32.6z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml
index 0cb1f32..36eb418 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
index 9a68dad..2e9e741 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_detail_empty.xml b/packages/SystemUI/res/drawable/ic_qs_cast_detail_empty.xml
index 59dcea2..fc831f4 100644
--- a/packages/SystemUI/res/drawable/ic_qs_cast_detail_empty.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_detail_empty.xml
@@ -17,9 +17,11 @@
android:width="56dp"
android:height="56dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:alpha="0.14"
+ android:tint="?android:attr/colorForeground">
<path
- android:fillColor="@color/qs_detail_empty"
+ android:fillColor="#FFFFFF"
android:pathData="M42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,6.0l4.0,0.0l0.0,-6.0l36.0,0.0l0.0,28.0L28.0,38.0l0.0,4.0l14.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0zM2.0,36.0l0.0,6.0l6.0,0.0C8.0,38.7 5.3,36.0 2.0,36.0zM2.0,28.0l0.0,4.0c5.5,0.0 10.0,4.5 10.0,10.0l4.0,0.0C16.0,34.3 9.7,28.0 2.0,28.0zM2.0,20.0l0.0,4.0c9.9,0.0 18.0,8.1 18.0,18.0l4.0,0.0C24.0,29.8 14.1,20.0 2.0,20.0z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_off.xml b/packages/SystemUI/res/drawable/ic_qs_cast_off.xml
index 8051795..0fdbe1f 100644
--- a/packages/SystemUI/res/drawable/ic_qs_cast_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_off.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_on.xml b/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
index 794eb9e..d2e9eb2 100644
--- a/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml
index 28d2e26..164a557 100644
--- a/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml
@@ -18,7 +18,8 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:alpha=".3"
- android:width="64dp" >
+ android:width="64dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml
index f4c20a9..7e2eca8 100644
--- a/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M24.0,4.0C12.95,4.0 4.0,12.95 4.0,24.0s8.95,20.0 20.0,20.0 20.0,-8.95 20.0,-20.0S35.05,4.0 24.0,4.0zm10.0,22.0L14.0,26.0l0.0,-4.0l20.0,0.0l0.0,4.0z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml
index fb26c09..5f4fa11 100644
--- a/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml
@@ -17,7 +17,8 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_minus.xml b/packages/SystemUI/res/drawable/ic_qs_minus.xml
index 6a3410a..147a94b 100644
--- a/packages/SystemUI/res/drawable/ic_qs_minus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_minus.xml
@@ -17,7 +17,8 @@
android:height="24.0dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
similarity index 61%
rename from packages/SystemUI/res/drawable/qs_dual_tile_caret.xml
rename to packages/SystemUI/res/drawable/ic_qs_network_logging.xml
index 71400db..1340ae1 100644
--- a/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+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.
@@ -13,13 +13,17 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+<!-- Placeholder icon for network logging until the real icon is finalized-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="12.0dp"
+ android:height="12.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="#4DFFFFFF" >
<path
- android:fillColor="@color/qs_tile_text"
- android:pathData="M14.0,20.0l10.0,10.0 10.0,-10.0z"/>
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M7,18v-2h6v2H7z M7,14v-2h10v2H7z M8.5,9 12,5.5 15.5,9 13,9 13,13 11,13 11,9z"/>
+
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml
index 778ccbc..b99dc03 100644
--- a/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml
@@ -18,10 +18,11 @@
android:height="64dp"
android:viewportWidth="24"
android:viewportHeight="24"
- android:alpha="0.3">
+ android:alpha="0.3"
+ android:tint="?android:attr/colorControlNormal">
<path
- android:fillColor="#FFF"
+ android:fillColor="#FFFFFF"
android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" />
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
index aaca663..d875592 100644
--- a/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
@@ -17,10 +17,11 @@
android:width="64dp"
android:height="64dp"
android:viewportWidth="24"
- android:viewportHeight="24">
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorControlNormal">
<path
- android:fillColor="#FFF"
+ android:fillColor="#FFFFFF"
android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" />
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_no_sim.xml b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
index bd46012..2d831b2 100644
--- a/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
@@ -17,7 +17,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_plus.xml b/packages/SystemUI/res/drawable/ic_qs_plus.xml
index 393f51c..1f254d1 100644
--- a/packages/SystemUI/res/drawable/ic_qs_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_plus.xml
@@ -17,7 +17,8 @@
android:height="24.0dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
index b78d3bf..0673848 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
@@ -18,7 +18,8 @@
android:width="32.0dp"
android:height="32.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
android:fillAlpha="0.3"
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
index e055de7..fbf9e71 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
@@ -18,7 +18,8 @@
android:width="32.0dp"
android:height="32.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z"
android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml
index 71c40df..3a55623 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml
@@ -17,7 +17,8 @@
android:width="16.0dp"
android:height="32dp"
android:viewportWidth="12.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M3.500000,11.000000L1.800000,11.000000L1.800000,4.400000L0.200000,5.100000L0.200000,3.700000l3.100000,-1.300000l0.200000,0.000000L3.500000,11.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
index 8a48817..e9f5a0b 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
@@ -18,7 +18,8 @@
android:width="32.0dp"
android:height="32.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z"
android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
index 39cc94c..769d648 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
@@ -18,7 +18,8 @@
android:width="32.0dp"
android:height="32.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
android:fillAlpha="0.3"
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml
index e9a57ea..ddd8065 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml
@@ -17,7 +17,8 @@
android:width="17.333334dp"
android:height="32dp"
android:viewportWidth="13.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M2.000000,6.000000l0.800000,0.000000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000s0.200000,-0.500000 0.200000,-0.900000c0.000000,-0.300000 -0.100000,-0.600000 -0.200000,-0.800000S3.200000,3.700000 2.900000,3.700000C2.700000,3.700000 2.500000,3.800000 2.300000,4.000000S2.100000,4.400000 2.100000,4.700000L0.500000,4.700000C0.500000,4.000000 0.700000,3.400000 1.100000,3.000000s1.000000,-0.600000 1.700000,-0.600000c0.800000,0.000000 1.400000,0.200000 1.900000,0.600000s0.700000,1.000000 0.700000,1.800000c0.000000,0.400000 -0.100000,0.700000 -0.300000,1.100000S4.600000,6.500000 4.300000,6.600000C4.700000,6.800000 5.000000,7.100000 5.200000,7.400000s0.300000,0.700000 0.300000,1.200000c0.000000,0.800000 -0.200000,1.400000 -0.700000,1.800000s-1.100000,0.700000 -1.900000,0.700000c-0.700000,0.000000 -1.300000,-0.200000 -1.800000,-0.600000s-0.700000,-1.000000 -0.700000,-1.800000L2.000000,8.700000C2.000000,9.000000 2.100000,9.300000 2.300000,9.500000s0.400000,0.300000 0.600000,0.300000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000S3.900000,9.000000 3.900000,8.600000c0.000000,-0.500000 -0.100000,-0.800000 -0.300000,-1.000000S3.200000,7.300000 2.800000,7.300000L2.000000,7.300000L2.000000,6.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
index 012e95e..1bec1b8 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
@@ -18,7 +18,8 @@
android:width="32.0dp"
android:height="32.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml
index 42045d1..8e1f8eb 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml
@@ -17,7 +17,8 @@
android:width="16.0dp"
android:height="32dp"
android:viewportWidth="12.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M4.600000,7.800000l0.700000,0.000000l0.000000,1.300000L4.600000,9.100000L4.600000,11.000000L3.000000,11.000000L3.000000,9.200000L0.100000,9.200000L0.000000,8.100000L3.000000,2.500000l1.700000,0.000000L4.700000,7.800000zM1.600000,7.800000L3.000000,7.800000l0.000000,-3.000000L2.900000,5.000000L1.600000,7.800000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
index 4d7f325..e0c6b68 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml
index 96e2fd4..1c068e5 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml
@@ -17,7 +17,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:name="dot1"
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml
index 4f253e3..0a85392 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml
@@ -18,7 +18,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M21.799999,22.299999l-1.199999,-1.299999 0.000000,0.000000 -9.600000,-10.000000 0.000000,0.000000 -6.400000,-6.700000 -1.300000,1.300000 6.400000,6.700000 -8.700000,8.700000 16.900000,0.000000 2.600000,2.700001z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml b/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
index e49a409..4c90421 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
@@ -17,7 +17,8 @@
android:width="6.6666665dp"
android:height="32dp"
android:viewportWidth="5.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M4.400000,7.300000L1.700000,7.300000l0.000000,2.400000l3.300000,0.000000L5.000000,11.000000L0.000000,11.000000L0.000000,2.500000l4.900000,0.000000l0.000000,1.300000L1.700000,3.800000l0.000000,2.100000l2.800000,0.000000L4.500000,7.300000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml
index 326373d..db4df76 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml
@@ -18,7 +18,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml
index 8baa4eb..6e5439d 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml
@@ -18,7 +18,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M2.0,22.0l20.0,0.0 0.0,-20.0z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml
index bf19a718..194edc3 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml
@@ -18,7 +18,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml
index 01839e85..b57af5c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml
@@ -18,7 +18,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml
index 48151ad..7d754a8 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml
@@ -18,7 +18,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
index 9d42a44..64aadf9 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
@@ -17,7 +17,8 @@
android:width="9.333333dp"
android:height="32dp"
android:viewportWidth="7.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M6.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S0.700000,9.000000 0.700000,7.900000L0.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000L4.700000,5.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S4.000000,3.700000 3.600000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S2.300000,5.000000 2.300000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L4.700000,7.800000L3.500000,7.800000L3.500000,6.600000l2.900000,0.000000L6.400000,9.900000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml b/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
index f509d71..31918a9 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
@@ -17,7 +17,8 @@
android:width="8.0dp"
android:height="32dp"
android:viewportWidth="6.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M6.000000,11.000000L4.400000,11.000000L4.400000,7.500000L1.700000,7.500000L1.700000,11.000000L0.000000,11.000000L0.000000,2.500000l1.700000,0.000000l0.000000,3.700000l2.700000,0.000000L4.400000,2.500000L6.000000,2.500000L6.000000,11.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_in.xml b/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
index 236fdac..4122b76 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
@@ -17,7 +17,8 @@
android:width="6.0dp"
android:height="32dp"
android:viewportWidth="6.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M6.000000,15.700000l-3.000000,5.599999 -3.000000,-5.599999z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml
index b7242e6..8766075 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml
@@ -17,7 +17,8 @@
android:width="17.333334dp"
android:height="32dp"
android:viewportWidth="13.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M2.000000,9.700000l2.000000,0.000000L4.000000,11.000000L0.300000,11.000000L0.300000,2.500000L2.000000,2.500000L2.000000,9.700000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
index 3af0629..5ff7d85 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml b/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml
index f7fd97c..4e65004 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml
@@ -18,7 +18,8 @@
android:width="32dp"
android:height="32dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M2.000000,22.000000l20.000000,0.000000L22.000000,2.000000L2.000000,22.000000zM20.000000,20.000000L6.800000,20.000000L20.000000,6.800000L20.000000,20.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_out.xml b/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
index c510972..a3823ae 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
@@ -17,7 +17,8 @@
android:width="6.0dp"
android:height="32dp"
android:viewportWidth="6.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M0.000000,13.700000l3.000000,-5.700000 3.000000,5.700000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_r.xml b/packages/SystemUI/res/drawable/ic_qs_signal_r.xml
index 66f64c9..2c10dc3f 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_r.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_r.xml
@@ -17,7 +17,8 @@
android:width="8.0dp"
android:height="32dp"
android:viewportWidth="6.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M2.800000,7.900000l-1.000000,0.000000L1.800000,11.000000L0.200000,11.000000L0.200000,2.500000l2.700000,0.000000c0.900000,0.000000 1.500000,0.200000 2.000000,0.700000s0.700000,1.100000 0.700000,1.900000c0.000000,0.600000 -0.100000,1.100000 -0.300000,1.500000S4.800000,7.200000 4.400000,7.400000l1.500000,3.500000L5.900000,11.000000L4.100000,11.000000L2.800000,7.900000zM1.800000,6.500000l1.100000,0.000000c0.400000,0.000000 0.600000,-0.100000 0.800000,-0.400000S4.000000,5.600000 4.000000,5.200000c0.000000,-0.400000 -0.100000,-0.800000 -0.300000,-1.000000S3.300000,3.800000 2.900000,3.800000L1.800000,3.800000L1.800000,6.500000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
index e6f9292..fe963b1 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
android:fillAlpha="0.3"
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
index d423ccb..82d2be2 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M13.8,13.2c-0.1,0.0 -0.3,-0.1 -0.4,-0.1c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,0.0 -0.6,-0.1 -0.9,-0.1c0.0,0.0 0.0,0.0 -0.1,0.0c0.0,0.0 0.0,0.0 0.0,0.0s0.0,0.0 0.0,0.0c0.0,0.0 0.0,0.0 -0.1,0.0c-0.3,0.0 -0.6,0.0 -0.9,0.1c-0.1,0.0 -0.3,0.0 -0.4,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.1,0.0 -0.1,0.0 -0.2,0.1c-1.6,0.5 -2.7,1.3 -2.8,1.5l5.3,6.6l0.0,0.0l0.0,0.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.700002,13.2z"
android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
index 1982130..f30ba76 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M13.8,12.2l4.9,0.0c-1.0,-0.7 -3.4,-2.2 -6.7,-2.2c-4.1,0.0 -6.9,2.2 -7.2,2.5l7.2,9.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.800001,12.2z"
android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
index b350111..8a17083 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M13.8,12.2l5.7,0.0l1.0,-1.2C20.0,10.6 16.8,8.0 12.0,8.0s-8.0,2.6 -8.5,3.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
index 136a004..fcd57d0 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_detail_empty.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_detail_empty.xml
index ad6b247..7993c80 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_detail_empty.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_detail_empty.xml
@@ -17,9 +17,11 @@
android:width="56dp"
android:height="56dp"
android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:viewportHeight="48.0"
+ android:alpha="0.14"
+ android:tint="?android:attr/colorForeground">
<path
android:pathData="M24.0,4.0C15.0,4.0 6.7,7.0 0.0,12.0l24.0,32.0l24.0,-32.0C41.3,7.0 33.0,4.0 24.0,4.0z"
- android:fillColor="@color/qs_detail_empty" />
+ android:fillColor="#FFFFFF" />
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml
index c505783..bbff2e1 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml
@@ -17,7 +17,8 @@
android:width="32.0dp"
android:height="29.5dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M17.500000,16.500000L5.800000,3.400000c0.000000,0.000000 0.000000,0.000000 0.000000,0.000000l-2.700000,-3.000000L1.600000,1.800000l2.200000,2.500000c-2.000000,1.000000 -3.200000,2.000000 -3.400000,2.200000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l3.200000,-3.900000l2.400000,2.700000l1.500000,-1.400000L17.500000,16.500000L17.500000,16.500000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml
index 2dcdb71..071892a 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml
@@ -17,7 +17,8 @@
android:width="26.0dp"
android:height="24.0dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M21.0,8.5
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml
index 1bc7438..c0e1037 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml
@@ -17,7 +17,8 @@
android:width="32.0dp"
android:height="29.5dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml
index 5856115..f609295 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml
@@ -17,7 +17,8 @@
android:width="32.0dp"
android:height="29.5dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M13.100000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.500000,6.500000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml
index 4a5e1f8..f44b303 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml
@@ -17,7 +17,8 @@
android:width="32.0dp"
android:height="29.5dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml
index 965442d..850f5b9 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml
@@ -17,7 +17,8 @@
android:width="32.0dp"
android:height="29.5dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml
index b29d3f9..8ccc1fd9 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml
@@ -17,7 +17,8 @@
android:width="32.0dp"
android:height="29.5dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml
index 3d58869..45cfc1c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml
@@ -17,7 +17,8 @@
android:width="32.0dp"
android:height="29.5dp"
android:viewportWidth="26.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#4DFFFFFF"
android:pathData="M13.000000,2.000000C7.700000,2.000000 3.700000,3.900000 0.400000,6.400000L13.000000,22.000000L25.600000,6.500000C22.299999,4.000000 18.299999,2.000000 13.000000,2.000000zM13.000000,18.600000L3.300000,7.000000l0.000000,0.000000l0.000000,0.000000C6.000000,5.300000 8.700000,4.000000 13.000000,4.000000s7.000000,1.400000 9.700000,3.000000l0.000000,0.000000l0.000000,0.000000L13.000000,18.600000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_settings_20dp.xml b/packages/SystemUI/res/drawable/ic_settings_20dp.xml
index 3170f86..45ee94f 100644
--- a/packages/SystemUI/res/drawable/ic_settings_20dp.xml
+++ b/packages/SystemUI/res/drawable/ic_settings_20dp.xml
@@ -17,7 +17,8 @@
android:width="20dp"
android:height="20dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z"
android:fillColor="#ffffffff" />
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml
index 09a67e1..2ff0de4 100644
--- a/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_signal_airplane"
android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml
index e30b21f..9987279 100644
--- a/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_signal_airplane"
android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml
index 35844b7..542797a 100644
--- a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_signal_flashlight"
android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml
index d53608f..a5ba05b 100644
--- a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_signal_flashlight"
android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_signal_location_disable.xml b/packages/SystemUI/res/drawable/ic_signal_location_disable.xml
index 439851d..e36f270 100644
--- a/packages/SystemUI/res/drawable/ic_signal_location_disable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_location_disable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_signal_location"
android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_signal_location_enable.xml b/packages/SystemUI/res/drawable/ic_signal_location_enable.xml
index 8614458..46a72bc 100644
--- a/packages/SystemUI/res/drawable/ic_signal_location_enable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_location_enable.xml
@@ -20,7 +20,8 @@
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
- android:viewportWidth="48" >
+ android:viewportWidth="48"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_signal_location"
android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_volume_alarm.xml b/packages/SystemUI/res/drawable/ic_volume_alarm.xml
index a8ca0d6..e64f445 100644
--- a/packages/SystemUI/res/drawable/ic_volume_alarm.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_alarm.xml
@@ -17,10 +17,11 @@
android:height="24.0dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal">
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M44.0,11.44l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-28.24,-4.66l-2.57,-3.06 -9.19,7.71 2.57,3.06 9.19,-7.71zm9.24,9.22l-3.0,0.0l0.0,12.0l9.49,5.71 1.51,-2.47 -8.0,-4.74l0.0,-10.5zm-1.01,-8.0c-9.95,0.0 -17.99,8.06 -17.99,18.0s8.04,18.0 17.99,18.0 18.01,-8.06 18.01,-18.0 -8.06,-18.0 -18.01,-18.0zm0.01,32.0c-7.73,0.0 -14.0,-6.27 -14.0,-14.0s6.27,-14.0 14.0,-14.0 14.0,6.27 14.0,14.0 -6.26,14.0 -14.0,14.0z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml b/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
index 8e2f083..37d7690 100644
--- a/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
@@ -17,10 +17,11 @@
android:height="24.0dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M24.0,12.0c7.73,0.0 14.0,6.27 14.0,14.0 0.0,1.69 -0.31,3.3 -0.86,4.8l3.04,3.04c1.16,-2.37 1.82,-5.03 1.82,-7.84 0.0,-9.94 -8.06,-18.0 -18.01,-18.0 -2.81,0.0 -5.46,0.66 -7.84,1.81l3.05,3.05c1.5,-0.55 3.11,-0.86 4.8,-0.86zm20.0,-0.56l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-38.16,-6.85l-2.55,2.54 2.66,2.66 -2.22,1.86 2.84,2.84 2.22,-1.86 1.6,1.6c-2.73,3.16 -4.39,7.27 -4.39,11.77 0.0,9.94 8.04,18.0 17.99,18.0 4.51,0.0 8.62,-1.67 11.77,-4.4l4.4,4.4 2.54,-2.55 -34.91,-34.91 -1.95,-1.95zm27.1,32.19c-2.43,2.01 -5.54,3.22 -8.94,3.22 -7.73,0.0 -14.0,-6.27 -14.0,-14.0 0.0,-3.4 1.21,-6.51 3.22,-8.94l19.72,19.72zm-16.91,-30.23l-2.84,-2.84 -1.7,1.43 2.84,2.84 1.7,-1.43z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml b/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
index 71df4d3..5c3c650 100644
--- a/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
@@ -17,10 +17,11 @@
android:height="24.0dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M29.41,19.0L34.0,14.41L34.0,22.0l1.0,0.0l5.71,-5.71 -4.3,-4.29 4.29,-4.29L35.0,2.0l-1.0,0.0l0.0,7.59L29.41,5.0 28.0,6.41 33.59,12.0 28.0,17.59 29.41,19.0zM36.0,5.83l1.88,1.88L36.0,9.59L36.0,5.83zm0.0,8.58l1.88,1.88L36.0,18.17l0.0,-3.76zM40.0,31.0c-2.49,0.0 -4.89,-0.4 -7.14,-1.14 -0.69,-0.22 -1.48,-0.06 -2.0,0.49l-4.4,4.41c-5.67,-2.88 -10.29,-7.51 -13.18,-13.17l4.4,-4.41c0.55,-0.5 0.71,-1.3 0.49,-2.03C17.4,12.9 17.0,10.49 17.0,8.0c0.0,-1.11 -0.89,-2.0 -2.0,-2.0L8.0,6.0c-1.11,0.0 -2.0,0.89 -2.0,2.0 0.0,18.78 15.22,34.0 34.0,34.0 1.11,0.0 2.0,-0.89 2.0,-2.0l0.0,-7.0c0.0,-1.11 -0.89,-2.0 -2.0,-2.0z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_collapse.xml b/packages/SystemUI/res/drawable/ic_volume_collapse.xml
index dc6d301..0f488a4 100644
--- a/packages/SystemUI/res/drawable/ic_volume_collapse.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_collapse.xml
@@ -18,7 +18,8 @@
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="24dp" >
+ android:width="24dp"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="chevron_02"
diff --git a/packages/SystemUI/res/drawable/ic_volume_expand.xml b/packages/SystemUI/res/drawable/ic_volume_expand.xml
index a60623f..70ff1f3 100644
--- a/packages/SystemUI/res/drawable/ic_volume_expand.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_expand.xml
@@ -18,7 +18,8 @@
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="24dp" >
+ android:width="24dp"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="chevron_01"
diff --git a/packages/SystemUI/res/drawable/ic_volume_media.xml b/packages/SystemUI/res/drawable/ic_volume_media.xml
index 97089f1..d689207 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media.xml
@@ -17,10 +17,11 @@
android:height="24.0dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M12.0,3.0l0.0,9.28c-0.47,-0.17 -0.97,-0.28 -1.5,-0.28C8.01,12.0 6.0,14.01 6.0,16.5S8.01,21.0 10.5,21.0c2.31,0.0 4.2,-1.75 4.45,-4.0L15.0,17.0L15.0,6.0l4.0,0.0L19.0,3.0l-7.0,0.0z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_bt.xml b/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
index 3364d9c..9b7b2da 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
@@ -17,13 +17,14 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M17.0,3.0l-7.0,0.0l0.0,9.3C9.5,12.1 9.0,12.0 8.5,12.0C6.0,12.0 4.0,14.0 4.0,16.5S6.0,21.0 8.5,21.0s4.5,-2.3 4.5,-4.5C13.0,14.7 13.0,6.0 13.0,6.0l4.0,0.0L17.0,3.0z"/>
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M23.4,9.9L20.5,7.0L20.0,7.0l0.0,3.8l-2.3,-2.3L17.0,9.2l2.8,2.8L17.0,14.8l0.7,0.7l2.3,-2.3L20.0,17.0l0.5,0.0l2.8,-2.8L21.2,12.0L23.4,9.9zM21.0,8.9l0.9,0.9l-0.9,1.0L21.0,8.9zM21.9,14.2L21.0,15.1l0.0,-1.9L21.9,14.2z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
index 39f54f1..17ac01d 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
@@ -17,16 +17,17 @@
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24dp" >
+ android:width="24dp"
+ android:tint="?android:attr/colorControlNormal">
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M13.0,6.0l4.0,0.0L17.0,3.0l-7.0,0.0l0.0,5.6l3.0,3.0C13.0,8.8 13.0,6.0 13.0,6.0z"/>
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M2.1,5.7L8.4,12.0C6.0,12.1 4.0,14.0 4.0,16.5S6.0,21.0 8.5,21.0c2.7,0.0 4.5,-2.3 4.5,-4.3l0.0,-0.1l3.9,3.9l1.3,-1.3L3.4,4.5L2.1,5.7z"/>
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M23.4,9.9L20.5,7.0L20.0,7.0l0.0,3.8l-2.3,-2.3L17.0,9.2l2.8,2.8L17.0,14.8l0.7,0.7l2.3,-2.3L20.0,17.0l0.5,0.0l2.8,-2.8L21.2,12.0L23.4,9.9zM21.0,8.9l0.9,0.9l-0.9,1.0L21.0,8.9zM21.9,14.2L21.0,15.1l0.0,-1.9L21.9,14.2z"/>
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
index beb806c..267d09d 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
@@ -17,13 +17,14 @@
android:height="24.0dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M15.0,6.0l4.0,0.0L19.0,3.0l-7.0,0.0l0.0,5.6l3.0,3.0C15.0,8.8 15.0,6.0 15.0,6.0z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M4.8,3.9L3.5,5.1l6.9,6.9C8.0,12.1 6.0,14.0 6.0,16.5C6.0,19.0 8.0,21.0 10.5,21.0c2.7,0.0 4.5,-2.3 4.5,-4.3c0.0,0.0 0.0,-0.1 0.0,-0.1l4.0,4.0l1.3,-1.3L4.8,3.9z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_remote.xml b/packages/SystemUI/res/drawable/ic_volume_remote.xml
index b363178..fe396d9 100644
--- a/packages/SystemUI/res/drawable/ic_volume_remote.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_remote.xml
@@ -17,10 +17,11 @@
android:height="24dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0"
- android:width="24dp" >
+ android:width="24dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M2.0,36.0l0.0,6.0l6.0,0.0C8.0,38.7 5.3,36.0 2.0,36.0zM2.0,28.0l0.0,4.0c5.5,0.0 10.0,4.5 10.0,10.0l4.0,0.0C16.0,34.3 9.7,28.0 2.0,28.0zM38.0,14.0L10.0,14.0l0.0,3.3c7.9,2.6 14.2,8.8 16.7,16.7L38.0,34.0L38.0,14.0zM2.0,20.0l0.0,4.0c9.9,0.0 18.0,8.1 18.0,18.0l4.0,0.0C24.0,29.8 14.1,20.0 2.0,20.0zM42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,6.0l4.0,0.0l0.0,-6.0l36.0,0.0l0.0,28.0L28.0,38.0l0.0,4.0l14.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_remote_mute.xml b/packages/SystemUI/res/drawable/ic_volume_remote_mute.xml
index 5f39ad7..2e05122 100644
--- a/packages/SystemUI/res/drawable/ic_volume_remote_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_remote_mute.xml
@@ -17,22 +17,23 @@
android:height="24.0dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M23.7,21.3l-1.1,-1.0c0.0,0.0 0.0,0.0 0.0,0.0L21.0,18.8l0.0,0.0L5.8,5.0l0.0,0.0L3.6,3.0l0.0,0.0L1.7,1.3L0.3,2.7l1.1,1.0C1.2,4.1 1.0,4.5 1.0,5.0l0.0,3.0l2.0,0.0L3.0,5.2L18.2,19.0L14.0,19.0l0.0,2.0l6.4,0.0l1.9,1.7L23.7,21.3z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M21.0,5.0l0.0,11.1l2.0,1.8L23.0,5.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0L6.6,3.0l2.2,2.0L21.0,5.0z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M1.0,18.0l0.0,3.0l3.0,0.0C4.0,19.3 2.7,18.0 1.0,18.0z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M1.0,14.0l0.0,2.0c2.8,0.0 5.0,2.2 5.0,5.0l2.0,0.0C8.0,17.1 4.9,14.0 1.0,14.0z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M1.0,10.0l0.0,2.0c5.0,0.0 9.0,4.0 9.0,9.0l2.0,0.0C12.0,14.9 7.1,10.0 1.0,10.0z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer.xml b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
index c566d5a..18af711 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
@@ -17,10 +17,11 @@
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24dp" >
+ android:width="24dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,16.0l0.0,-5.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0L18.0,16.0z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml b/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
index 0c20361..bc926c3 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
@@ -17,10 +17,11 @@
android:height="24dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0"
- android:width="24dp" >
+ android:width="24dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M23.000000,44.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000l-8.000000,0.000000C19.000000,42.200001 20.799999,44.000000 23.000000,44.000000zM36.000000,21.000000c0.000000,-6.100000 -4.300000,-11.300000 -10.000000,-12.600000L26.000000,7.000000c0.000000,-1.700000 -1.300000,-3.000000 -3.000000,-3.000000c-1.700000,0.000000 -3.000000,1.300000 -3.000000,3.000000l0.000000,1.400000c-1.000000,0.200000 -2.000000,0.600000 -2.900000,1.100000L36.000000,28.400000L36.000000,21.000000zM35.500000,38.000000l4.000000,4.000000l2.500000,-2.500000L8.500000,6.000000L6.000000,8.500000l5.800000,5.800000C10.700000,16.299999 10.000000,18.600000 10.000000,21.000000l0.000000,11.000000l-4.000000,4.000000l0.000000,2.000000L35.500000,38.000000z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml b/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
index 38b3234..ffbffad 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
@@ -17,10 +17,11 @@
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24dp" >
+ android:width="24dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M0.0,15.0l2.0,0.0L2.0,9.0L0.0,9.0L0.0,15.0zM3.0,17.0l2.0,0.0L5.0,7.0L3.0,7.0L3.0,17.0zM22.0,9.0l0.0,6.0l2.0,0.0L24.0,9.0L22.0,9.0zM19.0,17.0l2.0,0.0L21.0,7.0l-2.0,0.0L19.0,17.0zM16.5,3.0l-9.0,0.0C6.7,3.0 6.0,3.7 6.0,4.5l0.0,15.0C6.0,20.3 6.7,21.0 7.5,21.0l9.0,0.0c0.8,0.0 1.5,-0.7 1.5,-1.5l0.0,-15.0C18.0,3.7 17.3,3.0 16.5,3.0zM16.0,19.0L8.0,19.0L8.0,5.0l8.0,0.0L16.0,19.0z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_settings.xml b/packages/SystemUI/res/drawable/ic_volume_settings.xml
deleted file mode 100644
index 9f79b5a..0000000
--- a/packages/SystemUI/res/drawable/ic_volume_settings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
- Copyright (C) 2015 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="20dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0"
- android:width="20dp" >
-
- <path
- android:fillColor="@color/volume_settings_icon_color"
- android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z" />
-
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_system.xml b/packages/SystemUI/res/drawable/ic_volume_system.xml
index ccd8e18..71eed34 100644
--- a/packages/SystemUI/res/drawable/ic_volume_system.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_system.xml
@@ -17,16 +17,17 @@
android:height="24.0dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M17.7,14.8l-4.5,-2.3c-0.2,-0.1 -0.4,-0.1 -0.5,-0.1l-0.8,0.0l0.0,-6.0c0.0,-0.8 -0.7,-1.5 -1.5,-1.5S8.9,5.6 8.9,6.4l0.0,10.7l-3.4,-0.7c-0.1,0.0 -0.2,0.0 -0.2,0.0c-0.3,0.0 -0.6,0.1 -0.8,0.3l-0.8,0.8l4.9,4.9c0.3,0.3 0.6,0.4 1.1,0.4l6.8,0.0c0.8,0.0 1.3,-0.6 1.4,-1.3l0.8,-5.3c0.0,-0.1 0.0,-0.1 0.0,-0.2C18.6,15.5 18.2,15.0 17.7,14.8z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M14.3,8.8l1.8,0.9c1.5,-2.0 1.4,-4.8 -0.4,-6.6l-1.4,1.4C15.5,5.7 15.5,7.6 14.3,8.8z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M17.9,10.6l1.8,0.9C22.0,8.0 21.6,3.3 18.5,0.3l-1.4,1.4C19.5,4.1 19.8,7.9 17.9,10.6z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_system_mute.xml b/packages/SystemUI/res/drawable/ic_volume_system_mute.xml
index dfcb655..baad92a 100644
--- a/packages/SystemUI/res/drawable/ic_volume_system_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_system_mute.xml
@@ -17,19 +17,20 @@
android:height="24.0dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M14.3,8.8l1.8,0.9c1.5,-2.0 1.4,-4.8 -0.4,-6.6l-1.4,1.4C15.5,5.7 15.5,7.6 14.3,8.8z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M17.9,10.6l1.8,0.9C22.0,8.0 21.6,3.3 18.5,0.3l-1.4,1.4C19.5,4.1 19.8,7.9 17.9,10.6z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M22.0,20.6l-3.5,-2.8l0.0,0.0l-9.6,-7.6l0.0,0.0L3.2,5.7L2.0,7.3l6.9,5.4L8.9,17.0l-3.4,-0.7c-0.1,0.0 -0.2,0.0 -0.2,0.0c-0.3,0.0 -0.6,0.1 -0.8,0.3l-0.8,0.8l4.9,4.9c0.3,0.3 0.6,0.4 1.1,0.4l6.8,0.0c0.8,0.0 1.3,-0.6 1.4,-1.3l0.2,-1.5l2.6,2.1L22.0,20.6z" />
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M11.9,6.4c0.0,-0.8 -0.7,-1.5 -1.5,-1.5S8.9,5.6 8.9,6.4l0.0,1.5l3.0,2.4L11.9,6.4z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_voice.xml b/packages/SystemUI/res/drawable/ic_volume_voice.xml
index 133253e..7dc3dac 100644
--- a/packages/SystemUI/res/drawable/ic_volume_voice.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_voice.xml
@@ -17,10 +17,11 @@
android:height="24.0dp"
android:viewportHeight="48.0"
android:viewportWidth="48.0"
- android:width="24.0dp" >
+ android:width="24.0dp"
+ android:tint="?android:attr/colorControlNormal" >
<path
- android:fillColor="@color/volume_icon_color"
+ android:fillColor="#FFFFFF"
android:pathData="M13.25,21.59c2.88,5.66 7.51,10.29 13.18,13.17l4.4,-4.41c0.55,-0.55 1.34,-0.71 2.03,-0.49C35.1,30.6 37.51,31.0 40.0,31.0c1.11,0.0 2.0,0.89 2.0,2.0l0.0,7.0c0.0,1.11 -0.89,2.0 -2.0,2.0C21.22,42.0 6.0,26.78 6.0,8.0c0.0,-1.1 0.9,-2.0 2.0,-2.0l7.0,0.0c1.11,0.0 2.0,0.89 2.0,2.0 0.0,2.4 0.4,4.9 1.14,7.1 0.2,0.6 0.06,1.48 -0.49,2.03l-4.4,4.42z" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/back.xml b/packages/SystemUI/res/layout/back.xml
index d256622..4e8726b 100644
--- a/packages/SystemUI/res/layout/back.xml
+++ b/packages/SystemUI/res/layout/back.xml
@@ -21,7 +21,6 @@
android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
android:layout_weight="0"
- android:src="@drawable/ic_sysbar_back"
systemui:keyCode="4"
android:scaleType="center"
android:contentDescription="@string/accessibility_back"
diff --git a/packages/SystemUI/res/layout/home.xml b/packages/SystemUI/res/layout/home.xml
index f11592d..9586327 100644
--- a/packages/SystemUI/res/layout/home.xml
+++ b/packages/SystemUI/res/layout/home.xml
@@ -20,7 +20,6 @@
android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
android:layout_weight="0"
- android:src="@drawable/ic_sysbar_home"
systemui:keyCode="3"
android:scaleType="center"
android:contentDescription="@string/accessibility_home"
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
index 90b74d0..5e85ba0 100644
--- a/packages/SystemUI/res/layout/menu_ime.xml
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -25,7 +25,6 @@
android:layout_width="@dimen/navigation_extra_key_width"
android:layout_height="match_parent"
android:layout_marginEnd="2dp"
- android:src="@drawable/ic_sysbar_menu"
android:scaleType="centerInside"
systemui:keyCode="82"
android:visibility="invisible"
@@ -36,7 +35,6 @@
android:layout_width="@dimen/navigation_extra_key_width"
android:layout_height="match_parent"
android:layout_marginEnd="2dp"
- android:src="@drawable/ic_ime_switcher_default"
android:visibility="invisible"
android:contentDescription="@string/accessibility_ime_switch_button"
android:scaleType="centerInside"
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index 967db26..50ee64a3 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -42,6 +42,8 @@
android:background="@color/qs_detail_progress_track"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:scaleType="fitXY"
+ android:translationY="8dp"
/>
<com.android.systemui.qs.NonInterceptingScrollView
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index cce9c0f..5b0f0df 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -22,7 +22,7 @@
<TextView android:id="@+id/tile_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textColor="@color/qs_tile_text"
+ android:textColor="?android:attr/textColorSecondary"
android:gravity="center_horizontal"
android:minLines="2"
android:padding="0dp"
diff --git a/packages/SystemUI/res/layout/quick_settings_footer.xml b/packages/SystemUI/res/layout/quick_settings_footer.xml
index 53baf74..8667a5a 100644
--- a/packages/SystemUI/res/layout/quick_settings_footer.xml
+++ b/packages/SystemUI/res/layout/quick_settings_footer.xml
@@ -39,4 +39,16 @@
android:src="@drawable/ic_qs_vpn"
android:visibility="invisible" />
-</RelativeLayout>
\ No newline at end of file
+ <!-- Only shown if both images are visible -->
+ <ImageView
+ android:id="@+id/footer_icon2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_marginEnd="8dp"
+ android:layout_toStartOf="@id/footer_icon"
+ android:contentDescription="@null"
+ android:src="@drawable/ic_qs_network_logging"
+ android:visibility="invisible" />
+
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/recent_apps.xml b/packages/SystemUI/res/layout/recent_apps.xml
index eb8ee43c..870bcf7 100644
--- a/packages/SystemUI/res/layout/recent_apps.xml
+++ b/packages/SystemUI/res/layout/recent_apps.xml
@@ -21,7 +21,6 @@
android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
android:layout_weight="0"
- android:src="@drawable/ic_sysbar_recent"
android:scaleType="center"
android:contentDescription="@string/accessibility_recent"
android:paddingStart="@dimen/navigation_key_padding"
diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml
index 73f26e2..e4ea08e 100644
--- a/packages/SystemUI/res/layout/remote_input.xml
+++ b/packages/SystemUI/res/layout/remote_input.xml
@@ -42,7 +42,7 @@
android:singleLine="true"
android:ellipsize="start"
android:inputType="textShortMessage|textAutoCorrect|textCapSentences"
- android:imeOptions="actionNone|flagNoExtractUi|flagNoFullscreen" />
+ android:imeOptions="actionSend|flagNoExtractUi|flagNoFullscreen" />
<FrameLayout
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 40308dc..a511c58 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Minder dringende kennisgewings hieronder"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tik weer om oop te maak"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Sleep op om te ontsluit"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Hierdie toestel word bestuur"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Hierdie toestel word deur <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> bestuur"</string>
<string name="phone_hint" msgid="4872890986869209950">"Swiep vanaf ikoon vir foon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Swiep vanaf ikoon vir stembystand"</string>
<string name="camera_hint" msgid="7939688436797157483">"Swiep vanaf ikoon vir kamera"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index f807ba9..b40bd90 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"በጣም አስቸካይ ያልሆኑ ማሳወቂያዎች ከታች"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ለመክፈት ዳግም መታ ያድርጉ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ለማስከፈት ወደ ላይ ያንሸራትቱ"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ይህ መሣሪያ የሚተዳደር ነው"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ይህ መሣሪያ በ<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> የሚተዳደር ነው"</string>
<string name="phone_hint" msgid="4872890986869209950">"ለስልክ ከአዶ ላይ ጠረግ ያድርጉ"</string>
<string name="voice_hint" msgid="8939888732119726665">"ለድምጽ ረዳት ከአዶ ጠረግ ያድርጉ"</string>
<string name="camera_hint" msgid="7939688436797157483">"ለካሜራ ከአዶ ላይ ጠረግ ያድርጉ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 33110ce..9ec84f9 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -358,6 +358,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"الإشعارات الأقل إلحاحًا أدناه"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"انقر مرة أخرى للفتح"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"مرر سريعًا لأعلى لإلغاء القفل"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"تتم إدارة هذا الجهاز"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"تتم إدارة هذا الجهاز بواسطة <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"يمكنك التمرير سريعًا من الرمز لتشغيل الهاتف"</string>
<string name="voice_hint" msgid="8939888732119726665">"يمكنك التمرير سريعًا من الرمز لتشغيل المساعد الصوتي"</string>
<string name="camera_hint" msgid="7939688436797157483">"يمكنك التمرير سريعًا من الرمز لتشغيل الكاميرا"</string>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 49f27b2..14537a1 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Daha az təcili bildirişlər aşağıdadır"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Açmaq üçün yenidən tıklayın"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Kiliddən çıxarmaq üçün yuxarı çəkin"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Bu cihaz idarə olunur"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tərəfindən idarə olunur"</string>
<string name="phone_hint" msgid="4872890986869209950">"Telefon üçün ikonadan sürüşdürün"</string>
<string name="voice_hint" msgid="8939888732119726665">"Səs yardımçısı üçün ikonadan sürüşdürün"</string>
<string name="camera_hint" msgid="7939688436797157483">"Kamera üçün ikonadan sürüşdürün"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index dc21bde..c92490f 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Manje hitna obaveštenja su u nastavku"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Dodirnite ponovo da biste otvorili"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Prevucite nagore da biste otključali"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Ovim uređajem se upravlja"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Ovim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Prevucite od ikone za telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Prevucite od ikone za glasovnu pomoć"</string>
<string name="camera_hint" msgid="7939688436797157483">"Prevucite od ikone za kameru"</string>
diff --git a/packages/SystemUI/res/values-be-rBY/strings.xml b/packages/SystemUI/res/values-be-rBY/strings.xml
index ac93da7..6ae9db5 100644
--- a/packages/SystemUI/res/values-be-rBY/strings.xml
+++ b/packages/SystemUI/res/values-be-rBY/strings.xml
@@ -356,6 +356,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Менш тэрміновыя апавяшчэнні ніжэй"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Дакраніцеся яшчэ раз, каб адкрыць"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Правядзіце пальцам уверх, каб разблакіраваць"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Гэта прылада знаходзіцца пад кіраваннем"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Гэта прылада знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Тэлефон: правядзіце пальцам ад значка"</string>
<string name="voice_hint" msgid="8939888732119726665">"Галасавая дапамога: правядзіце пальцам ад значка"</string>
<string name="camera_hint" msgid="7939688436797157483">"Камера: правядзіце пальцам ад значка"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 7814efb..6079354 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Ппоказване на по-малко спешните известия по-долу"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Докоснете отново, за да отворите"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Плъзнете нагоре, за да отключите"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Това устройство се управлява"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Това устройство се управлява от <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Плъзнете с пръст от иконата, за да използвате телефона"</string>
<string name="voice_hint" msgid="8939888732119726665">"Прекарайте пръст от иконата, за да получите гласова помощ"</string>
<string name="camera_hint" msgid="7939688436797157483">"Плъзнете с пръст от иконата, за да включите камерата"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index c80efa4..32d00f6 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"নিচে অপেক্ষাকৃত কম জরুরী বিজ্ঞপ্তিগুলি"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"খোলার জন্য আবার আলতো চাপুন"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"আনলক করতে উপরের দিকে সোয়াইপ করুন"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"এই ডিভাইসটি পরিচালিত"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"এই ডিভাইসটি <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> এর দ্বারা পরিচালিত"</string>
<string name="phone_hint" msgid="4872890986869209950">"ফোনের জন্য আইকন থেকে সোয়াইপ করুন"</string>
<string name="voice_hint" msgid="8939888732119726665">"ভয়েস সহায়তার জন্য আইকন থেকে সোয়াইপ করুন"</string>
<string name="camera_hint" msgid="7939688436797157483">"ক্যামেরার জন্য আইকন থেকে সোয়াইপ করুন"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> হল ভলিউম ডায়লগ"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"আসলটি পুনঃস্থাপন করতে আলতো চাপ দিন৷"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"আপনি আপনার কাজের প্রোফাইল ব্যবহার করছেন"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"কল করুন"</item>
+ <item msgid="5997713001067658559">"সিস্টেম"</item>
+ <item msgid="7858983209929864160">"রিং"</item>
+ <item msgid="1850038478268896762">"মিডিয়া"</item>
+ <item msgid="8265110906352372092">"অ্যালার্ম"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"ব্লুটুথ"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"অ্যাক্সেসযোগ্যতা"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s। সশব্দ করতে আলতো চাপুন।"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s। কম্পন এ সেট করতে আলতো চাপুন। অ্যাক্সেসযোগ্যতার পরিষেবাগুলিকে নিঃশব্দ করা হতে পারে।"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s। নিঃশব্দ করতে আলতো চাপুন। অ্যাক্সেসযোগ্যতার পরিষেবাগুলিকে নিঃশব্দ করা হতে পারে।"</string>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index 2d02a4f..0c35e18 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Prikaži manje važna obavještenja ispod"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Dodirnite ponovo da otvorite"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Prevucite prema gore da otključate"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Ovim uređajem upravlja"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Ovim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Prevucite preko ikone da otvorite telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Prevucite preko ikone za glasovnu pomoć"</string>
<string name="camera_hint" msgid="7939688436797157483">"Prevucite od ikone da otvorite kameru"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index b0e6fe5..fd660ac 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificacions menys urgents a continuació"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Torna a tocar per obrir-la."</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Llisca cap amunt per desbloquejar el teclat"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Aquest és un dispositiu gestionat"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> gestiona aquest dispositiu"</string>
<string name="phone_hint" msgid="4872890986869209950">"Llisca des de la icona per obrir el telèfon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Llisca des de la icona per obrir l\'assistent de veu"</string>
<string name="camera_hint" msgid="7939688436797157483">"Llisca des de la icona per obrir la càmera"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 639f8b5..a045ecd 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -356,6 +356,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Méně urgentní oznámení níže"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Oznámení otevřete opětovným klepnutím"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Zařízení odemknete přejetím prstem nahoru"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Toto zařízení je spravováno"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Toto zařízení je spravováno organizací <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Telefon otevřete přejetím prstem od ikony"</string>
<string name="voice_hint" msgid="8939888732119726665">"Hlasovou asistenci otevřete přejetím prstem od ikony"</string>
<string name="camera_hint" msgid="7939688436797157483">"Fotoaparát otevřete přejetím prstem od ikony"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 8fa27ad..3eeabaa 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mindre presserende underretninger nedenfor"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tryk igen for at åbne"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Stryg opad for at låse op"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Dette er en administreret enhed"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Denne enhed administreres af <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Stryg fra telefonikonet"</string>
<string name="voice_hint" msgid="8939888732119726665">"Stryg fra mikrofonikonet"</string>
<string name="camera_hint" msgid="7939688436797157483">"Stryg fra kameraikonet"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er dialogboksen for lydstyrke"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Tryk for at gendanne det oprindelige."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du bruger din arbejdsprofil"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Opkald"</item>
+ <item msgid="5997713001067658559">"System"</item>
+ <item msgid="7858983209929864160">"Ring"</item>
+ <item msgid="1850038478268896762">"Medier"</item>
+ <item msgid="8265110906352372092">"Alarm"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Hjælpefunktioner"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tryk for at slå lyden til."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tryk for at konfigurere til at vibrere. Tilgængelighedstjenester kan blive deaktiveret."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tryk for at slå lyden fra. Lyden i tilgængelighedstjenester kan blive slået fra."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 564625f..603be91 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Weniger dringende Benachrichtigungen unten"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Erneut tippen, um Benachrichtigung zu öffnen"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Zum Entsperren nach oben wischen"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Dieses Gerät wird verwaltet"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Dieses Gerät wird von <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> verwaltet"</string>
<string name="phone_hint" msgid="4872890986869209950">"Zum Öffnen des Telefons vom Symbol wegwischen"</string>
<string name="voice_hint" msgid="8939888732119726665">"Zum Öffnen des Sprachassistenten vom Symbol wegwischen"</string>
<string name="camera_hint" msgid="7939688436797157483">"Zum Öffnen der Kamera vom Symbol wegwischen"</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> regelt die Lautstärke."</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Tippe, um das Original wiederherzustellen."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du verwendest dein Arbeitsprofil."</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Anruf"</item>
+ <item msgid="5997713001067658559">"System"</item>
+ <item msgid="7858983209929864160">"Klingeln lassen"</item>
+ <item msgid="1850038478268896762">"Medien"</item>
+ <item msgid="8265110906352372092">"Wecker"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Bedienungshilfen"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Zum Aufheben der Stummschaltung tippen."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tippen, um Vibrieren festzulegen. Bedienungshilfen werden unter Umständen stummgeschaltet."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Zum Stummschalten tippen. Bedienungshilfen werden unter Umständen stummgeschaltet."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index a5c790c..2b160c7 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Λιγότερο επείγουσες ειδοποιήσεις παρακάτω"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Πατήστε ξανά για να ανοίξετε"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Σύρετε για να ξεκλειδώσετε"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Αυτή η συσκευή είναι διαχειριζόμενη"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Τη συσκευή διαχειρίζεται ο οργανισμός <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Σύρετε προς τα έξω για τηλέφωνο"</string>
<string name="voice_hint" msgid="8939888732119726665">"Σύρετε προς τα έξω για voice assist"</string>
<string name="camera_hint" msgid="7939688436797157483">"Σύρετε προς τα έξω για κάμερα"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 5dacfb2..d73e130 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Swipe up to unlock"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"This device is managed"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string>
<string name="voice_hint" msgid="8939888732119726665">"Swipe from icon for voice assist"</string>
<string name="camera_hint" msgid="7939688436797157483">"Swipe from icon for camera"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 5dacfb2..d73e130 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Swipe up to unlock"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"This device is managed"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string>
<string name="voice_hint" msgid="8939888732119726665">"Swipe from icon for voice assist"</string>
<string name="camera_hint" msgid="7939688436797157483">"Swipe from icon for camera"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 5dacfb2..d73e130 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Swipe up to unlock"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"This device is managed"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string>
<string name="voice_hint" msgid="8939888732119726665">"Swipe from icon for voice assist"</string>
<string name="camera_hint" msgid="7939688436797157483">"Swipe from icon for camera"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 3ba4360..6f2c7d5 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificaciones menos urgentes abajo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Presionar de nuevo para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Desliza el dedo hacia arriba para desbloquear el teléfono"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Este dispositivo está administrado"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> administra este dispositivo"</string>
<string name="phone_hint" msgid="4872890986869209950">"Desliza el dedo para desbloquear el teléfono."</string>
<string name="voice_hint" msgid="8939888732119726665">"Desliza el dedo desde el ícono para abrir asistente de voz."</string>
<string name="camera_hint" msgid="7939688436797157483">"Desliza el dedo para acceder a la cámara."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 969f812..ba9154d 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificaciones menos urgente abajo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Toca de nuevo para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Desliza el dedo hacia arriba para desbloquear"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Este es un dispositivo administrado"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Este dispositivo está administrado por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Desliza desde el icono para abrir el teléfono"</string>
<string name="voice_hint" msgid="8939888732119726665">"Desliza desde el icono para abrir asistente de voz"</string>
<string name="camera_hint" msgid="7939688436797157483">"Desliza desde el icono para abrir la cámara"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index e1ebfd2..7566137 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Vähem kiireloomulised märguanded on allpool"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Avamiseks puudutage uuesti"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Lukustuse tühistamiseks pühkige üles"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Seda seadet hallatakse"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Seda seadet haldab <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Telefoni kasutamiseks pühkige ikoonilt eemale"</string>
<string name="voice_hint" msgid="8939888732119726665">"Häälabi kasutamiseks pühkige ikoonilt eemale"</string>
<string name="camera_hint" msgid="7939688436797157483">"Kaamera kasutamiseks pühkige ikoonilt eemale"</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> on helitugevuse dialoog"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Puudutage originaali taastamiseks."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Kasutate oma tööprofiili"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Helistamine"</item>
+ <item msgid="5997713001067658559">"Süsteem"</item>
+ <item msgid="7858983209929864160">"Helin"</item>
+ <item msgid="1850038478268896762">"Meedia"</item>
+ <item msgid="8265110906352372092">"Äratus"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Juurdepääsetavus"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Puudutage vaigistuse tühistamiseks."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Puudutage värinarežiimi määramiseks. Juurdepääsetavuse teenused võidakse vaigistada."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Puudutage vaigistamiseks. Juurdepääsetavuse teenused võidakse vaigistada."</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index fa0c711..b78ca62 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Horren premiazkoak ez diren jakinarazpenak daude behean"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Irekitzeko, ukitu berriro"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Desblokeatzeko, pasatu hatza gorantz"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Gailu kudeatu bat da hau"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> erakundeak kudeatzen du gailu hau"</string>
<string name="phone_hint" msgid="4872890986869209950">"Pasatu hatza ikonotik, telefonoa irekitzeko"</string>
<string name="voice_hint" msgid="8939888732119726665">"Pasatu hatza ikonotik, ahots-laguntza irekitzeko"</string>
<string name="camera_hint" msgid="7939688436797157483">"Pasatu hatza ikonotik, kamera irekitzeko"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index bd3c4fc..de596d2 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"اعلانهای کمتر فوری در زیر"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"دوباره ضربه بزنید تا باز شود"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"برای باز کردن قفل سریع به بالا بکشید"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"این دستگاه مدیریت میشود"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"این دستگاه توسط <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> مدیریت میشود"</string>
<string name="phone_hint" msgid="4872890986869209950">"انگشتتان را از نماد تلفن تند بکشید"</string>
<string name="voice_hint" msgid="8939888732119726665">"برای «دستیار صوتی»، تند بکشید"</string>
<string name="camera_hint" msgid="7939688436797157483">"انگشتتان را از نماد دوربین تند بکشید"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> کنترلکننده صدا است"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"برای بازیابی نسخه اصلی ضربه بزنید."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"درحال استفاده از نمایه کاریتان هستید"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"تماس"</item>
+ <item msgid="5997713001067658559">"سیستم"</item>
+ <item msgid="7858983209929864160">"تماس"</item>
+ <item msgid="1850038478268896762">"رسانه"</item>
+ <item msgid="8265110906352372092">"هشدار"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"بلوتوث"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"دسترسپذیری"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. برای باصدا کردن ضربه بزنید."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. برای تنظیم روی لرزش ضربه بزنید. ممکن است سرویسهای دسترسپذیری بیصدا شوند."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. برای بیصدا کردن ضربه بزنید. ممکن است سرویسهای دسترسپذیری بیصدا شوند."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 446c9f8..234a850 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Vähemmän kiireelliset ilmoitukset ovat alla"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Avaa napauttamalla uudelleen"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Avaa lukitus pyyhkäisemällä ylös"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Tämä on hallinnoitu laite."</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Tätä laitetta hallinnoi <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>."</string>
<string name="phone_hint" msgid="4872890986869209950">"Avaa puhelu pyyhkäisemällä."</string>
<string name="voice_hint" msgid="8939888732119726665">"Avaa ääniapuri pyyhkäisemällä kuvakkeesta."</string>
<string name="camera_hint" msgid="7939688436797157483">"Avaa kamera pyyhkäisemällä."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index a03e897..11edeb9 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notifications moins urgentes affichées ci-dessous"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Touchez à nouveau pour ouvrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Glissez vers le haut pour déverrouiller"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Cet appareil est géré"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Cet appareil est géré par <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Balayez à partir de l\'icône pour accéder au téléphone"</string>
<string name="voice_hint" msgid="8939888732119726665">"Balayez à partir de l\'icône pour accéder à l\'assist. vocale"</string>
<string name="camera_hint" msgid="7939688436797157483">"Balayez à partir de l\'icône pour accéder à l\'appareil photo"</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Touchez pour restaurer l\'original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Vous utilisez votre profil professionnel."</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Appeler"</item>
+ <item msgid="5997713001067658559">"Système"</item>
+ <item msgid="7858983209929864160">"Sonnerie"</item>
+ <item msgid="1850038478268896762">"Multimédia"</item>
+ <item msgid="8265110906352372092">"Alarme"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Accessibilité"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Touchez pour réactiver le son."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Touchez pour activer les vibrations. Il est possible de couper le son des services d\'accessibilité."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Touchez pour couper le son. Il est possible de couper le son des services d\'accessibilité."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 1e72795..fa9494e 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notifications moins urgentes ci-dessous"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Appuyer à nouveau pour ouvrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Faire glisser pour déverrouiller"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Cet appareil est géré"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Cet appareil est géré par <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Balayer pour téléphoner"</string>
<string name="voice_hint" msgid="8939888732119726665">"Balayer l\'écran depuis l\'icône pour l\'assistance vocale"</string>
<string name="camera_hint" msgid="7939688436797157483">"Balayer pour prendre une photo"</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Appuyez pour rétablir la version d\'origine."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Vous utilisez votre profil professionnel."</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Appeler"</item>
+ <item msgid="5997713001067658559">"Système"</item>
+ <item msgid="7858983209929864160">"Sonnerie"</item>
+ <item msgid="1850038478268896762">"Multimédia"</item>
+ <item msgid="8265110906352372092">"Alarme"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Accessibilité"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Appuyez pour ne plus ignorer."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Appuyez pour mettre en mode vibreur. Vous pouvez ignorer les services d\'accessibilité."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Appuyez pour ignorer. Vous pouvez ignorer les services d\'accessibilité."</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 515c729..2f9b2e6 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificacións menos urxentes abaixo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Toca de novo para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Pasa o dedo cara arriba para desbloquear"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Este dispositivo está xestionado"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Este dispositivo está xestionado por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Pasa o dedo desde a icona para acceder ao teléfono"</string>
<string name="voice_hint" msgid="8939888732119726665">"Pasa o dedo desde a icona para acceder ao asistente de voz"</string>
<string name="camera_hint" msgid="7939688436797157483">"Pasa o dedo desde a icona para acceder á cámara"</string>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 9778b86..3649e85 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"નીચે ઓછી તાકીદની સૂચનાઓ"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ખોલવા માટે ફરીથી ટૅપ કરો"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"અનલૉક કરવા માટે ઉપર સ્વાઇપ કરો"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"આ ઉપકરણ સંચાલિત છે"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"આ ઉપકરણ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> દ્વારા સંચાલિત થાય છે"</string>
<string name="phone_hint" msgid="4872890986869209950">"ફોન માટે આયકનમાંથી સ્વાઇપ કરો"</string>
<string name="voice_hint" msgid="8939888732119726665">"વૉઇસ સહાય માટે આયકનમાંથી સ્વાઇપ કરો"</string>
<string name="camera_hint" msgid="7939688436797157483">"કૅમેરા માટે આયકનમાંથી સ્વાઇપ કરો"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 1010126..7fd5eb6 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"कम अत्यावश्यक सूचनाएं नीचे दी गई हैं"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"खोलने के लिए पुन: टैप करें"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"अनलॉक करने के लिए ऊपर स्वाइप करें"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"यह डिवाइस प्रबंधित है"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"इस डिवाइस के प्रबंधक <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> हैं"</string>
<string name="phone_hint" msgid="4872890986869209950">"फ़ोन के लिए आइकन से स्वाइप करें"</string>
<string name="voice_hint" msgid="8939888732119726665">"वॉइस सहायक के लिए आइकन से स्वाइप करें"</string>
<string name="camera_hint" msgid="7939688436797157483">"कैमरे के लिए आइकन से स्वाइप करें"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> वॉल्यूम संवाद है"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"मूल को पुन: स्थापित करने के लिए टैप करें."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"आप अपनी कार्य प्रोफ़ाइल का उपयोग कर रहे हैं"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"कॉल करें"</item>
+ <item msgid="5997713001067658559">"सिस्टम"</item>
+ <item msgid="7858983209929864160">"रिंग करें"</item>
+ <item msgid="1850038478268896762">"मीडिया"</item>
+ <item msgid="8265110906352372092">"अलार्म"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"ब्लूटूथ"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"एक्सेस-योग्यता"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. अनम्यूट करने के लिए टैप करें."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. कंपन पर सेट करने के लिए टैप करें. एक्सेस-योग्यता सेवाएं म्यूट हो सकती हैं."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. म्यूट करने के लिए टैप करें. एक्सेस-योग्यता सेवाएं म्यूट हो सकती हैं."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 5d9162e..c105c23 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Manje hitne obavijesti pri dnu"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Dodirnite opet za otvaranje"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Prijeđite prstom prema gore za otključavanje"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Ovim se uređajem upravlja"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Ovim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Prijeđite prstom od ikone za telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Prijeđite prstom od ikone za glasovnu pomoć"</string>
<string name="camera_hint" msgid="7939688436797157483">"Prijeđite prstom od ikone za fotoaparat"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index bb78030..9944b21 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"A kevésbé sürgős értesítések lentebb vannak"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Koppintson rá ismét a megnyitáshoz"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Húzza felfelé az ujját a feloldáshoz"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Ez az eszköz felügyelt"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Az eszközt a(z) <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> felügyeli."</string>
<string name="phone_hint" msgid="4872890986869209950">"A telefonhoz csúsztasson az ikonról"</string>
<string name="voice_hint" msgid="8939888732119726665">"A hangsegéd eléréséhez csúsztassa ujját az ikonról"</string>
<string name="camera_hint" msgid="7939688436797157483">"A fényképezőhöz csúsztasson az ikonról"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index d9ec09e..1c3e9b3 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Պակաս հրատապ ծանուցումները ստորև"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Կրկին հպեք՝ բացելու համար"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Սահեցրեք վերև` ապակողպելու համար"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Այս սարքը կառավարվում է"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Այս սարքը կառավարվում է <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>-ի կողմից"</string>
<string name="phone_hint" msgid="4872890986869209950">"Սահահարվածեք հեռախոսի պատկերակից"</string>
<string name="voice_hint" msgid="8939888732119726665">"Սահահարվածեք ձայնային հուշման պատկերակից"</string>
<string name="camera_hint" msgid="7939688436797157483">"Սահահարվածեք խցիկի պատկերակից"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը ձայնի ուժգնության երկխոսության հավելված է"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Հպեք՝ բնօրինակը վերականգնելու համար:"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Դուք օգտագործում եք ձեր աշխատանքային պրոֆիլը"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Զանգել"</item>
+ <item msgid="5997713001067658559">"Համակարգ"</item>
+ <item msgid="7858983209929864160">"Զանգ"</item>
+ <item msgid="1850038478268896762">"Մեդիա"</item>
+ <item msgid="8265110906352372092">"Զարթուցիչ"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Մատչելիություն"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s: Հպեք՝ ձայնը միացնելու համար:"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s: Հպեք՝ թրթռումը միացնելու համար: Մատչելիության ծառայությունների ձայնը կարող է անջատվել:"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s: Հպեք՝ ձայնն անջատելու համար: Մատչելիության ծառայությունների ձայնը կարող է անջատվել:"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 49d5221..e1e522e 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notifikasi kurang darurat di bawah"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ketuk lagi untuk membuka"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Gesek ke atas untuk membuka kunci"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Perangkat ini dikelola"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Perangkat ini dikelola oleh <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Gesek dari ikon untuk telepon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Gesek dari ikon untuk mengaktifkan bantuan suara"</string>
<string name="camera_hint" msgid="7939688436797157483">"Gesek dari ikon untuk kamera"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index f95d35f..d92092d 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Minna áríðandi tilkynningar fyrir neðan"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ýttu aftur til að opna"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Strjúktu upp til að opna"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Þessu tæki er stýrt"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Þessu tæki er stýrt af <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Strjúktu frá tákninu fyrir síma"</string>
<string name="voice_hint" msgid="8939888732119726665">"Strjúktu frá tákninu fyrir raddaðstoð"</string>
<string name="camera_hint" msgid="7939688436797157483">"Strjúktu frá tákninu fyrir myndavél"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index b30516d..43b5f34 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notifiche meno urgenti in basso"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tocca ancora per aprire"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Scorri verso l\'alto per sbloccare"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Questo dispositivo è gestito"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Questo dispositivo è gestito da <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Scorri per accedere al telefono"</string>
<string name="voice_hint" msgid="8939888732119726665">"Scorri dall\'icona per accedere a Voice Assist"</string>
<string name="camera_hint" msgid="7939688436797157483">"Scorri dall\'icona per accedere alla fotocamera"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index c9f907a..b51020b 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -354,6 +354,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"הודעות בדחיפות נמוכה יותר בהמשך"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"הקש שוב כדי לפתוח"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"החלק מעלה כדי לבטל את הנעילה"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"המכשיר הזה מנוהל"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"המכשיר הזה מנוהל על ידי <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"החלק מהסמל כדי להפעיל את הטלפון"</string>
<string name="voice_hint" msgid="8939888732119726665">"החלק מהסמל כדי להפעיל את המסייע הקולי"</string>
<string name="camera_hint" msgid="7939688436797157483">"החלק מהסמל כדי להפעיל את המצלמה"</string>
@@ -444,7 +446,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> הוא תיבת הדו-שיח של עוצמת הקול"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"הקש כדי לשחזר את המקור."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"אתה משתמש בפרופיל העבודה שלך"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"שיחה"</item>
+ <item msgid="5997713001067658559">"מערכת"</item>
+ <item msgid="7858983209929864160">"השמע צלצול"</item>
+ <item msgid="1850038478268896762">"מדיה"</item>
+ <item msgid="8265110906352372092">"התראה"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"נגישות"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. הקש כדי לבטל את ההשתקה."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. הקש כדי להגדיר רטט. ייתכן ששירותי הנגישות מושתקים."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. הקש כדי להשתיק. ייתכן ששירותי הנגישות מושתקים."</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b891b61..a949cbf 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"緊急度の低い通知を下に表示"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"開くにはもう一度タップしてください"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ロック解除するには上にスワイプしてください"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"この端末は組織が管理しています"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"この端末は <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> が管理しています"</string>
<string name="phone_hint" msgid="4872890986869209950">"右にスワイプして通話"</string>
<string name="voice_hint" msgid="8939888732119726665">"アイコンからスワイプして音声アシストを起動"</string>
<string name="camera_hint" msgid="7939688436797157483">"左にスワイプしてカメラを起動"</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>を音量ダイアログとして使用"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"タップすると元に戻ります。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"仕事用プロファイルを使用しています"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"通話"</item>
+ <item msgid="5997713001067658559">"システム"</item>
+ <item msgid="7858983209929864160">"着信音"</item>
+ <item msgid="1850038478268896762">"メディア"</item>
+ <item msgid="8265110906352372092">"アラーム"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ユーザー補助機能"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。タップしてミュートを解除します。"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。タップしてバイブレーションに設定します。ユーザー補助機能サービスがミュートされる場合があります。"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。タップしてミュートします。ユーザー補助機能サービスがミュートされる場合があります。"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index e00d6b3..41de915 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"ქვემოთ მითითებულია ნაკლებად სასწრაფო შეტყობინებები"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"შეეხეთ ისევ გასახსნელად"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"გაასრიალეთ ზევით განსაბლოკად"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ეს მოწყობილობა მართულია"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ამ მოწყობილობას მართავს <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"ტელეფონისთვის გადაფურცლეთ ხატულადან"</string>
<string name="voice_hint" msgid="8939888732119726665">"ხმოვანი დახმარებისთვის გადაფურცლეთ ხატულადან"</string>
<string name="camera_hint" msgid="7939688436797157483">"კამერისთვის გადაფურცლეთ ხატულადან"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 92b94bd..0f9699a 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Шұғылдығы азырақ хабарландырулар төменде"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ашу үшін қайта түртіңіз"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Құлыпты ашу үшін жоғары сырғытыңыз"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Бұл құрылғыны ұйым басқарады"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Бұл құрылғыны <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> басқарады"</string>
<string name="phone_hint" msgid="4872890986869209950">"Телефонды ашу үшін белгішеден әрі қарай сырғытыңыз"</string>
<string name="voice_hint" msgid="8939888732119726665">"Дауыс көмекшісін ашу үшін белгішеден әрі қарай сырғытыңыз"</string>
<string name="camera_hint" msgid="7939688436797157483">"Камераны ашу үшін белгішеден әрі қарай сырғытыңыз"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> — көлем диалогтық терезесі"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Бастапқы қалпына келтіру үшін түртіңіз."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Сіз жұмыс профиліңізді пайдаланып жатырсыз"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Қоңырау шалу"</item>
+ <item msgid="5997713001067658559">"Жүйе"</item>
+ <item msgid="7858983209929864160">"Шылдырлау"</item>
+ <item msgid="1850038478268896762">"Мультимeдиа"</item>
+ <item msgid="8265110906352372092">"Дабыл"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Арнайы мүмкіндіктер"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Дыбысын қосу үшін түртіңіз."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Діріл режимін орнату үшін түртіңіз. Арнайы мүмкіндік қызметтерінің дыбысы өшуі мүмкін."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Дыбысын өшіру үшін түртіңіз. Арнайы мүмкіндік қызметтерінің дыбысы өшуі мүмкін."</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 9a352fc..4ad9ac8 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"ការជូនដំណឹងមិនសូវបន្ទាន់ខាងក្រោម"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ប៉ះម្ដងទៀត ដើម្បីបើក"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"អូសឡើងលើ ដើម្បីដោះសោ"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ឧបករណ៍នេះស្ថិតក្រោមការគ្រប់គ្រង"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ឧបករណ៍នេះត្រូវបានគ្រប់គ្រងដោយ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"អូសចេញពីរូបតំណាងដើម្បីប្រើទូរស័ព្ទ"</string>
<string name="voice_hint" msgid="8939888732119726665">"អូសចេញពីរូបតំណាងដើម្បីប្រើជំនួយសំឡេង"</string>
<string name="camera_hint" msgid="7939688436797157483">"អូសចេញពីរូបតំណាងដើម្បីប្រើកាមេរ៉ា"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> គឺជាប្រអប់សម្លេង"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ប៉ះដើម្បីស្តារច្បាប់ដើម"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"អ្នកកំពុងប្រើប្រវត្តិរូបការងាររបស់អ្នក"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"ហៅ"</item>
+ <item msgid="5997713001067658559">"ប្រព័ន្ធ"</item>
+ <item msgid="7858983209929864160">"រោទ៍"</item>
+ <item msgid="1850038478268896762">"មេឌៀ"</item>
+ <item msgid="8265110906352372092">"ម៉ោងរោទ៍"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"ប៊្លូធូស"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ភាពងាយស្រួល"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s។ ប៉ះដើម្បីបើកសំឡេង។"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s។ ប៉ះដើម្បីកំណត់ឲ្យញ័រ។ សេវាកម្មលទ្ធភាពប្រើប្រាស់អាចនឹងត្រូវបានបិទសំឡេង។"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s។ ប៉ះដើម្បីបិទសំឡេង។ សេវាកម្មលទ្ធភាពប្រើប្រាស់អាចនឹងត្រូវបានបិទសំឡេង។"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 990c721..3a29a6f 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"ಕೆಳಗೆ ಕಡಿಮೆ ಅವಸರದ ಅಧಿಸೂಚನೆಗಳು"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ತೆರೆಯಲು ಮತ್ತೆ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ಅನ್ಲಾಕ್ ಮಾಡಲು ಸ್ವೈಪ್ ಮಾಡಿ"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ಈ ಸಾಧನವನ್ನು ನಿರ್ವಹಿಸಲಾಗಿದೆ"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ಈ ಸಾಧನವನ್ನು <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ರಿಂದ ನಿರ್ವಹಿಸಲಾಗಿದೆ"</string>
<string name="phone_hint" msgid="4872890986869209950">"ಫೋನ್ಗಾಗಿ ಐಕಾನ್ನಿಂದ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="voice_hint" msgid="8939888732119726665">"ಧ್ವನಿ ಸಹಾಯಕ್ಕಾಗಿ ಐಕಾನ್ನಿಂದ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="camera_hint" msgid="7939688436797157483">"ಕ್ಯಾಮರಾಗಾಗಿ ಐಕಾನ್ನಿಂದ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ವಾಲ್ಯೂಮ್ ಸಂವಾದವಾಗಿದೆ"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ಮೂಲಕ್ಕೆ ಮರುಸ್ಥಾಪಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಅನ್ನು ನೀವು ಬಳಸುತ್ತಿರುವಿರಿ"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"ಕರೆಮಾಡಿ"</item>
+ <item msgid="5997713001067658559">"ಸಿಸ್ಟಂ"</item>
+ <item msgid="7858983209929864160">"ಉಂಗುರ"</item>
+ <item msgid="1850038478268896762">"ಮಾಧ್ಯಮ"</item>
+ <item msgid="8265110906352372092">"ಅಲಾರಮ್"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"ಬ್ಲೂಟೂತ್"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ಪ್ರವೇಶಿಸುವಿಕೆ"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. ಅನ್ಮ್ಯೂಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. ಕಂಪನಕ್ಕೆ ಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಪ್ರವೇಶಿಸುವಿಕೆ ಸೇವೆಗಳನ್ನು ಮ್ಯೂಟ್ ಮಾಡಬಹುದು."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. ಮ್ಯೂಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಪ್ರವೇಶಿಸುವಿಕೆ ಸೇವೆಗಳನ್ನು ಮ್ಯೂಟ್ ಮಾಡಬಹುದು."</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index b06f15e..cff469c 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"아래에 덜 급한 알림 표시"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"다시 탭하여 열기"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"위로 스와이프하여 잠금 해제"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"관리되는 기기입니다."</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>에서 관리하는 기기입니다."</string>
<string name="phone_hint" msgid="4872890986869209950">"전화 기능을 사용하려면 아이콘에서 스와이프하세요."</string>
<string name="voice_hint" msgid="8939888732119726665">"음성 지원을 사용하려면 아이콘에서 스와이프하세요."</string>
<string name="camera_hint" msgid="7939688436797157483">"카메라를 사용하려면 아이콘에서 스와이프하세요."</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>은(는) 볼륨 대화입니다."</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"원본을 복원하려면 탭하세요."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"직장 프로필을 사용하고 있습니다."</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"통화"</item>
+ <item msgid="5997713001067658559">"시스템"</item>
+ <item msgid="7858983209929864160">"벨 울리기"</item>
+ <item msgid="1850038478268896762">"미디어"</item>
+ <item msgid="8265110906352372092">"알람"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"블루투스"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"접근성"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. 탭하여 음소거를 해제하세요."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. 탭하여 진동으로 설정하세요. 접근성 서비스가 음소거될 수 있습니다."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. 탭하여 음소거로 설정하세요. 접근성 서비스가 음소거될 수 있습니다."</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index d5af0b3..a0675c0 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Анчейин шашылыш эмес эскертмелер төмөндө"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ачуу үчүн кайра таптап коюңуз"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Кулпуну ачуу үчүн серпип коюңуз"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Башкарылган түзмөк"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Бул түзмөк <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> тарабынан башкарылат"</string>
<string name="phone_hint" msgid="4872890986869209950">"Сүрөтчөнү серпип телефонго өтүңүз"</string>
<string name="voice_hint" msgid="8939888732119726665">"Сүрөтчөнү серпип үн жардамчысына өтүңүз"</string>
<string name="camera_hint" msgid="7939688436797157483">"Сүрөтчөнү серпип камерага өтүңүз"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 711a68d..2056194 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"ການແຈ້ງເຕືອນທີ່ສຳຄັນໜ້ອຍກວ່າຢູ່ດ້ານລຸ່ມ"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ແຕະອີກຄັ້ງເພື່ອເປີດ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ເລື່ອນຂຶ້ນເພື່ອປົດລັອກ"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ອຸປະກອນນີ້ຖືກຈັດການຢູ່"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ອຸປະກອນນີ້ຖືກຈັດການໂດຍ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"ປັດຈາກໄອຄອນສຳລັບໂທລະສັບ"</string>
<string name="voice_hint" msgid="8939888732119726665">"ປັດຈາກໄອຄອນສຳລັບການຊ່ວຍທາງສຽງ"</string>
<string name="camera_hint" msgid="7939688436797157483">"ປັດຈາກໄອຄອນສຳລັບກ້ອງຖ່າຍຮູບ"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ແມ່ນໜ້າຕ່າງລະດັບສຽງ"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ແຕະເພື່ອກູ້ຕົ້ນສະບັບຄືນມາ."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ທ່ານກຳລັງໃຊ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຂອງທ່ານ"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"ໂທ"</item>
+ <item msgid="5997713001067658559">"ລະບົບ"</item>
+ <item msgid="7858983209929864160">"ເຕືອນດ້ວຍສຽງ"</item>
+ <item msgid="1850038478268896762">"ມີເດຍ"</item>
+ <item msgid="8265110906352372092">"ໂມງປຸກ"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ການຊ່ວຍເຂົ້າເຖິງ"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. ແຕະເພື່ອເຊົາປິດສຽງ."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. ແຕະເພື່ອຕັ້ງເປັນສັ່ນ. ບໍລິການຊ່ວຍເຂົ້າເຖິງອາດຖືກປິດສຽງໄວ້."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. ແຕະເພື່ອປິດສຽງ. ບໍລິການຊ່ວຍເຂົ້າເຖິງອາດຖືກປິດສຽງໄວ້."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index aec484d..6dfdbe6 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -354,6 +354,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mažiau skubūs pranešimai toliau"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Palieskite dar kartą, kad atidarytumėte"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Perbraukite aukštyn, kad atrakintumėte"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Šis įrenginys tvarkomas"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Šį įrenginį tvarko <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Perbraukite iš telefono piktogramos"</string>
<string name="voice_hint" msgid="8939888732119726665">"Perbraukite iš „Voice Assist“ piktogramos"</string>
<string name="camera_hint" msgid="7939688436797157483">"Perbraukite iš fotoaparato piktogramos"</string>
@@ -444,7 +446,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ yra garsumo valdymo dialogo langas"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Palieskite, kad atkurtumėte originalą."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Naudojate darbo profilį"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Skambinti"</item>
+ <item msgid="5997713001067658559">"Sistema"</item>
+ <item msgid="7858983209929864160">"Skambinti"</item>
+ <item msgid="1850038478268896762">"Medija"</item>
+ <item msgid="8265110906352372092">"Signalas"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Pritaikymas neįgaliesiems"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Palieskite, kad įjungtumėte garsą."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Palieskite, kad nustatytumėte vibravimą. Gali būti nutildytos pritaikymo neįgaliesiems paslaugos."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Palieskite, kad nutildytumėte. Gali būti nutildytos pritaikymo neįgaliesiems paslaugos."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 900a955d..3862a8e 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mazāk steidzami paziņojumi tiek rādīti tālāk"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Pieskarieties vēlreiz, lai atvērtu"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Velciet uz augšu, lai atbloķētu"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Šī ierīce tiek pārvaldīta"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Šo ierīci pārvalda <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Lai lietotu tālruni, velciet no ikonas"</string>
<string name="voice_hint" msgid="8939888732119726665">"Lai lietotu balss palīgu, velciet no ikonas"</string>
<string name="camera_hint" msgid="7939688436797157483">"Lai lietotu kameru, velciet no ikonas"</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ir skaļuma dialoglodziņš"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Pieskarieties, lai atjaunotu sākotnējo saturu."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Jūs izmantojat darba profilu."</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Zvans"</item>
+ <item msgid="5997713001067658559">"Sistēma"</item>
+ <item msgid="7858983209929864160">"Zvanīt"</item>
+ <item msgid="1850038478268896762">"Multivide"</item>
+ <item msgid="8265110906352372092">"Signāls"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Pieejamība"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Pieskarieties, lai ieslēgtu skaņu."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Pieskarieties, lai iestatītu uz vibrozvanu. Var tikt izslēgti pieejamības pakalpojumu signāli."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Pieskarieties, lai izslēgtu skaņu. Var tikt izslēgti pieejamības pakalpojumu signāli."</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 716f76c..5d28e2b 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Долу се помалку итни известувања"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Допрете повторно за да се отвори"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Повлечете за да се отклучи"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Со уредов се управува"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Уредов го управува <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Повлечете од иконата за телефонот"</string>
<string name="voice_hint" msgid="8939888732119726665">"Повлечете од иконата за гласовна помош"</string>
<string name="camera_hint" msgid="7939688436797157483">"Повлечете од иконата за камерата"</string>
@@ -526,7 +528,7 @@
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Штедач на батерија"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Ја намалува изведбата и податоците во заднина"</string>
<string name="keyboard_key_button_template" msgid="6230056639734377300">"Копче <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="keyboard_key_home" msgid="2243500072071305073">"Почетна страница"</string>
+ <string name="keyboard_key_home" msgid="2243500072071305073">"Home-копче"</string>
<string name="keyboard_key_back" msgid="2337450286042721351">"Назад"</string>
<string name="keyboard_key_dpad_up" msgid="5584144111755734686">"Стрелка нагоре"</string>
<string name="keyboard_key_dpad_down" msgid="7331518671788337815">"Стрелка надолу"</string>
@@ -546,7 +548,7 @@
<string name="keyboard_key_page_up" msgid="5654098530106845603">"Страница нагоре"</string>
<string name="keyboard_key_page_down" msgid="8720502083731906136">"Страница надолу"</string>
<string name="keyboard_key_forward_del" msgid="1391451334716490176">"Избриши"</string>
- <string name="keyboard_key_move_home" msgid="2765693292069487486">"Почетна страница"</string>
+ <string name="keyboard_key_move_home" msgid="2765693292069487486">"Home-копче"</string>
<string name="keyboard_key_move_end" msgid="5901174332047975247">"Крај"</string>
<string name="keyboard_key_insert" msgid="8530501581636082614">"Вметни"</string>
<string name="keyboard_key_num_lock" msgid="5052537581246772117">"Num Lock"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 6c14826..f24b1e6 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"ആവശ്യം കുറഞ്ഞ അറിയിപ്പുകൾ ചുവടെ നൽകിയിരിക്കുന്നു"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"തുറക്കുന്നതിന് വീണ്ടും ടാപ്പുചെയ്യുക"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"അൺലോക്കുചെയ്യുന്നതിന് മുകളിലേക്ക് സ്വൈപ്പുചെയ്യുക"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"മാനേജുചെയ്യപ്പെടുന്ന ഉപകരണമാണിത്"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g> മാനേജുചെയ്യുന്ന ഉപകരണമാണിത്"</string>
<string name="phone_hint" msgid="4872890986869209950">"ഫോൺ ഐക്കണിൽ നിന്ന് സ്വൈപ്പുചെയ്യുക"</string>
<string name="voice_hint" msgid="8939888732119726665">"വോയ്സ് അസിസ്റ്റിനായുള്ള ഐക്കണിൽ നിന്ന് സ്വൈപ്പുചെയ്യുക"</string>
<string name="camera_hint" msgid="7939688436797157483">"ക്യാമറ ഐക്കണിൽ നിന്ന് സ്വൈപ്പുചെയ്യുക"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>, വോളിയം ഡയലോഗാണ്"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ഒറിജിനൽ പുനഃസ്ഥാപിക്കാൻ ടാപ്പുചെയ്യുക."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"നിങ്ങൾ ഉപയോഗിക്കുന്നത് ഔദ്യോഗിക പ്രൊഫൈലാണ്"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"വിളിക്കുക"</item>
+ <item msgid="5997713001067658559">"സിസ്റ്റം"</item>
+ <item msgid="7858983209929864160">"റിംഗുചെയ്യുക"</item>
+ <item msgid="1850038478268896762">"മീഡിയ"</item>
+ <item msgid="8265110906352372092">"അലാറം"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"ബ്ലൂടൂത്ത്"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"പ്രവേശനക്ഷമത"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. അൺമ്യൂട്ടുചെയ്യുന്നതിന് ടാപ്പുചെയ്യുക."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. വൈബ്രേറ്റിലേക്ക് സജ്ജമാക്കുന്നതിന് ടാപ്പുചെയ്യുക. പ്രവേശനക്ഷമതാ സേവനങ്ങൾ മ്യൂട്ടുചെയ്യപ്പെട്ടേക്കാം."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. മ്യൂട്ടുചെയ്യുന്നതിന് ടാപ്പുചെയ്യുക. പ്രവേശനക്ഷമതാ സേവനങ്ങൾ മ്യൂട്ടുചെയ്യപ്പെട്ടേക്കാം."</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 8171310..e285a42 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -348,6 +348,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Яаралтай биш мэдэгдлүүдийг доор"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Нээхийн тулд дахин товшино уу"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Түгжээг тайлах бол шудрана уу"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Энэ төхөөрөмжийг удирдаж байна"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Энэ төхөөрөмжийг <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> удирддаг"</string>
<string name="phone_hint" msgid="4872890986869209950">"Утсыг гаргахын тулд дүрс тэмдгээс шудрах"</string>
<string name="voice_hint" msgid="8939888732119726665">"Дуут туслахыг нээхийн тулд дүрс тэмдгээс шудрах"</string>
<string name="camera_hint" msgid="7939688436797157483">"Камер нээхийн тулд дүрс тэмдгийг шудрах"</string>
@@ -438,7 +440,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь дууны диалог юм."</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Эх хувилбарыг сэргээхийн тулд дарна уу."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Та өөрийн ажлын профайлыг ашиглаж байна"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Дуудлага"</item>
+ <item msgid="5997713001067658559">"Систем"</item>
+ <item msgid="7858983209929864160">"Хонх дуугаргах"</item>
+ <item msgid="1850038478268896762">"Медиа"</item>
+ <item msgid="8265110906352372092">"Сэрүүлэг"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Хүртээмж"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Дууг нь нээхийн тулд товшино уу."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Чичиргээнд тохируулахын тулд товшино уу. Хүртээмжийн үйлчилгээний дууг хаасан."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Дууг нь хаахын тулд товшино уу. Хүртээмжийн үйлчилгээний дууг хаасан."</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index ade3921..f94e859 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"खाली कमी तातडीच्या सूचना"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"उघडण्यासाठी पुन्हा टॅप करा"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"अनलॉक करण्यासाठी स्वाइप करा"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"हे डिव्हाइस व्यवस्थापित केले आहे"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ने व्यवस्थापित केले आहे"</string>
<string name="phone_hint" msgid="4872890986869209950">"फोनसाठी चिन्हावरून स्वाइप करा"</string>
<string name="voice_hint" msgid="8939888732119726665">"व्हॉइस सहाय्यासाठी चिन्हावरून स्वाइप करा"</string>
<string name="camera_hint" msgid="7939688436797157483">"कॅमेर्यासाठी चिन्हावरून स्वाइप करा"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index ebe2cf8..0c5924d 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Pemberitahuan kurang penting di bawah"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ketik lagi untuk membuka"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Leret ke atas untuk membuka kunci"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Peranti ini terurus"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Peranti ini diurus oleh <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Leret dari ikon untuk telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Leret dari ikon untuk bantuan suara"</string>
<string name="camera_hint" msgid="7939688436797157483">"Leret dari ikon untuk kamera"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ialah dialog kelantangan"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Ketik untuk memulihkan yang asal."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Anda sedang menggunakan profil kerja"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Panggil"</item>
+ <item msgid="5997713001067658559">"Sistem"</item>
+ <item msgid="7858983209929864160">"Dering"</item>
+ <item msgid="1850038478268896762">"Media"</item>
+ <item msgid="8265110906352372092">"Penggera"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Kebolehaksesan"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Ketik untuk menyahredam."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Ketik untuk menetapkan pada getar. Perkhidmatan kebolehaksesan mungkin diredamkan."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Ketik untuk meredam. Perkhidmatan kebolehaksesan mungkin diredamkan."</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index a1e6d37..af68511 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"အရေးပါမှု နည်းသည့် အကြောင်းကြားချက်များ အောက်မှာ"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ဖွင့်ရန် ထပ်ပြီး ပုတ်ပါ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"သော့ဖွင့်ရန် အပေါ်သို့ ပွတ်ဆွဲပါ"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ဤစက်ပစ္စည်းကို စီမံခန့်ခွဲထားပါသည်"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ဤစက်ပစ္စည်းကို <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> က စီမံခန့်ခွဲထားပါသည်"</string>
<string name="phone_hint" msgid="4872890986869209950">"ဖုန်းအတွက် သင်္ကေတပုံအား ပွတ်ဆွဲပါ"</string>
<string name="voice_hint" msgid="8939888732119726665">"အသံအကူအညီအတွက် သင်္ကေတပုံအား ပွတ်ဆွဲပါ"</string>
<string name="camera_hint" msgid="7939688436797157483">"ကင်မရာအတွက် သင်္ကေတပုံအား ပွတ်ဆွဲပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 4508276..1b9c35a 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mindre presserende varsler nedenfor"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Trykk på nytt for å åpne"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Sveip oppover for å låse opp"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Denne enheten blir administrert"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Denne enheten administreres av <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Sveip ikonet for å åpne telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Sveip fra ikonet for å åpne talehjelp"</string>
<string name="camera_hint" msgid="7939688436797157483">"Sveip ikonet for å åpne kamera"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 7afcac1..1d33a7d 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -331,7 +331,7 @@
<string name="recents_drag_hint_message" msgid="2649739267073203985">"विभाजित स्क्रिनको प्रयोग गर्नका लागि यहाँ तान्नुहोस्"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"तेर्सो रूपमा विभाजन गर्नुहोस्"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ठाडो रूपमा विभाजन गर्नुहोस्"</string>
- <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"अनुकूलन विभाजन गर्नुहोस्"</string>
+ <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"आफू अनुकूल विभाजन गर्नुहोस्"</string>
<string-array name="recents_blacklist_array">
</string-array>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज भयो"</string>
@@ -343,13 +343,15 @@
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>को लागि माथि धिसार्नुहोस्"</string>
<string name="description_direction_left" msgid="7207478719805562165">"स्लाइड <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>को लागि बायाँ।"</string>
<string name="zen_priority_introduction" msgid="3070506961866919502">"अलार्म, रिमाइन्डर, घटना, र तपाईँले निर्दिष्ट गर्नुहुने कलरहरू देखि बाहेक, आवाज र कम्पनले तपाईँ लाई वाधा गर्ने छैन।"</string>
- <string name="zen_priority_customize_button" msgid="7948043278226955063">"अनुकूलन गर्नुहोस्"</string>
+ <string name="zen_priority_customize_button" msgid="7948043278226955063">"आफू अनुकूल बनाउनुहोस्"</string>
<string name="zen_silence_introduction_voice" msgid="2284540992298200729">"यसले अलार्म, संगीत, भिडियो, र खेलहरू लगायतका सबै ध्वनि र कम्पन रोक्छ। तपाईँ अझै पनि फोन कल गर्न सक्षम हुनुहुन्छ।"</string>
<string name="zen_silence_introduction" msgid="3137882381093271568">"यसले अलार्म, संगीत, भिडियोहरू र खेलहरूसहित सबै ध्वनिहरू र कम्पनहरूलाई रोक्छ।"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"तल कम जरुरी सूचनाहरू"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"खोल्न पुनः ट्याप गर्नुहोस्"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"अनलक गर्न स्वाप गर्नुहोस्"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"यो यन्त्र व्यवस्थापन गरिएको छ"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"यो यन्त्र <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> द्वारा व्यवस्थापन गरिएको छ"</string>
<string name="phone_hint" msgid="4872890986869209950">"फोनको लागि आइकनबाट स्वाइप गर्नुहोस्"</string>
<string name="voice_hint" msgid="8939888732119726665">"आवाज सहायताका लागि आइकनबाट स्वाइप गर्नुहोस्"</string>
<string name="camera_hint" msgid="7939688436797157483">"क्यामेराको लागि आइकनबाट स्वाइप गर्नुहोस्"</string>
@@ -481,7 +483,7 @@
<string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"Hotspot"</string>
<string name="accessibility_managed_profile" msgid="6613641363112584120">"कार्य प्रोफाइल"</string>
<string name="tuner_warning_title" msgid="7094689930793031682">"केहीका लागि रमाइलो हुन्छ तर सबैका लागि होइन"</string>
- <string name="tuner_warning" msgid="8730648121973575701">"प्रणाली UI ट्युनरले तपाईँलाई Android प्रयोगकर्ता इन्टरफेस अनुकूलन गर्न र ट्विक गर्न थप तरिकाहरू प्रदान गर्छ। यी प्रयोगात्मक सुविधाहरू भावी विमोचनमा परिवर्तन हुन, बिग्रिन वा हराउन सक्ने छन्। सावधानीपूर्वक अगाडि बढ्नुहोस्।"</string>
+ <string name="tuner_warning" msgid="8730648121973575701">"प्रणाली UI ट्युनरले तपाईँलाई Android प्रयोगकर्ता इन्टरफेस आफू अनुकूल गर्न र ट्विक गर्न थप तरिकाहरू प्रदान गर्छ। यी प्रयोगात्मक सुविधाहरू भावी विमोचनमा परिवर्तन हुन, बिग्रिन वा हराउन सक्ने छन्। सावधानीपूर्वक अगाडि बढ्नुहोस्।"</string>
<string name="tuner_persistent_warning" msgid="8597333795565621795">"यी प्रयोगात्मक सुविधाहरू भावी विमोचनहरूमा परिवर्तन हुन, बिग्रन वा हराउन सक्छन्। सावधानीपूर्वक अगाडि बढ्नुहोस्।"</string>
<string name="got_it" msgid="2239653834387972602">"बुझेँ"</string>
<string name="tuner_toast" msgid="603429811084428439">"बधाईँ छ! सेटिङहरूमा प्रणाली UI ट्युनर थप गरिएको छ"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index a13030d..1d7ac5ec 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Minder urgente meldingen onderaan"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tik nogmaals om te openen"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Veeg omhoog om te ontgrendelen"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Dit apparaat wordt beheerd"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Dit apparaat wordt beheerd door <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Vegen voor telefoon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Vegen vanaf pictogram voor spraakassistent"</string>
<string name="camera_hint" msgid="7939688436797157483">"Vegen voor camera"</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 6b5abe4..bdb1e43 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -70,7 +70,7 @@
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
<string name="screenshot_saving_text" msgid="2419718443411738818">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਸੁਰੱਖਿਅਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ।"</string>
- <string name="screenshot_saved_title" msgid="6461865960961414961">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਕੈਪਚਰ ਕੀਤਾ।"</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਕੈਪਚਰ ਕੀਤਾ।"</string>
<string name="screenshot_saved_text" msgid="2685605830386712477">"ਆਪਣਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਵੇਖਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਕੈਪਚਰ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕਰਨ ਦੌਰਾਨ ਸਮੱਸਿਆ ਆਈ।"</string>
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"ਹੇਠਾਂ ਘੱਟ ਲਾਜ਼ਮੀ ਸੂਚਨਾਵਾਂ"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ਖੋਲ੍ਹਣ ਲਈ ਦੁਬਾਰਾ ਟੈਪ ਕਰੋ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਉੱਪਰ ਸਵਾਈਪ ਕਰੋ।"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ਇਹ ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਿਤ ਕੀਤੀ ਗਈ ਹੈ"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ਇਹ ਡੀਵਾਈਸ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤੀ ਗਈ ਹੈ"</string>
<string name="phone_hint" msgid="4872890986869209950">"ਫ਼ੋਨ ਲਈ ਆਈਕਨ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="voice_hint" msgid="8939888732119726665">"ਵੌਇਸ ਅਸਿਸਟ ਲਈ ਆਈਕਨ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="camera_hint" msgid="7939688436797157483">"ਕੈਮਰੇ ਲਈ ਆਈਕਨ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
@@ -395,7 +397,7 @@
<string name="battery_saver_notification_action_text" msgid="109158658238110382">"ਬੈਟਰੀ ਸੇਵਰ ਬੰਦ ਕਰੋ"</string>
<string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਉਹ ਸਭ ਕੁਝ ਕੈਪਚਰ ਕਰਨਾ ਸ਼ੁਰੂ ਕਰ ਦੇਵੇਗਾ, ਜੋ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ ਤੇ ਡਿਸਪਲੇ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"ਦੁਬਾਰਾ ਨਾ ਦਿਖਾਓ"</string>
- <string name="clear_all_notifications_text" msgid="814192889771462828">"ਸਾਰੇ ਹਟਾਓ"</string>
+ <string name="clear_all_notifications_text" msgid="814192889771462828">"ਸਭ ਸਾਫ਼ ਕਰੋ"</string>
<string name="media_projection_action_text" msgid="8470872969457985954">"ਹੁਣ ਚਾਲੂ ਕਰੋ"</string>
<string name="empty_shade_text" msgid="708135716272867002">"ਕੋਈ ਸੂਚਨਾਵਾਂ ਨਹੀਂ"</string>
<string name="device_owned_footer" msgid="3802752663326030053">"ਡੀਵਾਈਸ ਦਾ ਨਿਰੀਖਣ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਵੋਲਯੂਮ ਡਾਇਲੌਗ ਹੈ"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ਅਸਲ ਨੂੰ ਮੁੜ-ਬਹਾਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ਤੁਸੀਂ ਆਪਣੀ ਕੰਮ ਪ੍ਰੋਫਾਈਲ ਵਰਤ ਰਹੇ ਹੋ"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"ਕਾਲ ਕਰੋ"</item>
+ <item msgid="5997713001067658559">"ਸਿਸਟਮ"</item>
+ <item msgid="7858983209929864160">"ਰਿੰਗ ਕਰੋ"</item>
+ <item msgid="1850038478268896762">"ਮੀਡੀਆ"</item>
+ <item msgid="8265110906352372092">"ਅਲਾਰਮ"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"ਬਲੂਟੁੱਥ"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ਪਹੁੰਚਯੋਗਤਾ"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s। ਅਣਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s। ਥਰਥਰਾਹਟ ਸੈੱਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ। ਪਹੁੰਚਯੋਗਤਾ ਸੇਵਾਵਾਂ ਮਿਊਟ ਹੋ ਸਕਦੀਆਂ ਹਨ।"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s। ਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ। ਪਹੁੰਚਯੋਗਤਾ ਸੇਵਾਵਾਂ ਮਿਊਟ ਹੋ ਸਕਦੀਆਂ ਹਨ।"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 429fdfb..0bd9179 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -354,6 +354,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Poniżej widać mniej pilne powiadomienia"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Kliknij ponownie, by otworzyć"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Przesuń w górę, by odblokować"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"To urządzenie jest zarządzane"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Tym urządzeniem zarządza <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Aby włączyć telefon, przesuń palcem od ikony"</string>
<string name="voice_hint" msgid="8939888732119726665">"Aby uzyskać pomoc głosową, przesuń palcem od ikony"</string>
<string name="camera_hint" msgid="7939688436797157483">"Przesuń palcem od ikony, by włączyć aparat"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 828d4d9..ab107e8 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificações menos urgentes abaixo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Deslize para cima para desbloquear"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Este dispositivo é gerenciado"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Este dispositivo é gerenciado por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Deslize a partir do ícone do telefone"</string>
<string name="voice_hint" msgid="8939888732119726665">"Deslize a partir do ícone de assistência de voz"</string>
<string name="camera_hint" msgid="7939688436797157483">"Deslize a partir do ícone da câmera"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 60a1cda..ac34f24 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificações menos urgentes abaixo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Deslizar rapidamente com o dedo para cima para desbloquear"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Este dispositivo é gerido"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Este dispositivo é gerido por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Deslize rapid. a partir do ícone para aceder ao telemóvel"</string>
<string name="voice_hint" msgid="8939888732119726665">"Deslize rapid. a partir do ícone para aceder ao assist. voz"</string>
<string name="camera_hint" msgid="7939688436797157483">"Deslize rapidamente a partir do ícone para aceder à câmara"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 828d4d9..ab107e8 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificações menos urgentes abaixo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Deslize para cima para desbloquear"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Este dispositivo é gerenciado"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Este dispositivo é gerenciado por <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Deslize a partir do ícone do telefone"</string>
<string name="voice_hint" msgid="8939888732119726665">"Deslize a partir do ícone de assistência de voz"</string>
<string name="camera_hint" msgid="7939688436797157483">"Deslize a partir do ícone da câmera"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index b418d4a..d18629f 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -354,6 +354,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificările mai puțin urgente mai jos"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Atingeți din nou pentru a deschide"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Glisați în sus pentru a debloca"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Acest dispozitiv este gestionat"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Acest dispozitiv este gestionat de <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Glisați dinspre telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Glisați dinspre pictogramă pentru asistentul vocal"</string>
<string name="camera_hint" msgid="7939688436797157483">"Glisați pentru a fotografia"</string>
@@ -444,7 +446,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> afișează caseta de dialog pentru volum"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Atingeți pentru a restabili versiunea originală."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Acum folosiți profilul de serviciu"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Apel"</item>
+ <item msgid="5997713001067658559">"Sistem"</item>
+ <item msgid="7858983209929864160">"Sonerie"</item>
+ <item msgid="1850038478268896762">"Conținut media"</item>
+ <item msgid="8265110906352372092">"Alarmă"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Accesibilitate"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Atingeți pentru a activa sunetul."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Atingeți pentru a seta vibrarea. Sunetul se poate dezactiva pentru serviciile de accesibilitate."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Atingeți pentru a dezactiva sunetul. Sunetul se poate dezactiva pentru serviciile de accesibilitate."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 05f0d38..bfd75e9 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -356,6 +356,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Показать менее важные оповещения"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Нажмите ещё раз, чтобы открыть"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Проведите вверх, чтобы разблокировать"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Это управляемое устройство"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Этим устройством управляет компания \"<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>\""</string>
<string name="phone_hint" msgid="4872890986869209950">"Телефон: проведите от значка"</string>
<string name="voice_hint" msgid="8939888732119726665">"Аудиоподсказки: проведите от значка"</string>
<string name="camera_hint" msgid="7939688436797157483">"Камера: проведите от значка"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 2db54d0..d31d17b 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -342,14 +342,16 @@
<string name="description_target_search" msgid="3091587249776033139">"සෙවීම"</string>
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> සඳහා උඩට සර්පණය කරන්න."</string>
<string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> සඳහා වමට සර්පණය කරන්න."</string>
- <string name="zen_priority_introduction" msgid="3070506961866919502">"එලාම, සිහි කැඳවීම්, සිදුවීම් සහ ඔබ සඳහන් කරන අමතන්නන් වෙතින් හැර, වෙනත් ශබ්ද සහ කම්පනවලින් ඔබට බාධා නොවනු ඇත."</string>
+ <string name="zen_priority_introduction" msgid="3070506961866919502">"එලාම, සිහිකැඳවීම්, සිදුවීම් සහ ඔබ සඳහන් කරන අමතන්නන් වෙතින් හැර, ශබ්ද සහ කම්පනවලින් ඔබට බාධා නොවනු ඇත."</string>
<string name="zen_priority_customize_button" msgid="7948043278226955063">"අභිරුචිකරණය"</string>
- <string name="zen_silence_introduction_voice" msgid="2284540992298200729">"මෙය සීනු, සංගීතය, වීඩියෝ, සහ ක්රීඩා ඇතුළු, සියලු ශබ්ද සහ කම්පන අවහිර කරයි. ඔබට තවමත් දුරකථන ඇමතුම් සිදු කිරීමේ හැකියාව ඇත."</string>
- <string name="zen_silence_introduction" msgid="3137882381093271568">"මෙය සීනු, සංගීතය, වීඩියෝ, සහ ක්රීඩා ඇතුළු, සියලු ශබ්ද සහ කම්පන අවහිර කරයි."</string>
+ <string name="zen_silence_introduction_voice" msgid="2284540992298200729">"මෙය එලාම්, සංගීතය, වීඩියෝ, සහ ක්රීඩා ඇතුළු, සියලු ශබ්ද සහ කම්පන අවහිර කරයි. ඔබට තවමත් දුරකථන ඇමතුම් ගැනීමට හැකියාව ඇත."</string>
+ <string name="zen_silence_introduction" msgid="3137882381093271568">"මෙය එලාම්, සංගීතය, වීඩියෝ, සහ ක්රීඩා ඇතුළු, සියලු ශබ්ද සහ කම්පන අවහිර කරයි."</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"හදිසිය අඩු දැනුම් දීම් පහත"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"විවෘත කිරීමට නැවත තට්ටු කරන්න"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"අගුළු ඇරීමට ස්වයිප් කරන්න."</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"මෙම උපාංගය කළමනාකරණය නොකෙරේ"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"මෙම උපාංගය <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> මගින් කළමනාකරණය කෙරේ"</string>
<string name="phone_hint" msgid="4872890986869209950">"දුරකථනය සඳහා නිරූපකය වෙතින් ස්වයිප් කරන්න"</string>
<string name="voice_hint" msgid="8939888732119726665">"හඬ සහාය සඳහා නිරූපකය වෙතින් ස්වයිප් කරන්න"</string>
<string name="camera_hint" msgid="7939688436797157483">"කැමරාව සඳහා නිරූපකය වෙතින් ස්වයිප් කරන්න"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ධාරිතා සංවාදයයි"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"මුල් තත්ත්වය නැවත ප්රතිසාධනය කිරීමට තට්ටු කරන්න."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ඔබ ඔබේ කාර්යාල පැතිකඩ භාවිත කරමින් සිටී"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"ඇමතුම"</item>
+ <item msgid="5997713001067658559">"පද්ධතිය"</item>
+ <item msgid="7858983209929864160">"නාද කරන්න"</item>
+ <item msgid="1850038478268896762">"මාධ්ය"</item>
+ <item msgid="8265110906352372092">"එලාමය"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"බ්ලූටූත්"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ප්රවේශ්යතාව"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. නිහඬ කිරීම ඉවත් කිරීමට තට්ටු කරන්න."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. කම්පනය කිරීමට තට්ටු කරන්න. ප්රවේශ්යතා සේවා නිහඬ කළ හැකිය."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. නිහඬ කිරීමට තට්ටු කරන්න. ප්රවේශ්යතා සේවා නිහඬ කළ හැකිය."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 803be7f..94eb561 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -356,6 +356,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Menej naliehavé upozornenia sa nachádzajú nižšie"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Upozornenie otvoríte opätovným klepnutím"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Odomknete prejdením prstom nahor"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Toto zariadenie je spravované"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Toto zariadenie spravuje organizácia <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Telefón otvoríte prejdením prstom od ikony"</string>
<string name="voice_hint" msgid="8939888732119726665">"Hlasového asistenta otvoríte prejdením prstom od ikony"</string>
<string name="camera_hint" msgid="7939688436797157483">"Fotoaparát otvoríte prejdením prstom od ikony"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 0f03de9..ffbf4ff 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -356,6 +356,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Manj nujna obvestila spodaj"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Znova se dotaknite, da odprete"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Povlecite, da odklenete"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Ta naprava je upravljana"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"To napravo upravlja <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Povlecite z ikone za telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Povlecite z ikone za glasovnega pomočnika"</string>
<string name="camera_hint" msgid="7939688436797157483">"Povlecite z ikone za fotoaparat"</string>
@@ -446,7 +448,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je pogovorno okno glede prostornine"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Dotaknite se, če želite obnoviti prvotno stanje."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Uporabljate delovni profil"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Klic"</item>
+ <item msgid="5997713001067658559">"Sistem"</item>
+ <item msgid="7858983209929864160">"Zvonjenje"</item>
+ <item msgid="1850038478268896762">"Predstavnost"</item>
+ <item msgid="8265110906352372092">"Alarm"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Funkcije za ljudi s posebnimi potrebami"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Dotaknite se, če želite vklopiti zvok."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Dotaknite se, če želite nastaviti vibriranje. V storitvah za ljudi s posebnimi potrebami bo morda izklopljen zvok."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Dotaknite se, če želite izklopiti zvok. V storitvah za ljudi s posebnimi potrebami bo morda izklopljen zvok."</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index c03c0fe..9b0b832 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Njoftimet më pak urgjente, më poshtë!"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Trokit përsëri për ta hapur"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Rrëshqit për të shkyçur"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Kjo është një pajisje e menaxhuar"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Kjo pajisje menaxhohet nga <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Rrëshqit për të hapur telefonin"</string>
<string name="voice_hint" msgid="8939888732119726665">"Rrëshqit për të hapur ndihmën zanore"</string>
<string name="camera_hint" msgid="7939688436797157483">"Rrëshqit për të hapur kamerën"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> është dialogu i volumit"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Trokit për të restauruar origjinalin."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Po përdor profilin tënd të punës"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Telefono"</item>
+ <item msgid="5997713001067658559">"Sistemi"</item>
+ <item msgid="7858983209929864160">"Bjeri ziles"</item>
+ <item msgid="1850038478268896762">"Media"</item>
+ <item msgid="8265110906352372092">"Alarmi"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Qasshmëria"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Trokit për të aktivizuar."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Trokit për ta caktuar te dridhja. Shërbimet e qasshmërisë mund të çaktivizohen."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Trokit për të çaktivizuar. Shërbimet e qasshmërisë mund të çaktivizohen."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index fd560de..bf875e9 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Мање хитна обавештења су у наставку"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Додирните поново да бисте отворили"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Превуците нагоре да бисте откључали"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Овим уређајем се управља"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Овим уређајем управља <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Превуците од иконе за телефон"</string>
<string name="voice_hint" msgid="8939888732119726665">"Превуците од иконе за гласовну помоћ"</string>
<string name="camera_hint" msgid="7939688436797157483">"Превуците од иконе за камеру"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index e0c8472..6c4ee21 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mindre brådskande aviseringar nedan"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tryck igen för att öppna"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Svep uppåt för att låsa upp"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Den här enheten är hanterad"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Den här enheten hanteras av <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Svep från ikonen och öppna telefonen"</string>
<string name="voice_hint" msgid="8939888732119726665">"Svep från ikonen och öppna röstassistenten"</string>
<string name="camera_hint" msgid="7939688436797157483">"Svep från ikonen och öppna kameran"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 7c89410..e03615a 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Arifa zisizo za dharura sana ziko hapo chini"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Gonga tena ili ufungue"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Telezesha kidole ili ufungue"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Kifaa hiki kinadhibitiwa"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Kifaa hiki kinadhibitiwa na <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Telezesha kidole kutoka kwa aikoni ili ufikie simu"</string>
<string name="voice_hint" msgid="8939888732119726665">"Telezesha kidole kutoka aikoni ili upate mapendekezo ya sauti"</string>
<string name="camera_hint" msgid="7939688436797157483">"Telezesha kidole kutoka aikoni ili ufikie kamera"</string>
diff --git a/packages/SystemUI/res/values-sw900dp/config.xml b/packages/SystemUI/res/values-sw900dp/config.xml
new file mode 100644
index 0000000..182fa36
--- /dev/null
+++ b/packages/SystemUI/res/values-sw900dp/config.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+<resources>
+
+ <!-- Nav bar button default ordering/layout -->
+ <string name="config_navBarLayout" translatable="false">space[.2],back,home;space;menu_ime,recent,space[.2]</string>
+
+</resources>
diff --git a/packages/SystemUI/res/values-sw900dp/dimens.xml b/packages/SystemUI/res/values-sw900dp/dimens.xml
new file mode 100644
index 0000000..72e10c2
--- /dev/null
+++ b/packages/SystemUI/res/values-sw900dp/dimens.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+*/
+-->
+<resources>
+
+ <!-- All ryu nav buttons are th same size -->
+ <dimen name="button_size">80dp</dimen>
+ <dimen name="navigation_side_padding">@dimen/button_size</dimen>
+ <dimen name="navigation_key_width">@dimen/button_size</dimen>
+ <dimen name="navigation_extra_key_width">@dimen/button_size</dimen>
+
+ <!-- The maximum width of the navigation bar ripples. -->
+ <dimen name="key_button_ripple_max_width">76dp</dimen>
+
+ <!-- The padding around the navigation buttons -->
+ <dimen name="navigation_key_padding">5dp</dimen>
+
+ <!-- The inner radius of the halo. -->
+ <dimen name="halo_inner_radius">12dp</dimen>
+
+ <!-- The thickness of the halo. -->
+ <dimen name="halo_thickness">1dp</dimen>
+
+ <!-- The diameter of the halo. This is 2*(halo_inner_radius + halo_thickness). -->
+ <dimen name="halo_diameter">26dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index bd23b43..60f1d6a 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"அவசர நிலைக் குறைவான அறிவிப்புகள் கீழே உள்ளன"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"திறக்க, மீண்டும் தட்டவும்"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"திறக்க, மேலே ஸ்வைப் செய்யவும்"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"இந்தச் சாதனத்தை நிர்வகிப்பது:"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"இந்தச் சாதனத்தை நிர்வகிப்பது: <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"ஃபோனிற்கு ஐகானிலிருந்து ஸ்வைப் செய்யவும்"</string>
<string name="voice_hint" msgid="8939888732119726665">"குரல் உதவிக்கு ஐகானிலிருந்து ஸ்வைப் செய்யவும்"</string>
<string name="camera_hint" msgid="7939688436797157483">"கேமராவிற்கு ஐகானிலிருந்து ஸ்வைப் செய்யவும்"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"ஒலியளவு செய்தி: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"அசலை மீட்டமைக்க, தட்டவும்."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"பணி சுயவிவரத்தைப் பயன்படுத்துகிறீர்கள்"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"அழைப்பு"</item>
+ <item msgid="5997713001067658559">"சாதனம்"</item>
+ <item msgid="7858983209929864160">"ரிங்"</item>
+ <item msgid="1850038478268896762">"மீடியா"</item>
+ <item msgid="8265110906352372092">"அலாரம்"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"புளூடூத்"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"அணுகல்தன்மை"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. ஒலி இயக்க, தட்டவும்."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. அதிர்விற்கு அமைக்க, தட்டவும். அணுகல்தன்மை சேவைகள் ஒலியடக்கப்படக்கூடும்."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. ஒலியடக்க, தட்டவும். அணுகல்தன்மை சேவைகள் ஒலியடக்கப்படக்கூடும்."</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 6ae1e67..f500fc2 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"తక్కువ అత్యవసర నోటిఫికేషన్లు దిగువన"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"తెరవడానికి మళ్లీ నొక్కండి"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"అన్లాక్ చేయడానికి ఎగువకు స్వైప్ చేయండి"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"ఈ పరికరం నిర్వహణలో ఉంది"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"ఈ పరికరం <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> నిర్వహణలో ఉంది"</string>
<string name="phone_hint" msgid="4872890986869209950">"ఫోన్ కోసం చిహ్నాన్ని స్వైప్ చేయండి"</string>
<string name="voice_hint" msgid="8939888732119726665">"వాయిస్ సహాయకం చిహ్నం నుండి స్వైప్"</string>
<string name="camera_hint" msgid="7939688436797157483">"కెమెరా కోసం చిహ్నాన్ని స్వైప్ చేయండి"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> అనేది వాల్యూమ్ డైలాగ్"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"అసలు దాన్ని పునరుద్ధరించడానికి నొక్కండి."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"మీరు మీ కార్యాలయ ప్రొఫైల్ను ఉపయోగిస్తున్నారు"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"కాల్"</item>
+ <item msgid="5997713001067658559">"సిస్టమ్"</item>
+ <item msgid="7858983209929864160">"రింగ్"</item>
+ <item msgid="1850038478268896762">"మీడియా"</item>
+ <item msgid="8265110906352372092">"అలారం"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"బ్లూటూత్"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ప్రాప్యత"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. అన్మ్యూట్ చేయడానికి నొక్కండి."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. వైబ్రేషన్కు సెట్ చేయడానికి నొక్కండి. ప్రాప్యత సేవలు మ్యూట్ చేయబడవచ్చు."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. మ్యూట్ చేయడానికి నొక్కండి. ప్రాప్యత సేవలు మ్యూట్ చేయబడవచ్చు."</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 7e2c00f8..e4d39b7 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"การแจ้งเตือนที่เร่งด่วนน้อยด้านล่าง"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"แตะอีกครั้งเพื่อเปิด"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"เลื่อนเพื่อปลดล็อก"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"อุปกรณ์เครื่องนี้มีการจัดการ"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"อุปกรณ์เครื่องนี้จัดการโดย <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"เลื่อนไอคอนโทรศัพท์"</string>
<string name="voice_hint" msgid="8939888732119726665">"เลื่อนไอคอนตัวช่วยเสียง"</string>
<string name="camera_hint" msgid="7939688436797157483">"เลื่อนไอคอนกล้อง"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> เป็นช่องโต้ตอบระดับเสียง"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"แตะเพื่อคืนค่าเป็นค่าเดิม"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"คุณกำลังใช้โปรไฟล์งานของคุณ"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"โทร"</item>
+ <item msgid="5997713001067658559">"ระบบ"</item>
+ <item msgid="7858983209929864160">"ทำให้ส่งเสียง"</item>
+ <item msgid="1850038478268896762">"สื่อ"</item>
+ <item msgid="8265110906352372092">"การปลุก"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"บลูทูธ"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"การเข้าถึง"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s แตะเพื่อเปิดเสียง"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s แตะเพื่อตั้งค่าให้สั่น อาจมีการปิดเสียงบริการการเข้าถึง"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s แตะเพื่อปิดเสียง อาจมีการปิดเสียงบริการการเข้าถึง"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index e1e06df..de81f71 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Nasa ibaba ang mga notification na hindi masyadong mahalaga"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"I-tap ulit upang buksan"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"I-swipe pataas upang i-unlock"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Pinamamahalaan ang device na ito"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Pinamamahalaan ng <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ang device na ito"</string>
<string name="phone_hint" msgid="4872890986869209950">"Mag-swipe mula sa icon para sa telepono"</string>
<string name="voice_hint" msgid="8939888732119726665">"Mag-swipe mula sa icon para sa voice assist"</string>
<string name="camera_hint" msgid="7939688436797157483">"Mag-swipe mula sa icon para sa camera"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ang volume dialog"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"I-tap upang i-restore ang orihinal."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Ginagamit mo ang iyong profile sa trabaho"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Tawag"</item>
+ <item msgid="5997713001067658559">"System"</item>
+ <item msgid="7858983209929864160">"Ipa-ring"</item>
+ <item msgid="1850038478268896762">"Media"</item>
+ <item msgid="8265110906352372092">"Alarm"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Pagiging Naa-access"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. I-tap upang i-unmute."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. I-tap upang itakda na mag-vibrate. Maaaring i-mute ang mga serbisyo sa Accessibility."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. I-tap upang i-mute. Maaaring i-mute ang mga serbisyo sa Accessibility."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index d416fdf..c6e4909 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Daha az acil bildirimler aşağıdadır"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Açmak için tekrar dokunun"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Kilidi açmak için hızlıca yukarı kaydırın"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Bu cihaz yönetilen bir cihazdır"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tarafından yönetilmektedir."</string>
<string name="phone_hint" msgid="4872890986869209950">"Telefon için, simgeden hızlıca kaydırın"</string>
<string name="voice_hint" msgid="8939888732119726665">"Sesli yardım için, simgeden hızlıca kaydırın"</string>
<string name="camera_hint" msgid="7939688436797157483">"Kamera için, simgeden hızlıca kaydırın"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ses denetimi iletişim kutusu olarak ayarlandı"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Orijinali geri yüklemek için dokunun."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"İş profilinizi kullanıyorsunuz"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Çağrı"</item>
+ <item msgid="5997713001067658559">"Sistem"</item>
+ <item msgid="7858983209929864160">"Zili Çaldır"</item>
+ <item msgid="1850038478268896762">"Medya"</item>
+ <item msgid="8265110906352372092">"Alarm"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Erişilebilirlik"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Sesi açmak için hafifçe dokunun."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Titreşime ayarlamak için hafifçe dokunun. Erişilebilirlik hizmetlerinin sesi kapatılabilir."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Sesi kapatmak için hafifçe dokunun. Erişilebilirlik hizmetlerinin sesi kapatılabilir."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 5db65459..21f9e0e 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -356,6 +356,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Менше термінових сповіщень нижче"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Торкніться знову, щоб відкрити"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Проведіть пальцем угору, щоб розблокувати"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Цим пристроєм керує адміністратор"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Цим пристроєм керує організація <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Телефон: проведіть пальцем від значка"</string>
<string name="voice_hint" msgid="8939888732119726665">"Голосові підказки: проведіть пальцем від значка"</string>
<string name="camera_hint" msgid="7939688436797157483">"Камера: проведіть пальцем від значка"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index bc89301..0bf112e 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"کم اہم اطلاعات ذیل میں ہیں"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"کھولنے کیلئے دوبارہ تھپتھپائیں"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"غیر مقفل کرنے کیلئے اوپر سوائپ کریں"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"یہ آلہ زیر انتظام ہے"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"یہ آلہ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> کے زیر انتظام ہے"</string>
<string name="phone_hint" msgid="4872890986869209950">"فون کیلئے آئیکن سے سوائپ کریں"</string>
<string name="voice_hint" msgid="8939888732119726665">"صوتی معاون کیلئے آئیکن سے سوائپ کریں"</string>
<string name="camera_hint" msgid="7939688436797157483">"کیمرہ کیلئے آئیکن سے سوائپ کریں"</string>
@@ -440,10 +442,22 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> والیوم ڈائلاگ ہے"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"اصل بحال کرنے کیلئے تھپتھپائیں۔"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"آپ اپنا دفتری پروفائل استعمال کر رہے ہیں۔"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"کال"</item>
+ <item msgid="5997713001067658559">"سسٹم"</item>
+ <item msgid="7858983209929864160">"رِنگ"</item>
+ <item msgid="1850038478268896762">"میڈیا"</item>
+ <item msgid="8265110906352372092">"الارم"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"بلوٹوتھ"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"ایکسیسبیلٹی"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s۔ آواز چالو کرنے کیلئے تھپتھپائیں۔"</string>
- <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s۔ ارتعاش پر سیٹ کرنے کیلئے تھپتھپائیں۔ Accessibility سروسز شاید خاموش ہوں۔"</string>
- <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s۔ خاموش کرنے کیلئے تھپتھپائیں۔ Accessibility سروسز شاید خاموش ہوں۔"</string>
+ <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s۔ ارتعاش پر سیٹ کرنے کیلئے تھپتھپائیں۔ ایکسیسبیلٹی سروسز شاید خاموش ہوں۔"</string>
+ <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s۔ خاموش کرنے کیلئے تھپتھپائیں۔ ایکسیسبیلٹی سروسز شاید خاموش ہوں۔"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s والیوم کے کنٹرولز دکھائے جا رہے ہیں۔ برخاست کرنے کیلئے سوائپ کریں۔"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"والیوم کے کنٹرولز مخفی ہیں"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"سسٹم UI ٹیونر"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index a71b539..591b98a 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Kam ahamiyatli bildirishnomalarni pastda ko‘rsatish"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ochish uchun yana bosing"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Qulfdan chiqarish uchun tepaga suring"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Bu – boshqariladigan qurilma"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Bu – <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> tomonidan boshqariladigan qurilma"</string>
<string name="phone_hint" msgid="4872890986869209950">"Telefonni ochish uchun suring"</string>
<string name="voice_hint" msgid="8939888732119726665">"Ovozli yordam: belgidan boshlab suring"</string>
<string name="camera_hint" msgid="7939688436797157483">"Kamerani ochish uchun suring"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d0d8216..8b6ea67 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Thông báo ít khẩn cấp hơn bên dưới"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Nhấn lại để mở"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Vuốt lên để mở khóa"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Thiết bị này được quản lý"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Thiết bị này được <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> quản lý"</string>
<string name="phone_hint" msgid="4872890986869209950">"Vuốt từ biểu tượng để mở điện thoại"</string>
<string name="voice_hint" msgid="8939888732119726665">"Vuốt từ biểu tượng để mở trợ lý thoại"</string>
<string name="camera_hint" msgid="7939688436797157483">"Vuốt từ biểu tượng để mở máy ảnh"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> là hộp thoại khối lượng"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Nhấn để khôi phục ảnh chụp màn hình gốc."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Bạn đang sử dụng hồ sơ công việc của mình"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Gọi"</item>
+ <item msgid="5997713001067658559">"Hệ thống"</item>
+ <item msgid="7858983209929864160">"Chuông"</item>
+ <item msgid="1850038478268896762">"Phương tiện"</item>
+ <item msgid="8265110906352372092">"Báo thức"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"Trợ năng"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Nhấn để bật tiếng."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Nhấn để đặt chế độ rung. Bạn có thể tắt tiếng dịch vụ trợ năng."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Nhấn để tắt tiếng. Bạn có thể tắt tiếng dịch vụ trợ năng."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7928bf9..172c107 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"不太紧急的通知会显示在下方"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"再次点按即可打开"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"向上滑动即可解锁"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"此设备已受到托管"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"此设备是由<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>托管"</string>
<string name="phone_hint" msgid="4872890986869209950">"滑动图标即可拨打电话"</string>
<string name="voice_hint" msgid="8939888732119726665">"滑动图标即可打开语音助理"</string>
<string name="camera_hint" msgid="7939688436797157483">"滑动图标即可打开相机"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”已用作音量控制对话框"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"点按即可恢复原始设置。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您当前正在使用工作资料"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"通话"</item>
+ <item msgid="5997713001067658559">"系统"</item>
+ <item msgid="7858983209929864160">"铃声"</item>
+ <item msgid="1850038478268896762">"媒体"</item>
+ <item msgid="8265110906352372092">"闹钟"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"蓝牙"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"无障碍"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。点按即可取消静音。"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。点按即可设为振动,但可能会同时将无障碍服务设为静音。"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。点按即可设为静音,但可能会同时将无障碍服务设为静音。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index b4ea6f8..afae1ee 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -352,6 +352,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"不太緊急的通知會在下方顯示"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"再次輕按即可開啟"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"向上快速滑動即可解鎖"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"此裝置已受管理"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"此裝置由<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>管理"</string>
<string name="phone_hint" msgid="4872890986869209950">"從圖示快速滑動即可使用手機功能"</string>
<string name="voice_hint" msgid="8939888732119726665">"從圖示快速滑動即可使用語音助手"</string>
<string name="camera_hint" msgid="7939688436797157483">"從圖示快速滑動即可使用相機功能"</string>
@@ -442,7 +444,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」為音量對話框"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"輕按即可復原。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您正在使用工作設定檔"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"通話"</item>
+ <item msgid="5997713001067658559">"系統"</item>
+ <item msgid="7858983209929864160">"鈴聲"</item>
+ <item msgid="1850038478268896762">"媒體"</item>
+ <item msgid="8265110906352372092">"鬧鐘"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"藍牙"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"無障礙功能"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。輕按即可取消靜音。"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。輕按即可設為震動。無障礙功能服務可能已經設為靜音。"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。輕按即可設為靜音。無障礙功能服務可能已經設為靜音。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index a6a87f6..17946f3 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"較不緊急的通知會顯示在下方"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"再次輕觸即可開啟"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"向上滑動即可解鎖"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"這個裝置受到管理"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"這個裝置是由 <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> 所管理"</string>
<string name="phone_hint" msgid="4872890986869209950">"滑動手機圖示即可啟用"</string>
<string name="voice_hint" msgid="8939888732119726665">"滑動語音小幫手圖示即可啟用"</string>
<string name="camera_hint" msgid="7939688436797157483">"滑動相機圖示即可啟用"</string>
@@ -440,7 +442,19 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」現在是預設的音量控制對話方塊。"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"輕觸即可恢復原始設定。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您正在使用 Work 設定檔"</string>
- <!-- no translation found for volume_stream_titles:10 (8119402510273906841) -->
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"通話"</item>
+ <item msgid="5997713001067658559">"系統"</item>
+ <item msgid="7858983209929864160">"鈴聲"</item>
+ <item msgid="1850038478268896762">"媒體"</item>
+ <item msgid="8265110906352372092">"鬧鐘"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"藍牙"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ <item msgid="8119402510273906841">"協助工具"</item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。輕觸即可取消靜音。"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。輕觸即可設為震動,但系統可能會將無障礙服務一併設為靜音。"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。輕觸即可設為靜音,但系統可能會將無障礙服務一併設為靜音。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 324d306..9d76dc3 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -350,6 +350,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Izaziso ezingasheshi kakhulu ezingezansi"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Thepha futhi ukuze uvule"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Swayiphela phezulu ukuze uvule"</string>
+ <string name="do_disclosure_generic" msgid="8498005633306135779">"Le divayisi iphethwe"</string>
+ <string name="do_disclosure_with_name" msgid="5640615509915445501">"Le divayisi iphethwe yi-<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Swayiphela ifoni kusukela kusithonjana"</string>
<string name="voice_hint" msgid="8939888732119726665">"Swayiphela isilekeleli sezwi kusukela kusithonjana"</string>
<string name="camera_hint" msgid="7939688436797157483">"Swayiphela ikhamela kusukela kusithonjana"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 52565ba..e41991a 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -131,7 +131,6 @@
<color name="light_mode_icon_color_dual_tone_background">#4dffffff</color>
<color name="light_mode_icon_color_dual_tone_fill">#ffffff</color>
- <color name="volume_icon_color">#ffffffff</color>
<color name="volume_settings_icon_color">#7fffffff</color>
<color name="volume_slider_inactive">@*android:color/quaternary_device_default_settings</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a6604cb..a7d4aa0 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -81,6 +81,9 @@
<!-- Height of a heads up notification in the status bar -->
<dimen name="notification_max_heads_up_height">148dp</dimen>
+ <!-- a threshold in dp per second that is considered fast scrolling -->
+ <dimen name="scroll_fast_threshold">1500dp</dimen>
+
<!-- Height of a the shelf with the notification icons -->
<dimen name="notification_shelf_height">32dp</dimen>
@@ -94,6 +97,9 @@
<!-- The amount the content shifts upwards when transforming into the icon -->
<dimen name="notification_icon_transform_content_shift">32dp</dimen>
+ <!-- The padding on the bottom of the notifications on the keyguard -->
+ <dimen name="keyguard_indication_bottom_padding">12sp</dimen>
+
<!-- Minimum layouted height of a notification in the statusbar-->
<dimen name="min_notification_layout_height">48dp</dimen>
@@ -129,9 +135,6 @@
<dimen name="navigation_key_padding">0dp</dimen>
- <dimen name="navigation_key_width_sw600dp_land">162dp</dimen>
- <dimen name="navigation_key_padding_sw600dp_land">42dp</dimen>
-
<!-- The width of the view containing the menu/ime navigation bar icons -->
<dimen name="navigation_extra_key_width">36dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index bfc26e3..c8b3b69d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -840,10 +840,10 @@
<!-- Shows when people have pressed the unlock icon to explain how to unlock. [CHAR LIMIT=60] -->
<string name="keyguard_unlock">Swipe up to unlock</string>
- <!-- Text on keyguard screen indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=60] -->
+ <!-- Text on keyguard screen and in Quick Settings footer indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=60] -->
<string name="do_disclosure_generic">This device is managed</string>
- <!-- Text on keyguard screen indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=40] -->
+ <!-- Text on keyguard screen and in Quick Settings footer indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=40] -->
<string name="do_disclosure_with_name">This device is managed by <xliff:g id="organization_name" example="Foo, Inc.">%s</xliff:g></string>
<!-- Shows when people have clicked on the phone icon [CHAR LIMIT=60] -->
@@ -992,9 +992,6 @@
<!-- Text which is shown in the notification shade when there are no notifications. [CHAR LIMIT=30] -->
<string name="empty_shade_text">No notifications</string>
- <!-- Footer device owned text [CHAR LIMIT=50] -->
- <string name="device_owned_footer">Device may be monitored</string>
-
<!-- Footer profile owned text [CHAR LIMIT=50] -->
<string name="profile_owned_footer">Profile may be monitored</string>
@@ -1019,15 +1016,27 @@
<!-- Monitoring dialog disconnect vpn button [CHAR LIMIT=30] -->
<string name="disconnect_vpn">Disconnect VPN</string>
- <!-- Monitoring dialog device owner body text [CHAR LIMIT=400] -->
- <string name="monitoring_description_device_owned">Your device is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information. For more information, contact your administrator.</string>
+ <!-- Monitoring dialog: Header indicating that the device is managed by a Device Owner app [CHAR LIMIT=80] -->
+ <string name="monitoring_description_do_header_generic">Your device is managed by <xliff:g id="device_owner_app" example="Google Mobile Management">%1$s</xliff:g>.</string>
+
+ <!-- Monitoring dialog: Header indicating that the device is managed by a Device Owner app [CHAR LIMIT=60] -->
+ <string name="monitoring_description_do_header_with_name"><xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g> uses <xliff:g id="device_owner_app" example="Google Mobile Management">%2$s</xliff:g> to manage your device.</string>
+
+ <!-- Monitoring dialog: Part of text body explaining what a Device Owner app can do [CHAR LIMIT=130] -->
+ <string name="monitoring_description_do_body">Your administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.</string>
+
+ <!-- Monitoring dialog: Part of text body explaining that a VPN is connected and what it can do, for devices managed by a Device Owner app [CHAR LIMIT=130] -->
+ <string name="monitoring_description_do_body_vpn">You\'re connected to <xliff:g id="vpn_app">%1$s</xliff:g>, which can monitor your network activity, including emails, apps, and websites.</string>
+
+ <!-- Monitoring dialog: Space that separates the body text and the "learn more" link that follows it. [CHAR LIMIT=5] -->
+ <string name="monitoring_description_do_learn_more_separator">" "</string>
+
+ <!-- Monitoring dialog: Link to learn more about what a Device Owner app can do [CHAR LIMIT=55] -->
+ <string name="monitoring_description_do_learn_more">Learn more</string>
<!-- Monitoring dialog VPN text [CHAR LIMIT=400] -->
<string name="monitoring_description_vpn">You gave an app permission to set up a VPN connection.\n\nThis app can monitor your device and network activity, including emails, apps, and websites.</string>
- <!-- Monitoring dialog VPN with device owner text [CHAR LIMIT=400] -->
- <string name="monitoring_description_vpn_device_owned">Your device is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nYou\'re connected to a VPN, which can monitor your network activity, including emails, apps, and websites.\n\nFor more information, contact your administrator.</string>
-
<!-- Monitoring dialog VPN with profile owner text [CHAR LIMIT=400] -->
<string name="monitoring_description_vpn_profile_owned">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator is capable of monitoring your network activity including emails, apps, and websites.\n\nFor more information, contact your administrator.\n\nYou\'re also connected to a VPN, which can monitor your network activity.</string>
@@ -1049,9 +1058,6 @@
<!-- Monitoring dialog text for multiple apps (in personal and work profiles) [CHAR LIMIT=400] -->
<string name="monitoring_description_app_personal_work">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>. It is connected to <xliff:g id="application_work">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps, and websites.\n\nYou\'re also connected to <xliff:g id="application_personal">%3$s</xliff:g>, which can monitor your personal network activity.</string>
- <!-- Monitoring dialog text for single app (with device owner) [CHAR LIMIT=400] -->
- <string name="monitoring_description_vpn_app_device_owned">Your device is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nYou\'re connected to <xliff:g id="application">%2$s</xliff:g>, which can monitor your network activity, including emails, apps, and websites.\n\nFor more information, contact your administrator.</string>
-
<!-- Indication on the keyguard that appears when the user disables trust agents until the next time they unlock manually. [CHAR LIMIT=NONE] -->
<string name="keyguard_indication_trust_disabled">Device will stay locked until you manually unlock</string>
@@ -1126,6 +1132,7 @@
<item></item> <!-- STREAM_SYSTEM_ENFORCED -->
<item></item> <!-- STREAM_DTMF -->
<item></item> <!-- STREAM_TTS -->
+ <item>Accessibility</item> <!-- STREAM_ACCESSIBILITY -->
</string-array>
<string name="volume_stream_muted" translatable="false">%s silent</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 78fc9f9..08b8988 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -127,7 +127,7 @@
<style name="TextAppearance.StatusBar.Expanded.Clock">
<item name="android:textSize">@dimen/qs_time_expanded_size</item>
<item name="android:fontFamily">sans-serif-medium</item>
- <item name="android:textColor">#ffffff</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="TextAppearance.StatusBar.Expanded.Date">
@@ -159,7 +159,7 @@
<style name="TextAppearance.QS">
<item name="android:textStyle">normal</item>
- <item name="android:textColor">@color/qs_text</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:fontFamily">sans-serif</item>
</style>
@@ -259,7 +259,7 @@
<style name="Animation.StatusBar">
</style>
- <style name="systemui_theme" parent="@*android:style/Theme.DeviceDefault.Settings.Dark" />
+ <style name="systemui_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings" />
<style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light">
<item name="android:colorAccent">@color/remote_input_accent</item>
@@ -400,7 +400,7 @@
<item name="android:textColor">?android:attr/colorAccent</item>
</style>
- <style name="edit_theme" parent="@*android:style/Theme.DeviceDefault.Settings.Dark">
+ <style name="edit_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
<item name="android:colorBackground">?android:attr/colorSecondary</item>
</style>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index e036128..10328a4 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -30,6 +30,7 @@
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
+import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -96,9 +97,10 @@
dismissCallbackRegistry);
}
- public ScrimController createScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
- View headsUpScrim, LockscreenWallpaper lockscreenWallpaper) {
- return new ScrimController(scrimBehind, scrimInFront, headsUpScrim);
+ public ScrimController createScrimController(LightBarController lightBarController,
+ ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim,
+ LockscreenWallpaper lockscreenWallpaper) {
+ return new ScrimController(lightBarController, scrimBehind, scrimInFront, headsUpScrim);
}
public VolumeDialogController createVolumeDialogController(Context context,
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 9eceeac..3f9ae55 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -13,6 +13,7 @@
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.os.AsyncTask;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -155,6 +156,7 @@
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
+ lp.token = new Binder();
if (ActivityManager.isHighEndGfx()) {
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 951b27f..13e047c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -56,7 +56,41 @@
/** Pulse is done showing. Followed by transition to DOZE or DOZE_AOD. */
DOZE_PULSE_DONE,
/** Doze is done. DozeService is finished. */
- FINISH,
+ FINISH;
+
+ boolean canPulse() {
+ switch (this) {
+ case DOZE:
+ case DOZE_AOD:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ boolean staysAwake() {
+ switch (this) {
+ case DOZE_REQUEST_PULSE:
+ case DOZE_PULSING:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ int screenState() {
+ switch (this) {
+ case UNINITIALIZED:
+ case INITIALIZED:
+ case DOZE:
+ return Display.STATE_OFF;
+ case DOZE_PULSING:
+ case DOZE_AOD:
+ return Display.STATE_DOZE; // TODO: use STATE_ON if appropriate.
+ default:
+ return Display.STATE_UNKNOWN;
+ }
+ }
}
private final Service mDozeService;
@@ -165,52 +199,32 @@
}
private void validateTransition(State newState) {
- switch (mState) {
- case FINISH:
- Preconditions.checkState(newState == State.FINISH);
- break;
- case UNINITIALIZED:
- Preconditions.checkState(newState == State.INITIALIZED);
- break;
- }
- switch (newState) {
- case UNINITIALIZED:
- throw new IllegalArgumentException("can't go to UNINITIALIZED");
- case INITIALIZED:
- Preconditions.checkState(mState == State.UNINITIALIZED);
- break;
- case DOZE_PULSING:
- Preconditions.checkState(mState == State.DOZE_REQUEST_PULSE);
- break;
- case DOZE_PULSE_DONE:
- Preconditions.checkState(mState == State.DOZE_PULSING);
- break;
- default:
- break;
- }
- }
-
- private int screenPolicy(State newState) {
- switch (newState) {
- case UNINITIALIZED:
- case INITIALIZED:
- case DOZE:
- return Display.STATE_OFF;
- case DOZE_PULSING:
- case DOZE_AOD:
- return Display.STATE_DOZE; // TODO: use STATE_ON if appropriate.
- default:
- return Display.STATE_UNKNOWN;
- }
- }
-
- private boolean wakeLockPolicy(State newState) {
- switch (newState) {
- case DOZE_REQUEST_PULSE:
- case DOZE_PULSING:
- return true;
- default:
- return false;
+ try {
+ switch (mState) {
+ case FINISH:
+ Preconditions.checkState(newState == State.FINISH);
+ break;
+ case UNINITIALIZED:
+ Preconditions.checkState(newState == State.INITIALIZED);
+ break;
+ }
+ switch (newState) {
+ case UNINITIALIZED:
+ throw new IllegalArgumentException("can't transition to UNINITIALIZED");
+ case INITIALIZED:
+ Preconditions.checkState(mState == State.UNINITIALIZED);
+ break;
+ case DOZE_PULSING:
+ Preconditions.checkState(mState == State.DOZE_REQUEST_PULSE);
+ break;
+ case DOZE_PULSE_DONE:
+ Preconditions.checkState(mState == State.DOZE_PULSING);
+ break;
+ default:
+ break;
+ }
+ } catch (RuntimeException e) {
+ throw new IllegalStateException("Illegal Transition: " + mState + " -> " + newState, e);
}
}
@@ -218,22 +232,26 @@
if (mState == State.FINISH) {
return State.FINISH;
}
+ if (requestedState == State.DOZE_REQUEST_PULSE && !mState.canPulse()) {
+ Log.i(TAG, "Dropping pulse request because current state can't pulse: " + mState);
+ return mState;
+ }
return requestedState;
}
private void updateWakeLockState(State newState) {
- boolean newPolicy = wakeLockPolicy(newState);
- if (mWakeLockHeldForCurrentState && !newPolicy) {
+ boolean staysAwake = newState.staysAwake();
+ if (mWakeLockHeldForCurrentState && !staysAwake) {
mWakeLock.release();
mWakeLockHeldForCurrentState = false;
- } else if (!mWakeLockHeldForCurrentState && newPolicy) {
+ } else if (!mWakeLockHeldForCurrentState && staysAwake) {
mWakeLock.acquire();
mWakeLockHeldForCurrentState = true;
}
}
private void updateScreenState(State newState) {
- int state = screenPolicy(newState);
+ int state = newState.screenState();
if (state != Display.STATE_UNKNOWN) {
mDozeService.setDozeScreenState(state);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 07e1193..d4da9a4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -17,6 +17,8 @@
package com.android.systemui.keyguard;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+
+import static com.android.internal.telephony.IccCardConstants.State.ABSENT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
@@ -429,7 +431,11 @@
resetStateLocked();
}
}
- onSimNotReadyLocked();
+ if (simState == ABSENT) {
+ // MVNO SIMs can become transiently NOT_READY when switching networks,
+ // so we should only lock when they are ABSENT.
+ onSimAbsentLocked();
+ }
}
break;
case PIN_REQUIRED:
@@ -456,7 +462,7 @@
+ "show permanently disabled message in lockscreen.");
resetStateLocked();
}
- onSimNotReadyLocked();
+ onSimAbsentLocked();
}
break;
case READY:
@@ -470,22 +476,20 @@
default:
if (DEBUG_SIM_STATES) Log.v(TAG, "Unspecific state: " + simState);
synchronized (KeyguardViewMediator.this) {
- onSimNotReadyLocked();
+ onSimAbsentLocked();
}
break;
}
}
- private void onSimNotReadyLocked() {
+ private void onSimAbsentLocked() {
if (isSecure() && mLockWhenSimRemoved) {
mLockWhenSimRemoved = false;
MetricsLogger.action(mContext,
MetricsProto.MetricsEvent.ACTION_LOCK_BECAUSE_SIM_REMOVED, mShowing);
if (!mShowing) {
- if (DEBUG_SIM_STATES) Log.d(TAG, "SIM removed, showing keyguard");
+ Log.i(TAG, "SIM removed, showing keyguard");
doKeyguardLocked(null);
- } else {
- resetStateLocked();
}
}
}
@@ -1228,7 +1232,7 @@
// if the setup wizard hasn't run yet, don't show
final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", false);
final boolean absent = SubscriptionManager.isValidSubscriptionId(
- mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.ABSENT));
+ mUpdateMonitor.getNextSubIdForState(ABSENT));
final boolean disabled = SubscriptionManager.isValidSubscriptionId(
mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.PERM_DISABLED));
final boolean lockedOrMissing = mUpdateMonitor.isSimPinSecure()
@@ -1798,7 +1802,6 @@
// (like recents). Temporary enable/disable (e.g. the "back" button) are
// done in KeyguardHostView.
flags |= StatusBarManager.DISABLE_RECENT;
- flags |= StatusBarManager.DISABLE_SEARCH;
}
if (isShowingAndNotOccluded()) {
flags |= StatusBarManager.DISABLE_HOME;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index c6dde46..09671e7 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -156,6 +156,10 @@
@Override
public void onListenerRegistered(IPinnedStackController controller) {
mPinnedStackController = controller;
+
+ // Update the controller with the current tuner state
+ setMinimizedState(mIsMinimized);
+ setSnapToEdge(mEnableSnapToEdge);
}
@Override
@@ -353,10 +357,13 @@
*/
private void setSnapToEdge(boolean snapToEdge) {
mSnapAlgorithm.setSnapToEdge(snapToEdge);
- try {
- mPinnedStackController.setSnapToEdge(snapToEdge);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not set snap mode to edge", e);
+
+ if (mPinnedStackController != null) {
+ try {
+ mPinnedStackController.setSnapToEdge(snapToEdge);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not set snap mode to edge", e);
+ }
}
}
@@ -365,10 +372,13 @@
*/
private void setMinimizedState(boolean isMinimized) {
mIsMinimized = isMinimized;
- try {
- mPinnedStackController.setIsMinimized(isMinimized);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not set minimized state", e);
+
+ if (mPinnedStackController != null) {
+ try {
+ mPinnedStackController.setIsMinimized(isMinimized);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not set minimized state", e);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index ccb28e9..f3da47b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -24,10 +24,15 @@
import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.SpannableStringBuilder;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
+import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
@@ -46,19 +51,23 @@
private final View mRootView;
private final TextView mFooterText;
private final ImageView mFooterIcon;
+ private final ImageView mFooterIcon2;
private final Context mContext;
private final Callback mCallback = new Callback();
private SecurityController mSecurityController;
private AlertDialog mDialog;
private QSTileHost mHost;
- private Handler mHandler;
+ protected Handler mHandler;
private final Handler mMainHandler;
private boolean mIsVisible;
private boolean mIsIconVisible;
+ private boolean mIsIcon2Visible;
+ private CharSequence mFooterTextContent = null;
private int mFooterTextId;
private int mFooterIconId;
+ private int mFooterIcon2Id;
public QSFooter(QSPanel qsPanel, Context context) {
mRootView = LayoutInflater.from(context)
@@ -66,15 +75,18 @@
mRootView.setOnClickListener(this);
mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon);
+ mFooterIcon2 = (ImageView) mRootView.findViewById(R.id.footer_icon2);
mFooterIconId = R.drawable.ic_qs_vpn;
+ mFooterIcon2Id = R.drawable.ic_qs_network_logging;
mContext = context;
- mMainHandler = new Handler();
+ mMainHandler = new Handler(Looper.getMainLooper());
}
- public void setHost(QSTileHost host) {
+ public void setHostEnvironment(QSTileHost host, SecurityController securityController,
+ Looper looper) {
mHost = host;
- mSecurityController = host.getSecurityController();
- mHandler = new H(host.getLooper());
+ mSecurityController = securityController;
+ mHandler = new H(looper);
}
public void setListening(boolean listening) {
@@ -113,17 +125,36 @@
}
private void handleRefreshState() {
- mIsIconVisible = mSecurityController.isVpnEnabled();
- // If the device has device owner, show "Device may be monitored", but --
- // TODO See b/25779452 -- device owner doesn't actually have monitoring power.
+ boolean isVpnEnabled = mSecurityController.isVpnEnabled();
+ boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
+ mIsIconVisible = isVpnEnabled || isNetworkLoggingEnabled;
+ mIsIcon2Visible = isVpnEnabled && isNetworkLoggingEnabled;
if (mSecurityController.isDeviceManaged()) {
- mFooterTextId = R.string.device_owned_footer;
+ final CharSequence organizationName =
+ mSecurityController.getDeviceOwnerOrganizationName();
+ if (organizationName != null) {
+ mFooterTextContent = mContext.getResources().getString(
+ R.string.do_disclosure_with_name, organizationName);
+ } else {
+ mFooterTextContent =
+ mContext.getResources().getString(R.string.do_disclosure_generic);
+ }
mIsVisible = true;
+ int footerIconId = isVpnEnabled
+ ? R.drawable.ic_qs_vpn
+ : R.drawable.ic_qs_network_logging;
+ if (mFooterIconId != footerIconId) {
+ mFooterIconId = footerIconId;
+ mMainHandler.post(mUpdateIcon);
+ }
} else {
boolean isBranded = mSecurityController.isVpnBranded();
- mFooterTextId = isBranded ? R.string.branded_vpn_footer : R.string.vpn_footer;
+ mFooterTextContent = mContext.getResources().getText(
+ isBranded ? R.string.branded_vpn_footer : R.string.vpn_footer);
// Update the VPN footer icon, if needed.
- int footerIconId = isBranded ? R.drawable.ic_qs_branded_vpn : R.drawable.ic_qs_vpn;
+ int footerIconId = isVpnEnabled
+ ? (isBranded ? R.drawable.ic_qs_branded_vpn : R.drawable.ic_qs_vpn)
+ : R.drawable.ic_qs_network_logging;
if (mFooterIconId != footerIconId) {
mFooterIconId = footerIconId;
mMainHandler.post(mUpdateIcon);
@@ -142,23 +173,36 @@
}
private void createDialog() {
- String deviceOwner = mSecurityController.getDeviceOwnerName();
- String profileOwner = mSecurityController.getProfileOwnerName();
- String primaryVpn = mSecurityController.getPrimaryVpnName();
- String profileVpn = mSecurityController.getProfileVpnName();
- boolean managed = mSecurityController.hasProfileOwner();
- boolean isBranded = deviceOwner == null && mSecurityController.isVpnBranded();
+ final String deviceOwnerPackage = mSecurityController.getDeviceOwnerName();
+ final String profileOwnerPackage = mSecurityController.getProfileOwnerName();
+ final String primaryVpn = mSecurityController.getPrimaryVpnName();
+ final String profileVpn = mSecurityController.getProfileVpnName();
+ final CharSequence deviceOwnerOrganization =
+ mSecurityController.getDeviceOwnerOrganizationName();
+ boolean hasProfileOwner = mSecurityController.hasProfileOwner();
+ boolean isBranded = deviceOwnerPackage == null && mSecurityController.isVpnBranded();
mDialog = new SystemUIDialog(mContext);
if (!isBranded) {
- mDialog.setTitle(getTitle(deviceOwner));
+ mDialog.setTitle(getTitle(deviceOwnerPackage));
}
- mDialog.setMessage(getMessage(deviceOwner, profileOwner, primaryVpn, profileVpn, managed,
- isBranded));
+ mDialog.setMessage(getMessage(deviceOwnerPackage, profileOwnerPackage, primaryVpn,
+ profileVpn, deviceOwnerOrganization, hasProfileOwner, isBranded));
+
mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(isBranded), this);
if (mSecurityController.isVpnEnabled() && !mSecurityController.isVpnRestricted()) {
mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getSettingsButton(), this);
}
+
+ // Make the link "learn more" clickable.
+ // TODO: Reaching into SystemUIDialog's internal View hierarchy is ugly and error-prone.
+ // This is a temporary solution. b/33126622 will introduce a custom View hierarchy for this
+ // dialog, allowing us to set the movement method on the appropriate View without any
+ // knowledge of SystemUIDialog's internals.
+ mDialog.create();
+ ((TextView) mDialog.getWindow().findViewById(com.android.internal.R.id.message))
+ .setMovementMethod(new LinkMovementMethod());
+
mDialog.show();
}
@@ -170,22 +214,35 @@
return mContext.getString(isBranded ? android.R.string.ok : R.string.quick_settings_done);
}
- private String getMessage(String deviceOwner, String profileOwner, String primaryVpn,
- String profileVpn, boolean primaryUserIsManaged, boolean isBranded) {
- // Show a special warning when the device has device owner, but --
- // TODO See b/25779452 -- device owner doesn't actually have monitoring power.
- if (deviceOwner != null) {
- if (primaryVpn != null) {
- return mContext.getString(R.string.monitoring_description_vpn_app_device_owned,
- deviceOwner, primaryVpn);
+ protected CharSequence getMessage(String deviceOwnerPackage, String profileOwnerPackage,
+ String primaryVpn, String profileVpn, CharSequence deviceOwnerOrganization,
+ boolean hasProfileOwner, boolean isBranded) {
+ if (deviceOwnerPackage != null) {
+ final SpannableStringBuilder message = new SpannableStringBuilder();
+ if (deviceOwnerOrganization != null) {
+ message.append(mContext.getString(
+ R.string.monitoring_description_do_header_with_name,
+ deviceOwnerOrganization, deviceOwnerPackage));
} else {
- return mContext.getString(R.string.monitoring_description_device_owned,
- deviceOwner);
+ message.append(mContext.getString(R.string.monitoring_description_do_header_generic,
+ deviceOwnerPackage));
}
+ message.append("\n\n");
+ message.append(mContext.getString(R.string.monitoring_description_do_body));
+ if (primaryVpn != null) {
+ message.append("\n\n");
+ message.append(mContext.getString(R.string.monitoring_description_do_body_vpn,
+ primaryVpn));
+ }
+ message.append(mContext.getString(
+ R.string.monitoring_description_do_learn_more_separator));
+ message.append(mContext.getString(R.string.monitoring_description_do_learn_more),
+ new EnterprisePrivacySpan(), 0);
+ return message;
} else if (primaryVpn != null) {
if (profileVpn != null) {
return mContext.getString(R.string.monitoring_description_app_personal_work,
- profileOwner, profileVpn, primaryVpn);
+ profileOwnerPackage, profileVpn, primaryVpn);
} else {
if (isBranded) {
return mContext.getString(R.string.branded_monitoring_description_app_personal,
@@ -197,10 +254,10 @@
}
} else if (profileVpn != null) {
return mContext.getString(R.string.monitoring_description_app_work,
- profileOwner, profileVpn);
- } else if (profileOwner != null && primaryUserIsManaged) {
+ profileOwnerPackage, profileVpn);
+ } else if (profileOwnerPackage != null && hasProfileOwner) {
return mContext.getString(R.string.monitoring_description_device_owned,
- profileOwner);
+ profileOwnerPackage);
} else {
// No device owner, no personal VPN, no work VPN, no user owner. Why are we here?
return null;
@@ -219,17 +276,19 @@
@Override
public void run() {
mFooterIcon.setImageResource(mFooterIconId);
+ mFooterIcon2.setImageResource(mFooterIcon2Id);
}
};
private final Runnable mUpdateDisplayState = new Runnable() {
@Override
public void run() {
- if (mFooterTextId != 0) {
- mFooterText.setText(mFooterTextId);
+ if (mFooterTextContent != null) {
+ mFooterText.setText(mFooterTextContent);
}
mRootView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
mFooterIcon.setVisibility(mIsIconVisible ? View.VISIBLE : View.INVISIBLE);
+ mFooterIcon2.setVisibility(mIsIcon2Visible ? View.VISIBLE : View.INVISIBLE);
}
};
@@ -267,4 +326,18 @@
}
}
+ protected class EnterprisePrivacySpan extends ClickableSpan {
+ @Override
+ public void onClick(View widget) {
+ final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mDialog.dismiss();
+ mContext.startActivity(intent);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ return object instanceof EnterprisePrivacySpan;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index e55ff70..d8855c8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -179,7 +179,7 @@
mHost = host;
mHost.addCallback(this);
setTiles(mHost.getTiles());
- mFooter.setHost(host);
+ mFooter.setHostEnvironment(host, host.getSecurityController(), host.getLooper());
mCustomizePanel = customizer;
if (mCustomizePanel != null) {
mCustomizePanel.setHost(mHost);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 4341d17..f73241c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -474,10 +474,19 @@
public Drawable getDrawable(Context context) {
return mDrawable;
}
+ }
+
+ public static class DrawableIconWithRes extends DrawableIcon {
+ private final int mId;
+
+ public DrawableIconWithRes(Drawable drawable, int id) {
+ super(drawable);
+ mId = id;
+ }
@Override
- public Drawable getInvisibleDrawable(Context context) {
- return mDrawable;
+ public boolean equals(Object o) {
+ return o instanceof DrawableIconWithRes && ((DrawableIconWithRes) o).mId == mId;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 28530d7..1fcb45b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -17,11 +17,14 @@
import android.app.ActivityManager;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
@@ -63,6 +66,7 @@
private final IQSTileService mService;
private final TileServiceManager mServiceManager;
private final int mUser;
+ private Context mAppContext;
private android.graphics.drawable.Icon mDefaultIcon;
private boolean mListening;
@@ -80,6 +84,10 @@
mService = mServiceManager.getTileService();
mServiceManager.setTileChangeListener(this);
mUser = ActivityManager.getCurrentUser();
+ try {
+ mAppContext = mContext.createPackageContext(mComponent.getPackageName(), 0);
+ } catch (NameNotFoundException e) {
+ }
}
private void setTileIcon() {
@@ -283,16 +291,20 @@
tileState = Tile.STATE_UNAVAILABLE;
}
Drawable drawable;
+ boolean mHasRes = false;
+ android.graphics.drawable.Icon icon = mTile.getIcon();
try {
- drawable = mTile.getIcon().loadDrawable(mContext);
+ drawable = icon.loadDrawable(mAppContext);
+ mHasRes = icon.getType() == android.graphics.drawable.Icon.TYPE_RESOURCE;
} catch (Exception e) {
Log.w(TAG, "Invalid icon, forcing into unavailable state");
tileState = Tile.STATE_UNAVAILABLE;
- drawable = mDefaultIcon.loadDrawable(mContext);
+ drawable = mDefaultIcon.loadDrawable(mAppContext);
}
int color = mContext.getColor(getColor(tileState));
drawable.setTint(color);
- state.icon = new DrawableIcon(drawable);
+ state.icon = mHasRes ? new DrawableIconWithRes(drawable, icon.getResId())
+ : new DrawableIcon(drawable);
state.label = mTile.getLabel();
if (tileState == Tile.STATE_UNAVAILABLE) {
state.label = new SpannableStringBuilder().append(state.label,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 7655e6c..790f3f6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -438,9 +438,9 @@
SystemServicesProxy ssp = Recents.getSystemServices();
ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
boolean screenPinningActive = ssp.isScreenPinningActive();
- boolean isRunningTaskInHomeStack = runningTask != null &&
- SystemServicesProxy.isHomeStack(runningTask.stackId);
- if (runningTask != null && !isRunningTaskInHomeStack && !screenPinningActive) {
+ boolean isRunningTaskInHomeOrRecentsStack = runningTask != null &&
+ ActivityManager.StackId.isHomeOrRecentsStack(runningTask.stackId);
+ if (runningTask != null && !isRunningTaskInHomeOrRecentsStack && !screenPinningActive) {
logDockAttempt(mContext, runningTask.topActivity, runningTask.resizeMode);
if (runningTask.isDockable) {
if (metricsDockAction != -1) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index af1823c..d5a6a58 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -399,7 +399,7 @@
RecentsActivityLaunchState launchState = config.getLaunchState();
if (!loadPlan.hasTasks()) {
loader.preloadTasks(loadPlan, launchState.launchedToTaskId,
- !launchState.launchedFromHome);
+ !launchState.launchedFromHome && !launchState.launchedViaDockGesture);
}
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
@@ -526,12 +526,14 @@
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
- // Workaround for b/22542869, if the RecentsActivity is started again, but without going
- // through SystemUI, we need to reset the config launch flags to ensure that we do not
- // wait on the system to send a signal that was never queued.
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
- launchState.reset();
+ if (!isChangingConfigurations()) {
+ // Workaround for b/22542869, if the RecentsActivity is started again, but without going
+ // through SystemUI, we need to reset the config launch flags to ensure that we do not
+ // wait on the system to send a signal that was never queued.
+ RecentsConfiguration config = Recents.getConfiguration();
+ RecentsActivityLaunchState launchState = config.getLaunchState();
+ launchState.reset();
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index abde44e..c9c4f2b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -18,6 +18,8 @@
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
+import static android.app.ActivityManager.StackId.isHomeOrRecentsStack;
import static android.view.View.MeasureSpec;
import android.app.ActivityManager;
@@ -460,8 +462,8 @@
// Return early if there is no running task (can't determine affiliated tasks in this case)
ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
if (runningTask == null) return;
- // Return early if the running task is in the home stack (optimization)
- if (SystemServicesProxy.isHomeStack(runningTask.stackId)) return;
+ // Return early if the running task is in the home/recents stack (optimization)
+ if (isHomeOrRecentsStack(runningTask.stackId)) return;
// Find the task in the recents list
ArrayList<Task> tasks = focusedStack.getStackTasks();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index cf75c4f..002515d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -27,6 +27,7 @@
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
+import android.os.Binder;
import android.os.RemoteException;
import android.util.DisplayMetrics;
import android.view.Gravity;
@@ -106,6 +107,7 @@
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
,
PixelFormat.TRANSLUCENT);
+ lp.token = new Binder();
lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
lp.setTitle("ScreenPinningConfirmation");
lp.gravity = Gravity.FILL;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 2272a72..ea50d89 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -321,7 +321,7 @@
// Remove home/recents/excluded tasks
int minNumTasksToQuery = 10;
int numTasksToQuery = Math.max(minNumTasksToQuery, numLatestTasks);
- int flags = ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS |
+ int flags = ActivityManager.RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS |
ActivityManager.RECENT_INGORE_DOCKED_STACK_TOP_TASK |
ActivityManager.RECENT_INGORE_PINNED_STACK_TASKS |
ActivityManager.RECENT_IGNORE_UNAVAILABLE |
@@ -399,21 +399,23 @@
if (mIam == null) return false;
try {
- ActivityManager.StackInfo stackInfo = mIam.getStackInfo(
+ ActivityManager.StackInfo homeStackInfo = mIam.getStackInfo(
ActivityManager.StackId.HOME_STACK_ID);
ActivityManager.StackInfo fullscreenStackInfo = mIam.getStackInfo(
ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID);
- ComponentName topActivity = stackInfo.topActivity;
- boolean homeStackVisibleNotOccluded = stackInfo.visible;
- if (fullscreenStackInfo != null) {
- boolean isFullscreenStackOccludingHome = fullscreenStackInfo.visible &&
- fullscreenStackInfo.position > stackInfo.position;
- homeStackVisibleNotOccluded &= !isFullscreenStackOccludingHome;
- }
+ ActivityManager.StackInfo recentsStackInfo = mIam.getStackInfo(
+ ActivityManager.StackId.RECENTS_STACK_ID);
+
+ boolean homeStackVisibleNotOccluded = isStackNotOccluded(homeStackInfo,
+ fullscreenStackInfo);
+ boolean recentsStackVisibleNotOccluded = isStackNotOccluded(recentsStackInfo,
+ fullscreenStackInfo);
if (isHomeStackVisible != null) {
isHomeStackVisible.value = homeStackVisibleNotOccluded;
}
- return (homeStackVisibleNotOccluded && topActivity != null
+ ComponentName topActivity = recentsStackInfo != null ?
+ recentsStackInfo.topActivity : null;
+ return (recentsStackVisibleNotOccluded && topActivity != null
&& topActivity.getPackageName().equals(RecentsImpl.RECENTS_PACKAGE)
&& Recents.RECENTS_ACTIVITIES.contains(topActivity.getClassName()));
} catch (RemoteException e) {
@@ -422,6 +424,17 @@
return false;
}
+ private boolean isStackNotOccluded(ActivityManager.StackInfo stackInfo,
+ ActivityManager.StackInfo fullscreenStackInfo) {
+ boolean stackVisibleNotOccluded = stackInfo == null || stackInfo.visible;
+ if (fullscreenStackInfo != null && stackInfo != null) {
+ boolean isFullscreenStackOccludingg = fullscreenStackInfo.visible &&
+ fullscreenStackInfo.position > stackInfo.position;
+ stackVisibleNotOccluded &= !isFullscreenStackOccludingg;
+ }
+ return stackVisibleNotOccluded;
+ }
+
/**
* Returns whether this device has freeform workspaces.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
index 3db03d0..cb9453b 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.graphics.PixelFormat;
+import android.os.Binder;
import android.view.View;
import android.view.WindowManager;
@@ -51,6 +52,7 @@
FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL
| FLAG_WATCH_OUTSIDE_TOUCH | FLAG_SPLIT_TOUCH | FLAG_SLIPPERY,
PixelFormat.TRANSLUCENT);
+ mLp.token = new Binder();
mLp.setTitle(WINDOW_TITLE);
mLp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index d46d267..cf8d332 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -103,7 +103,7 @@
private boolean mDimmed;
private boolean mDark;
- private int mBgTint = 0;
+ private int mBgTint = NO_COLOR;
private float mBgAlpha = 1f;
/**
@@ -507,8 +507,10 @@
* Sets the tint color of the background
*/
public void setTintColor(int color, boolean animated) {
- mBgTint = color;
- updateBackgroundTint(animated);
+ if (color != mBgTint) {
+ mBgTint = color;
+ updateBackgroundTint(animated);
+ }
}
/**
@@ -567,13 +569,15 @@
}
private void setBackgroundTintColor(int color) {
- mCurrentBackgroundTint = color;
- if (color == mNormalColor) {
- // We don't need to tint a normal notification
- color = 0;
+ if (color != mCurrentBackgroundTint) {
+ mCurrentBackgroundTint = color;
+ if (color == mNormalColor) {
+ // We don't need to tint a normal notification
+ color = 0;
+ }
+ mBackgroundDimmed.setTint(color);
+ mBackgroundNormal.setTint(color);
}
- mBackgroundDimmed.setTint(color);
- mBackgroundNormal.setTint(color);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 661cc3c..e89fe55 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -193,7 +193,7 @@
private View mChildAfterViewWhenDismissed;
private View mGroupParentWhenDismissed;
private boolean mRefocusOnDismiss;
- private float mIconTransformationAmount;
+ private float mContentTransformationAmount;
private boolean mIconsVisible = true;
private boolean mAboveShelf;
private boolean mIsLastChild;
@@ -837,23 +837,29 @@
/**
* Set how much this notification is transformed into an icon.
*
- * @param iconTransformationAmount A value from 0 to 1 indicating how much we are transformed
- * to an icon
+ * @param contentTransformationAmount A value from 0 to 1 indicating how much we are transformed
+ * to the content away
* @param isLastChild is this the last child in the list. If true, then the transformation is
* different since it's content fades out.
*/
- public void setIconTransformationAmount(float iconTransformationAmount, boolean isLastChild) {
+ public void setContentTransformationAmount(float contentTransformationAmount,
+ boolean isLastChild) {
boolean changeTransformation = isLastChild != mIsLastChild;
- changeTransformation |= mIconTransformationAmount != iconTransformationAmount;
+ changeTransformation |= mContentTransformationAmount != contentTransformationAmount;
mIsLastChild = isLastChild;
- mIconTransformationAmount = iconTransformationAmount;
+ mContentTransformationAmount = contentTransformationAmount;
if (changeTransformation) {
updateContentTransformation();
- boolean iconsVisible = mIconTransformationAmount == 0.0f;
- if (iconsVisible != mIconsVisible) {
- mIconsVisible = iconsVisible;
- updateIconVisibilities();
- }
+ }
+ }
+
+ /**
+ * Set the icons to be visible of this notification.
+ */
+ public void setIconsVisible(boolean iconsVisible) {
+ if (iconsVisible != mIconsVisible) {
+ mIconsVisible = iconsVisible;
+ updateIconVisibilities();
}
}
@@ -864,9 +870,9 @@
private void updateContentTransformation() {
float contentAlpha;
- float translationY = - mIconTransformationAmount * mIconTransformContentShift;
+ float translationY = -mContentTransformationAmount * mIconTransformContentShift;
if (mIsLastChild) {
- contentAlpha = 1.0f - mIconTransformationAmount;
+ contentAlpha = 1.0f - mContentTransformationAmount;
contentAlpha = Math.min(contentAlpha / 0.5f, 1.0f);
contentAlpha = Interpolators.ALPHA_OUT.getInterpolation(contentAlpha);
translationY *= 0.4f;
@@ -885,7 +891,9 @@
}
private void updateIconVisibilities() {
- boolean visible = isChildInGroup() || isBelowSpeedBump() || mIconsVisible;
+ boolean visible = isChildInGroup()
+ || (isBelowSpeedBump() && !NotificationShelf.SHOW_AMBIENT_ICONS)
+ || mIconsVisible;
mPublicLayout.setIconsVisible(visible);
mPrivateLayout.setIconsVisible(visible);
if (mChildrenContainer != null) {
@@ -1679,13 +1687,17 @@
@Override
public void setClipBottomAmount(int clipBottomAmount) {
- super.setClipBottomAmount(clipBottomAmount);
- mPrivateLayout.setClipBottomAmount(clipBottomAmount);
- mPublicLayout.setClipBottomAmount(clipBottomAmount);
- if (mGuts != null) {
- mGuts.setClipBottomAmount(clipBottomAmount);
+ if (clipBottomAmount != mClipBottomAmount) {
+ super.setClipBottomAmount(clipBottomAmount);
+ mPrivateLayout.setClipBottomAmount(clipBottomAmount);
+ mPublicLayout.setClipBottomAmount(clipBottomAmount);
+ if (mGuts != null) {
+ mGuts.setClipBottomAmount(clipBottomAmount);
+ }
}
if (mChildrenContainer != null) {
+ // We have to update this even if it hasn't changed, since the children locations can
+ // have changed
mChildrenContainer.setClipBottomAmount(clipBottomAmount);
}
}
@@ -1871,8 +1883,8 @@
}
@Override
- protected void onYTranslationAnimationFinished() {
- super.onYTranslationAnimationFinished();
+ protected void onYTranslationAnimationFinished(View view) {
+ super.onYTranslationAnimationFinished(view);
if (mHeadsupDisappearRunning) {
setHeadsUpAnimatingAway(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 3687f6d..a6e730d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -208,6 +208,13 @@
expandedIcon = null;
throw new IconException("Couldn't create icon: " + ic);
}
+ expandedIcon.setVisibility(View.INVISIBLE);
+ expandedIcon.setOnVisibilityChangedListener(
+ newVisibility -> {
+ if (row != null) {
+ row.setIconsVisible(newVisibility != View.VISIBLE);
+ }
+ });
}
public void setIconTag(int key, Object tag) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 680562a..e054bbe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.res.Configuration;
+import android.os.SystemProperties;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
@@ -33,9 +34,7 @@
import com.android.systemui.statusbar.stack.ExpandableViewState;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.StackScrollState;
-
-import java.util.ArrayList;
-import java.util.WeakHashMap;
+import com.android.systemui.statusbar.stack.ViewState;
/**
* A notification shelf view that is placed inside the notification scroller. It manages the
@@ -43,10 +42,12 @@
*/
public class NotificationShelf extends ActivatableNotificationView {
+ public static final boolean SHOW_AMBIENT_ICONS = true;
+ private static final boolean USE_ANIMATIONS_WHEN_OPENING =
+ SystemProperties.getBoolean("debug.icon_opening_animations", true);
private ViewInvertHelper mViewInvertHelper;
private boolean mDark;
private NotificationIconContainer mShelfIcons;
- private ArrayList<StatusBarIconView> mIcons = new ArrayList<>();
private ShelfState mShelfState;
private int[] mTmp = new int[2];
private boolean mHideBackground;
@@ -60,6 +61,7 @@
private int mNotGoneIndex;
private boolean mHasItemsInStableShelf;
private NotificationIconContainer mCollapsedIcons;
+ private int mScrollFastThreshold;
public NotificationShelf(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -101,6 +103,8 @@
setLayoutParams(layoutParams);
int padding = getResources().getDimensionPixelOffset(R.dimen.shelf_icon_container_padding);
mShelfIcons.setPadding(padding, 0, padding, 0);
+ mScrollFastThreshold = getResources().getDimensionPixelOffset(
+ R.dimen.scroll_fast_threshold);
}
@Override
@@ -162,6 +166,7 @@
mShelfState.notGoneIndex = Math.min(mShelfState.notGoneIndex, mNotGoneIndex);
}
mShelfState.hasItemsInStableShelf = lastViewState.inShelf;
+ mShelfState.hidden = !mAmbientState.isShadeExpanded();
} else {
mShelfState.hidden = true;
mShelfState.location = ExpandableViewState.LOCATION_GONE;
@@ -174,15 +179,15 @@
* the icons from the notification area into the shelf.
*/
public void updateAppearance() {
- WeakHashMap<View, NotificationIconContainer.IconState> iconStates =
- mShelfIcons.resetViewStates();
+ mShelfIcons.resetViewStates();
+ float shelfStart = getTranslationY();
float numViewsInShelf = 0.0f;
View lastChild = mAmbientState.getLastVisibleBackgroundChild();
mNotGoneIndex = -1;
float interpolationStart = mMaxLayoutHeight - getIntrinsicHeight() * 2;
float expandAmount = 0.0f;
- if (getTranslationY() >= interpolationStart) {
- expandAmount = (getTranslationY() - interpolationStart) / getIntrinsicHeight();
+ if (shelfStart >= interpolationStart) {
+ expandAmount = (shelfStart - interpolationStart) / getIntrinsicHeight();
expandAmount = Math.min(1.0f, expandAmount);
}
// find the first view that doesn't overlap with the shelf
@@ -196,6 +201,12 @@
int colorTwoBefore = NO_COLOR;
int previousColor = NO_COLOR;
float transitionAmount = 0.0f;
+ boolean scrollingFast = mAmbientState.getCurrentScrollVelocity() > mScrollFastThreshold
+ || (mAmbientState.isExpansionChanging()
+ && Math.abs(mAmbientState.getExpandingVelocity()) > mScrollFastThreshold);
+ boolean expandingAnimated = mAmbientState.isExpansionChanging()
+ && !mAmbientState.isPanelTracking();
+ int baseZHeight = mAmbientState.getBaseZHeight();
while (notificationIndex < mHostLayout.getChildCount()) {
ExpandableView child = (ExpandableView) mHostLayout.getChildAt(notificationIndex);
notificationIndex++;
@@ -204,30 +215,28 @@
continue;
}
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- StatusBarIconView icon = row.getEntry().expandedIcon;
- NotificationIconContainer.IconState iconState = iconStates.get(icon);
float notificationClipEnd;
- float shelfStart = getTranslationY();
- boolean aboveShelf = row.getTranslationZ() > mAmbientState.getBaseZHeight();
+ boolean aboveShelf = row.getTranslationZ() > baseZHeight;
boolean isLastChild = child == lastChild;
+ float rowTranslationY = row.getTranslationY();
if (isLastChild || aboveShelf || backgroundForceHidden) {
notificationClipEnd = shelfStart + getIntrinsicHeight();
} else {
notificationClipEnd = shelfStart - mPaddingBetweenElements;
- float height = notificationClipEnd - row.getTranslationY();
+ float height = notificationClipEnd - rowTranslationY;
if (!row.isBelowSpeedBump() && height <= getNotificationMergeSize()) {
// We want the gap to close when we reached the minimum size and only shrink
// before
notificationClipEnd = Math.min(shelfStart,
- row.getTranslationY() + getNotificationMergeSize());
+ rowTranslationY + getNotificationMergeSize());
}
}
updateNotificationClipHeight(row, notificationClipEnd);
- float inShelfAmount = updateIconAppearance(row, iconState, icon, expandAmount,
- isLastChild);
+ float inShelfAmount = updateIconAppearance(row, expandAmount, scrollingFast,
+ expandingAnimated, isLastChild);
numViewsInShelf += inShelfAmount;
int ownColorUntinted = row.getBackgroundColorWithoutTint();
- if (row.getTranslationY() >= getTranslationY() && mNotGoneIndex == -1) {
+ if (rowTranslationY >= shelfStart && mNotGoneIndex == -1) {
mNotGoneIndex = notGoneIndex;
setTintColor(previousColor);
setOverrideTintColor(colorTwoBefore, transitionAmount);
@@ -248,11 +257,9 @@
notGoneIndex++;
previousColor = ownColorUntinted;
}
+ mShelfIcons.setSpeedBumpIndex(mAmbientState.getSpeedBumpIndex());
mShelfIcons.calculateIconTranslations();
mShelfIcons.applyIconStates();
- setVisibility(numViewsInShelf != 0.0f && mAmbientState.isShadeExpanded()
- ? VISIBLE
- : INVISIBLE);
boolean hideBackground = numViewsInShelf < 1.0f;
setHideBackground(hideBackground || backgroundForceHidden);
if (mNotGoneIndex == -1) {
@@ -275,41 +282,116 @@
/**
* @return the icon amount how much this notification is in the shelf;
*/
- private float updateIconAppearance(ExpandableNotificationRow row,
- NotificationIconContainer.IconState iconState, StatusBarIconView icon,
- float expandAmount, boolean isLastChild) {
+ private float updateIconAppearance(ExpandableNotificationRow row, float expandAmount,
+ boolean scrollingFast, boolean expandingAnimated, boolean isLastChild) {
// Let calculate how much the view is in the shelf
float viewStart = row.getTranslationY();
- int transformHeight = row.getActualHeight() + mPaddingBetweenElements;
+ int fullHeight = row.getActualHeight() + mPaddingBetweenElements;
+ float iconTransformDistance = getIntrinsicHeight() * 1.5f;
if (isLastChild) {
- transformHeight =
- Math.min(transformHeight, row.getMinHeight() - getIntrinsicHeight());
+ fullHeight = Math.min(fullHeight, row.getMinHeight() - getIntrinsicHeight());
+ iconTransformDistance = Math.min(iconTransformDistance, row.getMinHeight()
+ - getIntrinsicHeight());
}
- float viewEnd = viewStart + transformHeight;
- float iconAppearAmount;
- float yTranslation;
- float alpha = 1.0f;
- if (viewEnd >= getTranslationY() && (mAmbientState.isShadeExpanded()
+ float viewEnd = viewStart + fullHeight;
+ float fullTransitionAmount;
+ float iconTransitionAmount;
+ float shelfStart = getTranslationY();
+ if (viewEnd >= shelfStart && (mAmbientState.isShadeExpanded()
|| (!row.isPinned() && !row.isHeadsUpAnimatingAway()))) {
- if (viewStart < getTranslationY()) {
- float linearAmount = (getTranslationY() - viewStart) / transformHeight;
+ if (viewStart < shelfStart) {
+
+ float fullAmount = (shelfStart - viewStart) / fullHeight;
float interpolatedAmount = Interpolators.ACCELERATE_DECELERATE.getInterpolation(
- linearAmount);
+ fullAmount);
interpolatedAmount = NotificationUtils.interpolate(
- interpolatedAmount, linearAmount, expandAmount);
- iconAppearAmount = 1.0f - interpolatedAmount;
+ interpolatedAmount, fullAmount, expandAmount);
+ fullTransitionAmount = 1.0f - interpolatedAmount;
+
+ iconTransitionAmount = (shelfStart - viewStart) / iconTransformDistance;
+ iconTransitionAmount = Math.min(1.0f, iconTransitionAmount);
+ iconTransitionAmount = 1.0f - iconTransitionAmount;
+
} else {
- iconAppearAmount = 1.0f;
+ fullTransitionAmount = 1.0f;
+ iconTransitionAmount = 1.0f;
}
} else {
- iconAppearAmount = 0.0f;
+ fullTransitionAmount = 0.0f;
+ iconTransitionAmount = 0.0f;
}
+ updateIconPositioning(row, iconTransitionAmount, fullTransitionAmount, scrollingFast,
+ expandingAnimated, isLastChild);
+ return fullTransitionAmount;
+ }
- // Lets now calculate how much of the transformation has already happened. This is different
- // from the above, since we only start transforming when the view is already quite a bit
- // pushed in.
+ private void updateIconPositioning(ExpandableNotificationRow row, float iconTransitionAmount,
+ float fullTransitionAmount, boolean scrollingFast, boolean expandingAnimated,
+ boolean isLastChild) {
+ StatusBarIconView icon = row.getEntry().expandedIcon;
+ NotificationIconContainer.IconState iconState = getIconState(icon);
+ if (iconState == null) {
+ return;
+ }
+ float clampedAmount = iconTransitionAmount > 0.5f ? 1.0f : 0.0f;
+ if (clampedAmount == iconTransitionAmount) {
+ iconState.keepClampedPosition = false;
+ }
+ if (clampedAmount == fullTransitionAmount) {
+ iconState.useFullTransitionAmount = fullTransitionAmount == 0.0f || scrollingFast
+ || expandingAnimated;
+ iconState.translateContent = mMaxLayoutHeight - getTranslationY()
+ - getIntrinsicHeight() > 0;
+ }
+ if (scrollingFast || (expandingAnimated && iconState.useFullTransitionAmount
+ && !ViewState.isAnimatingY(icon))) {
+ iconState.cancelAnimations(icon);
+ iconState.useFullTransitionAmount = true;
+ }
+ float transitionAmount;
+ boolean needCannedAnimation = iconState.clampedAppearAmount == 1.0f
+ && clampedAmount == 0.0f;
+ if (isLastChild || !USE_ANIMATIONS_WHEN_OPENING || iconState.useFullTransitionAmount) {
+ transitionAmount = iconTransitionAmount;
+ } else if (iconState.keepClampedPosition
+ && iconState.clampedAppearAmount != clampedAmount) {
+ // We animated to the clamped amount but then decided to go the other way. Let's
+ // animate it to the new position
+ transitionAmount = iconTransitionAmount;
+ iconState.needsCannedAnimation = true;
+ iconState.keepClampedPosition = false;
+ } else if (needCannedAnimation || iconState.keepClampedPosition
+ || iconState.iconAppearAmount == 1.0f) {
+ // We need to perform a canned animation since we crossed the treshhold
+ transitionAmount = clampedAmount;
+ iconState.keepClampedPosition = iconState.keepClampedPosition || needCannedAnimation;
+ iconState.needsCannedAnimation = needCannedAnimation;
+ } else {
+ transitionAmount = iconTransitionAmount;
+ }
+ iconState.iconAppearAmount = !USE_ANIMATIONS_WHEN_OPENING
+ || iconState.useFullTransitionAmount
+ ? fullTransitionAmount
+ : transitionAmount;
+ iconState.clampedAppearAmount = clampedAmount;
+ setIconTransformationAmount(row, transitionAmount);
+ float contentTransformationAmount = isLastChild || iconState.translateContent
+ ? iconTransitionAmount
+ : 0.0f;
+ row.setContentTransformationAmount(contentTransformationAmount, isLastChild);
+ }
+
+ private boolean isLastChild(ExpandableNotificationRow row) {
+ return row == mAmbientState.getLastVisibleBackgroundChild();
+ }
+
+ private void setIconTransformationAmount(ExpandableNotificationRow row,
+ float transitionAmount) {
+ StatusBarIconView icon = row.getEntry().expandedIcon;
+ NotificationIconContainer.IconState iconState = getIconState(icon);
+
View rowIcon = row.getNotificationIcon();
- float notificationIconPosition = viewStart;
+ float notificationIconPosition = row.getTranslationY();
float notificationIconSize = 0.0f;
int iconTopPadding;
if (rowIcon != null) {
@@ -322,28 +404,18 @@
float shelfIconPosition = getTranslationY() + icon.getTop();
shelfIconPosition += ((1.0f - icon.getIconScale()) * icon.getHeight()) / 2.0f;
float transitionDistance = getIntrinsicHeight() * 1.5f;
- if (isLastChild) {
+ if (row == mAmbientState.getLastVisibleBackgroundChild()) {
transitionDistance = Math.min(transitionDistance, row.getMinHeight()
- getIntrinsicHeight());
}
float transformationStartPosition = getTranslationY() - transitionDistance;
- float transitionAmount = 0.0f;
- if (viewStart < transformationStartPosition
- || (!mAmbientState.isShadeExpanded()
- && (row.isPinned() || row.isHeadsUpAnimatingAway()))) {
- // We simply place it on the icon of the notification
- yTranslation = notificationIconPosition - shelfIconPosition;
- } else {
- transitionAmount = (viewStart - transformationStartPosition)
- / transitionDistance;
- float startPosition = transformationStartPosition + iconTopPadding;
- yTranslation = NotificationUtils.interpolate(
- startPosition - shelfIconPosition, 0, transitionAmount);
- // If we are merging into the shelf, lets make sure the shelf is at least on our height,
- // otherwise the icons won't be visible.
- setTranslationZ(Math.max(getTranslationZ(), row.getTranslationZ()));
- }
+ float iconYTranslation = NotificationUtils.interpolate(
+ Math.min(notificationIconPosition, transformationStartPosition + iconTopPadding)
+ - shelfIconPosition,
+ 0,
+ transitionAmount);
float shelfIconSize = icon.getHeight() * icon.getIconScale();
+ float alpha = 1.0f;
if (!row.isShowingIcon()) {
// The view currently doesn't have an icon, lets transform it in!
alpha = transitionAmount;
@@ -352,15 +424,12 @@
// The notification size is different from the size in the shelf / statusbar
float newSize = NotificationUtils.interpolate(notificationIconSize, shelfIconSize,
transitionAmount);
- row.setIconTransformationAmount(transitionAmount, isLastChild);
if (iconState != null) {
iconState.scaleX = newSize / icon.getHeight() / icon.getIconScale();
iconState.scaleY = iconState.scaleX;
iconState.hidden = transitionAmount == 0.0f;
- iconState.iconAppearAmount = iconAppearAmount;
iconState.alpha = alpha;
- iconState.yTranslation = yTranslation;
- icon.setVisibility(transitionAmount == 0.0f ? INVISIBLE : VISIBLE);
+ iconState.yTranslation = iconYTranslation;
if (row.isInShelf() && !row.isTransformingIntoShelf()) {
iconState.iconAppearAmount = 1.0f;
iconState.alpha = 1.0f;
@@ -368,8 +437,14 @@
iconState.scaleY = 1.0f;
iconState.hidden = false;
}
+ if (row.isAboveShelf()) {
+ iconState.hidden = true;
+ }
}
- return iconAppearAmount;
+ }
+
+ private NotificationIconContainer.IconState getIconState(StatusBarIconView icon) {
+ return mShelfIcons.getIconState(icon);
}
private float getFullyClosedTranslation() {
@@ -386,9 +461,11 @@
}
private void setHideBackground(boolean hideBackground) {
- mHideBackground = hideBackground;
- updateBackground();
- updateOutline();
+ if (mHideBackground != hideBackground) {
+ mHideBackground = hideBackground;
+ updateBackground();
+ updateOutline();
+ }
}
public boolean hidesBackground() {
@@ -415,13 +492,23 @@
mShelfIcons.getWidth(),
openedAmount);
mShelfIcons.setActualLayoutWidth(width);
- float padding = NotificationUtils.interpolate(mCollapsedIcons.getPaddingEnd(),
+ boolean hasOverflow = mCollapsedIcons.hasOverflow();
+ int collapsedPadding = mCollapsedIcons.getPaddingEnd();
+ if (!hasOverflow) {
+ // we have to ensure that adding the low priority notification won't lead to an
+ // overflow
+ collapsedPadding -= (1.0f + NotificationIconContainer.OVERFLOW_EARLY_AMOUNT)
+ * mCollapsedIcons.getIconSize();
+ }
+ float padding = NotificationUtils.interpolate(collapsedPadding,
mShelfIcons.getPaddingEnd(),
openedAmount);
mShelfIcons.setActualPaddingEnd(padding);
float paddingStart = NotificationUtils.interpolate(start,
mShelfIcons.getPaddingStart(), openedAmount);
mShelfIcons.setActualPaddingStart(paddingStart);
+ mShelfIcons.setOpenedAmount(openedAmount);
+ mShelfIcons.setVisualOverflowAdaption(mCollapsedIcons.getVisualOverflowAdaption());
}
public void setMaxLayoutHeight(int maxLayoutHeight) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
index bfa43fd..dba7130 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
@@ -42,7 +42,6 @@
private float mViewAlpha = 1.0f;
private ValueAnimator mAlphaAnimator;
private Rect mExcludedRect = new Rect();
- private int mLeftInset = 0;
private boolean mHasExcludedArea;
private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener
= new ValueAnimator.AnimatorUpdateListener() {
@@ -88,12 +87,12 @@
if (mExcludedRect.top > 0) {
canvas.drawRect(0, 0, getWidth(), mExcludedRect.top, mPaint);
}
- if (mExcludedRect.left + mLeftInset > 0) {
- canvas.drawRect(0, mExcludedRect.top, mExcludedRect.left + mLeftInset,
- mExcludedRect.bottom, mPaint);
+ if (mExcludedRect.left > 0) {
+ canvas.drawRect(0, mExcludedRect.top, mExcludedRect.left, mExcludedRect.bottom,
+ mPaint);
}
- if (mExcludedRect.right + mLeftInset < getWidth()) {
- canvas.drawRect(mExcludedRect.right + mLeftInset,
+ if (mExcludedRect.right < getWidth()) {
+ canvas.drawRect(mExcludedRect.right,
mExcludedRect.top,
getWidth(),
mExcludedRect.bottom,
@@ -184,14 +183,4 @@
public void setChangeRunnable(Runnable changeRunnable) {
mChangeRunnable = changeRunnable;
}
-
- public void setLeftInset(int leftInset) {
- if (mLeftInset != leftInset) {
- mLeftInset = leftInset;
-
- if (mHasExcludedArea) {
- invalidate();
- }
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index d635bb0..a2c2fd7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -37,6 +37,7 @@
import android.util.Log;
import android.util.Property;
import android.util.TypedValue;
+import android.view.View;
import android.view.ViewDebug;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.Interpolator;
@@ -102,6 +103,7 @@
private ObjectAnimator mIconAppearAnimator;
private ObjectAnimator mDotAnimator;
private float mDotAppearAmount;
+ private OnVisibilityChangedListener mOnVisibilityChangedListener;
public StatusBarIconView(Context context, String slot, Notification notification) {
this(context, slot, notification, false);
@@ -453,6 +455,7 @@
}
public void setVisibleState(int visibleState, boolean animate, Runnable endRunnable) {
+ boolean runnableAdded = false;
if (visibleState != mVisibleState) {
mVisibleState = visibleState;
if (animate) {
@@ -465,20 +468,22 @@
targetAmount = 1.0f;
interpolator = Interpolators.LINEAR_OUT_SLOW_IN;
}
- mIconAppearAnimator = ObjectAnimator.ofFloat(this, ICON_APPEAR_AMOUNT,
- targetAmount);
- mIconAppearAnimator.setInterpolator(interpolator);
- mIconAppearAnimator.setDuration(100);
- mIconAppearAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mIconAppearAnimator = null;
- if (endRunnable != null) {
- endRunnable.run();
+ float currentAmount = getIconAppearAmount();
+ if (targetAmount != currentAmount) {
+ mIconAppearAnimator = ObjectAnimator.ofFloat(this, ICON_APPEAR_AMOUNT,
+ currentAmount, targetAmount);
+ mIconAppearAnimator.setInterpolator(interpolator);
+ mIconAppearAnimator.setDuration(100);
+ mIconAppearAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mIconAppearAnimator = null;
+ runRunnable(endRunnable);
}
- }
- });
- mIconAppearAnimator.start();
+ });
+ mIconAppearAnimator.start();
+ runnableAdded = true;
+ }
if (mDotAnimator != null) {
mDotAnimator.cancel();
@@ -489,22 +494,41 @@
targetAmount = 1.0f;
interpolator = Interpolators.LINEAR_OUT_SLOW_IN;
}
- mDotAnimator = ObjectAnimator.ofFloat(this, DOT_APPEAR_AMOUNT,
- targetAmount);
- mDotAnimator.setInterpolator(interpolator);
- mDotAnimator.setDuration(100);
- mDotAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mDotAnimator = null;
- }
- });
- mDotAnimator.start();
+ currentAmount = getDotAppearAmount();
+ if (targetAmount != currentAmount) {
+ mDotAnimator = ObjectAnimator.ofFloat(this, DOT_APPEAR_AMOUNT,
+ currentAmount, targetAmount);
+ mDotAnimator.setInterpolator(interpolator);
+ mDotAnimator.setDuration(100);
+ final boolean runRunnable = !runnableAdded;
+ mDotAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mDotAnimator = null;
+ if (runRunnable) {
+ runRunnable(endRunnable);
+ }
+ }
+ });
+ mDotAnimator.start();
+ runnableAdded = true;
+ }
} else {
setIconAppearAmount(visibleState == STATE_ICON ? 1.0f : 0.0f);
- setDotAppearAmount(visibleState == STATE_DOT ? 1.0f : 0.0f);
+ setDotAppearAmount(visibleState == STATE_DOT ? 1.0f
+ : visibleState == STATE_ICON ? 2.0f
+ : 0.0f);
}
}
+ if (!runnableAdded) {
+ runRunnable(endRunnable);
+ }
+ }
+
+ private void runRunnable(Runnable runnable) {
+ if (runnable != null) {
+ runnable.run();
+ }
}
public void setIconAppearAmount(float iconAppearAmount) {
@@ -525,7 +549,23 @@
invalidate();
}
+ @Override
+ public void setVisibility(int visibility) {
+ super.setVisibility(visibility);
+ if (mOnVisibilityChangedListener != null) {
+ mOnVisibilityChangedListener.onVisibilityChanged(visibility);
+ }
+ }
+
public float getDotAppearAmount() {
return mDotAppearAmount;
}
+
+ public void setOnVisibilityChangedListener(OnVisibilityChangedListener listener) {
+ mOnVisibilityChangedListener = listener;
+ }
+
+ public interface OnVisibilityChangedListener {
+ void onVisibilityChanged(int newVisibility);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index f6fe176..2bc2665 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -18,6 +18,7 @@
import android.view.View;
import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
+import com.android.systemui.statusbar.policy.KeyButtonDrawable;
import java.util.ArrayList;
@@ -36,10 +37,11 @@
private View.OnLongClickListener mLongClickListener;
private Boolean mLongClickable;
private Integer mAlpha;
+ private Float mDarkIntensity;
private Integer mVisibility = -1;
- private int mImageResource = -1;
- private Drawable mImageDrawable;
+ private KeyButtonDrawable mImageDrawable;
private View mCurrentView;
+ private boolean mVertical;
public ButtonDispatcher(int id) {
mId = id;
@@ -49,13 +51,6 @@
mViews.clear();
}
- void addView(View view, boolean landscape) {
- addView(view);
- if (view instanceof ButtonInterface) {
- ((ButtonInterface) view).setLandscape(landscape);
- }
- }
-
void addView(View view) {
mViews.add(view);
view.setOnClickListener(mClickListener);
@@ -67,14 +62,19 @@
if (mAlpha != null) {
view.setAlpha(mAlpha);
}
+ if (mDarkIntensity != null) {
+ ((ButtonInterface) view).setDarkIntensity(mDarkIntensity);
+ }
if (mVisibility != null) {
view.setVisibility(mVisibility);
}
- if (mImageResource > 0) {
- ((ButtonInterface) view).setImageResource(mImageResource);
- } else if (mImageDrawable != null) {
+ if (mImageDrawable != null) {
((ButtonInterface) view).setImageDrawable(mImageDrawable);
}
+
+ if (view instanceof ButtonInterface) {
+ ((ButtonInterface) view).setVertical(mVertical);
+ }
}
public int getId() {
@@ -89,24 +89,14 @@
return mAlpha != null ? mAlpha : 1;
}
- public void setImageDrawable(Drawable drawable) {
+ public void setImageDrawable(KeyButtonDrawable drawable) {
mImageDrawable = drawable;
- mImageResource = -1;
final int N = mViews.size();
for (int i = 0; i < N; i++) {
((ButtonInterface) mViews.get(i)).setImageDrawable(mImageDrawable);
}
}
- public void setImageResource(int resource) {
- mImageResource = resource;
- mImageDrawable = null;
- final int N = mViews.size();
- for (int i = 0; i < N; i++) {
- ((ButtonInterface) mViews.get(i)).setImageResource(mImageResource);
- }
- }
-
public void setVisibility(int visibility) {
if (mVisibility == visibility) return;
mVisibility = visibility;
@@ -132,6 +122,14 @@
}
}
+ public void setDarkIntensity(float darkIntensity) {
+ mDarkIntensity = darkIntensity;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ ((ButtonInterface) mViews.get(i)).setDarkIntensity(darkIntensity);
+ }
+ }
+
public void setOnClickListener(View.OnClickListener clickListener) {
mClickListener = clickListener;
final int N = mViews.size();
@@ -186,4 +184,14 @@
}
}
+ public void setVertical(boolean vertical) {
+ mVertical = vertical;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ final View view = mViews.get(i);
+ if (view instanceof ButtonInterface) {
+ ((ButtonInterface) view).setVertical(vertical);
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index daa57c6..a2c106a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -32,6 +32,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
+import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
@@ -143,6 +144,7 @@
private boolean mLeftIsVoiceAssist;
private AssistManager mAssistManager;
+ private Drawable mLeftAssistIcon;
private IntentButton mRightButton = new DefaultRightButton();
private IntentButton mLeftButton = new DefaultLeftButton();
@@ -348,6 +350,14 @@
? View.VISIBLE : View.GONE);
}
+ /**
+ * Set an alternate icon for the left assist affordance (replace the mic icon)
+ */
+ public void setLeftAssistIcon(Drawable drawable) {
+ mLeftAssistIcon = drawable;
+ updateLeftAffordanceIcon();
+ }
+
private void updateLeftAffordanceIcon() {
IconState state = mLeftButton.getIcon();
mLeftAffordanceView.setVisibility(state.isVisible ? View.VISIBLE : View.GONE);
@@ -814,7 +824,11 @@
mLeftIsVoiceAssist = canLaunchVoiceAssist();
if (mLeftIsVoiceAssist) {
mIconState.isVisible = mUserSetupComplete;
- mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp);
+ if (mLeftAssistIcon == null) {
+ mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp);
+ } else {
+ mIconState.drawable = mLeftAssistIcon;
+ }
mIconState.contentDescription = mContext.getString(
R.string.accessibility_voice_assist_button);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
new file mode 100644
index 0000000..b5358a1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.graphics.Rect;
+import android.view.View;
+
+import com.android.systemui.statusbar.policy.BatteryController;
+
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
+
+/**
+ * Controls how light status bar flag applies to the icons.
+ */
+public class LightBarController implements BatteryController.BatteryStateChangeCallback {
+
+ private static final float NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD = 0.1f;
+
+ private final StatusBarIconController mStatusBarIconController;
+ private final BatteryController mBatteryController;
+ private FingerprintUnlockController mFingerprintUnlockController;
+ private final NavigationBarView mNavigationBarView;
+
+ private int mSystemUiVisibility;
+ private int mFullscreenStackVisibility;
+ private int mDockedStackVisibility;
+ private boolean mFullscreenLight;
+ private boolean mDockedLight;
+ private int mLastStatusBarMode;
+ private int mLastNavigationBarMode;
+ private boolean mNavigationLight;
+ private float mScrimAlpha;
+
+ private final Rect mLastFullscreenBounds = new Rect();
+ private final Rect mLastDockedBounds = new Rect();
+
+ public LightBarController(StatusBarIconController statusBarIconController,
+ NavigationBarView navigationBarView,
+ BatteryController batteryController) {
+ mStatusBarIconController = statusBarIconController;
+ mNavigationBarView = navigationBarView;
+ mBatteryController = batteryController;
+ batteryController.addCallback(this);
+ }
+
+ public void setFingerprintUnlockController(
+ FingerprintUnlockController fingerprintUnlockController) {
+ mFingerprintUnlockController = fingerprintUnlockController;
+ }
+
+ public void onSystemUiVisibilityChanged(int vis, int fullscreenStackVis, int dockedStackVis,
+ int mask, Rect fullscreenStackBounds, Rect dockedStackBounds, boolean sbModeChanged,
+ int statusBarMode, boolean nbModeChanged, int navigationBarMode) {
+ int oldFullscreen = mFullscreenStackVisibility;
+ int newFullscreen = (oldFullscreen & ~mask) | (fullscreenStackVis & mask);
+ int diffFullscreen = newFullscreen ^ oldFullscreen;
+ int oldDocked = mDockedStackVisibility;
+ int newDocked = (oldDocked & ~mask) | (dockedStackVis & mask);
+ int diffDocked = newDocked ^ oldDocked;
+ if ((diffFullscreen & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
+ || (diffDocked & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
+ || sbModeChanged
+ || !mLastFullscreenBounds.equals(fullscreenStackBounds)
+ || !mLastDockedBounds.equals(dockedStackBounds)) {
+
+ mFullscreenLight = isLight(newFullscreen, statusBarMode,
+ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+ mDockedLight = isLight(newDocked, statusBarMode, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+ updateStatus(fullscreenStackBounds, dockedStackBounds);
+ }
+
+ int oldVis = mSystemUiVisibility;
+ int newVis = (oldVis & ~mask) | (vis & mask);
+ int diffVis = newVis ^ oldVis;
+ if ((diffVis & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) != 0
+ || nbModeChanged) {
+ boolean last = mNavigationLight;
+ mNavigationLight = isNavigationLight(newVis, navigationBarMode);
+ if (mNavigationLight != last) {
+ updateNavigation();
+ }
+ }
+ mFullscreenStackVisibility = newFullscreen;
+ mDockedStackVisibility = newDocked;
+ mSystemUiVisibility = newVis;
+ mLastStatusBarMode = statusBarMode;
+ mLastNavigationBarMode = navigationBarMode;
+ mLastFullscreenBounds.set(fullscreenStackBounds);
+ mLastDockedBounds.set(dockedStackBounds);
+ }
+
+ private void reevaluate() {
+ onSystemUiVisibilityChanged(mSystemUiVisibility, mFullscreenStackVisibility,
+ mDockedStackVisibility, 0 /* mask */, mLastFullscreenBounds, mLastDockedBounds,
+ true /* sbModeChange*/, mLastStatusBarMode, true /* nbModeChange*/,
+ mLastNavigationBarMode);
+ }
+
+ public void setScrimAlpha(float alpha) {
+ mScrimAlpha = alpha;
+ reevaluate();
+ }
+
+ private boolean isNavigationLight(int vis, int barMode) {
+ return isLight(vis, barMode, View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR)
+ && mScrimAlpha < NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD;
+ }
+
+ private boolean isLight(int vis, int barMode, int flag) {
+ boolean isTransparentBar = (barMode == MODE_TRANSPARENT
+ || barMode == MODE_LIGHTS_OUT_TRANSPARENT);
+ boolean allowLight = isTransparentBar && !mBatteryController.isPowerSave();
+ boolean light = (vis & flag) != 0;
+ return allowLight && light;
+ }
+
+ private boolean animateChange() {
+ if (mFingerprintUnlockController == null) {
+ return false;
+ }
+ int unlockMode = mFingerprintUnlockController.getMode();
+ return unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
+ && unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
+ }
+
+ private void updateStatus(Rect fullscreenStackBounds, Rect dockedStackBounds) {
+ boolean hasDockedStack = !dockedStackBounds.isEmpty();
+
+ // If both are light or fullscreen is light and there is no docked stack, all icons get
+ // dark.
+ if ((mFullscreenLight && mDockedLight) || (mFullscreenLight && !hasDockedStack)) {
+ mStatusBarIconController.setIconsDarkArea(null);
+ mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
+
+ }
+
+ // If no one is light or the fullscreen is not light and there is no docked stack,
+ // all icons become white.
+ else if ((!mFullscreenLight && !mDockedLight) || (!mFullscreenLight && !hasDockedStack)) {
+ mStatusBarIconController.getTransitionsController().setIconsDark(
+ false, animateChange());
+ }
+
+ // Not the same for every stack, magic!
+ else {
+ Rect bounds = mFullscreenLight ? fullscreenStackBounds : dockedStackBounds;
+ if (bounds.isEmpty()) {
+ mStatusBarIconController.setIconsDarkArea(null);
+ } else {
+ mStatusBarIconController.setIconsDarkArea(bounds);
+ }
+ mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
+ }
+ }
+
+ private void updateNavigation() {
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().setIconsDark(
+ mNavigationLight, animateChange());
+ }
+ }
+
+ @Override
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+
+ }
+
+ @Override
+ public void onPowerSaveChanged(boolean isPowerSave) {
+ reevaluate();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
new file mode 100644
index 0000000..1d4d2d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.animation.ValueAnimator;
+import android.os.Handler;
+import android.os.SystemClock;
+
+import com.android.systemui.Interpolators;
+
+/**
+ * Class to control all aspects about light bar changes.
+ */
+public class LightBarTransitionsController {
+
+ public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
+
+ private final Handler mHandler;
+ private final DarkIntensityApplier mApplier;
+
+ private boolean mTransitionDeferring;
+ private long mTransitionDeferringStartTime;
+ private long mTransitionDeferringDuration;
+ private boolean mTransitionPending;
+ private boolean mTintChangePending;
+ private float mPendingDarkIntensity;
+ private ValueAnimator mTintAnimator;
+ private float mDarkIntensity;
+
+ private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mTransitionDeferring = false;
+ }
+ };
+
+ public LightBarTransitionsController(DarkIntensityApplier applier) {
+ mApplier = applier;
+ mHandler = new Handler();
+ }
+
+ public void appTransitionPending() {
+ mTransitionPending = true;
+ }
+
+ public void appTransitionCancelled() {
+ if (mTransitionPending && mTintChangePending) {
+ mTintChangePending = false;
+ animateIconTint(mPendingDarkIntensity, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
+ }
+ mTransitionPending = false;
+ }
+
+ public void appTransitionStarting(long startTime, long duration) {
+ if (mTransitionPending && mTintChangePending) {
+ mTintChangePending = false;
+ animateIconTint(mPendingDarkIntensity,
+ Math.max(0, startTime - SystemClock.uptimeMillis()),
+ duration);
+
+ } else if (mTransitionPending) {
+
+ // If we don't have a pending tint change yet, the change might come in the future until
+ // startTime is reached.
+ mTransitionDeferring = true;
+ mTransitionDeferringStartTime = startTime;
+ mTransitionDeferringDuration = duration;
+ mHandler.removeCallbacks(mTransitionDeferringDoneRunnable);
+ mHandler.postAtTime(mTransitionDeferringDoneRunnable, startTime);
+ }
+ mTransitionPending = false;
+ }
+
+ public void setIconsDark(boolean dark, boolean animate) {
+ if (!animate) {
+ setIconTintInternal(dark ? 1.0f : 0.0f);
+ } else if (mTransitionPending) {
+ deferIconTintChange(dark ? 1.0f : 0.0f);
+ } else if (mTransitionDeferring) {
+ animateIconTint(dark ? 1.0f : 0.0f,
+ Math.max(0, mTransitionDeferringStartTime - SystemClock.uptimeMillis()),
+ mTransitionDeferringDuration);
+ } else {
+ animateIconTint(dark ? 1.0f : 0.0f, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
+ }
+ }
+
+ public float getCurrentDarkIntensity() {
+ return mDarkIntensity;
+ }
+
+ private void deferIconTintChange(float darkIntensity) {
+ if (mTintChangePending && darkIntensity == mPendingDarkIntensity) {
+ return;
+ }
+ mTintChangePending = true;
+ mPendingDarkIntensity = darkIntensity;
+ }
+
+ private void animateIconTint(float targetDarkIntensity, long delay,
+ long duration) {
+ if (mTintAnimator != null) {
+ mTintAnimator.cancel();
+ }
+ if (mDarkIntensity == targetDarkIntensity) {
+ return;
+ }
+ mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
+ mTintAnimator.addUpdateListener(
+ animation -> setIconTintInternal((Float) animation.getAnimatedValue()));
+ mTintAnimator.setDuration(duration);
+ mTintAnimator.setStartDelay(delay);
+ mTintAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mTintAnimator.start();
+ }
+
+ private void setIconTintInternal(float darkIntensity) {
+ mDarkIntensity = darkIntensity;
+ mApplier.applyDarkIntensity(darkIntensity);
+ }
+
+ /**
+ * Interface to apply a specific dark intensity.
+ */
+ public interface DarkIntensityApplier {
+ void applyDarkIntensity(float darkIntensity);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightStatusBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightStatusBarController.java
deleted file mode 100644
index dd7f3cc..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightStatusBarController.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.graphics.Rect;
-import android.view.View;
-
-import com.android.systemui.statusbar.policy.BatteryController;
-
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
-
-/**
- * Controls how light status bar flag applies to the icons.
- */
-public class LightStatusBarController implements BatteryController.BatteryStateChangeCallback {
-
- private final StatusBarIconController mIconController;
- private final BatteryController mBatteryController;
- private FingerprintUnlockController mFingerprintUnlockController;
-
- private int mFullscreenStackVisibility;
- private int mDockedStackVisibility;
- private boolean mFullscreenLight;
- private boolean mDockedLight;
- private int mLastStatusBarMode;
-
- private final Rect mLastFullscreenBounds = new Rect();
- private final Rect mLastDockedBounds = new Rect();
-
- public LightStatusBarController(StatusBarIconController iconController,
- BatteryController batteryController) {
- mIconController = iconController;
- mBatteryController = batteryController;
- batteryController.addCallback(this);
- }
-
- public void setFingerprintUnlockController(
- FingerprintUnlockController fingerprintUnlockController) {
- mFingerprintUnlockController = fingerprintUnlockController;
- }
-
- public void onSystemUiVisibilityChanged(int fullscreenStackVis, int dockedStackVis, int mask,
- Rect fullscreenStackBounds, Rect dockedStackBounds, boolean sbModeChanged,
- int statusBarMode) {
- int oldFullscreen = mFullscreenStackVisibility;
- int newFullscreen = (oldFullscreen & ~mask) | (fullscreenStackVis & mask);
- int diffFullscreen = newFullscreen ^ oldFullscreen;
- int oldDocked = mDockedStackVisibility;
- int newDocked = (oldDocked & ~mask) | (dockedStackVis & mask);
- int diffDocked = newDocked ^ oldDocked;
- if ((diffFullscreen & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
- || (diffDocked & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
- || sbModeChanged
- || !mLastFullscreenBounds.equals(fullscreenStackBounds)
- || !mLastDockedBounds.equals(dockedStackBounds)) {
-
- mFullscreenLight = isLight(newFullscreen, statusBarMode);
- mDockedLight = isLight(newDocked, statusBarMode);
- update(fullscreenStackBounds, dockedStackBounds);
- }
- mFullscreenStackVisibility = newFullscreen;
- mDockedStackVisibility = newDocked;
- mLastStatusBarMode = statusBarMode;
- mLastFullscreenBounds.set(fullscreenStackBounds);
- mLastDockedBounds.set(dockedStackBounds);
- }
-
- private boolean isLight(int vis, int statusBarMode) {
- boolean isTransparentBar = (statusBarMode == MODE_TRANSPARENT
- || statusBarMode == MODE_LIGHTS_OUT_TRANSPARENT);
- boolean allowLight = isTransparentBar && !mBatteryController.isPowerSave();
- boolean light = (vis & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0;
- return allowLight && light;
- }
-
- private boolean animateChange() {
- if (mFingerprintUnlockController == null) {
- return false;
- }
- int unlockMode = mFingerprintUnlockController.getMode();
- return unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
- && unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
- }
-
- private void update(Rect fullscreenStackBounds, Rect dockedStackBounds) {
- boolean hasDockedStack = !dockedStackBounds.isEmpty();
-
- // If both are light or fullscreen is light and there is no docked stack, all icons get
- // dark.
- if ((mFullscreenLight && mDockedLight) || (mFullscreenLight && !hasDockedStack)) {
- mIconController.setIconsDarkArea(null);
- mIconController.setIconsDark(true, animateChange());
-
- }
-
- // If no one is light or the fullscreen is not light and there is no docked stack,
- // all icons become white.
- else if ((!mFullscreenLight && !mDockedLight) || (!mFullscreenLight && !hasDockedStack)) {
- mIconController.setIconsDark(false, animateChange());
-
- }
-
- // Not the same for every stack, magic!
- else {
- Rect bounds = mFullscreenLight ? fullscreenStackBounds : dockedStackBounds;
- if (bounds.isEmpty()) {
- mIconController.setIconsDarkArea(null);
- } else {
- mIconController.setIconsDarkArea(bounds);
- }
- mIconController.setIconsDark(true, animateChange());
- }
- }
-
- @Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
-
- }
-
- @Override
- public void onPowerSaveChanged(boolean isPowerSave) {
- onSystemUiVisibilityChanged(mFullscreenStackVisibility, mDockedStackVisibility,
- 0 /* mask */, mLastFullscreenBounds, mLastDockedBounds, true /* sbModeChange*/,
- mLastStatusBarMode);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
index 1a46815..4969a1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
@@ -14,134 +14,16 @@
package com.android.systemui.statusbar.phone;
-import android.app.ActivityManager;
-import android.app.StatusBarManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.UserInfo;
-import android.os.UserHandle;
-import android.os.UserManager;
-
import com.android.systemui.statusbar.phone.ManagedProfileController.Callback;
import com.android.systemui.statusbar.policy.CallbackController;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
+public interface ManagedProfileController extends CallbackController<Callback> {
-public class ManagedProfileController implements CallbackController<Callback> {
+ void setWorkModeEnabled(boolean enabled);
- private final List<Callback> mCallbacks = new ArrayList<>();
+ boolean hasActiveProfile();
- private final Context mContext;
- private final UserManager mUserManager;
- private final LinkedList<UserInfo> mProfiles;
- private boolean mListening;
- private int mCurrentUser;
-
- public ManagedProfileController(QSTileHost host) {
- mContext = host.getContext();
- mUserManager = UserManager.get(mContext);
- mProfiles = new LinkedList<UserInfo>();
- }
-
- public void addCallback(Callback callback) {
- mCallbacks.add(callback);
- if (mCallbacks.size() == 1) {
- setListening(true);
- }
- callback.onManagedProfileChanged();
- }
-
- public void removeCallback(Callback callback) {
- if (mCallbacks.remove(callback) && mCallbacks.size() == 0) {
- setListening(false);
- }
- }
-
- public void setWorkModeEnabled(boolean enableWorkMode) {
- synchronized (mProfiles) {
- for (UserInfo ui : mProfiles) {
- if (enableWorkMode) {
- if (!mUserManager.trySetQuietModeDisabled(ui.id, null)) {
- StatusBarManager statusBarManager = (StatusBarManager) mContext
- .getSystemService(android.app.Service.STATUS_BAR_SERVICE);
- statusBarManager.collapsePanels();
- }
- } else {
- mUserManager.setQuietModeEnabled(ui.id, true);
- }
- }
- }
- }
-
- private void reloadManagedProfiles() {
- synchronized (mProfiles) {
- boolean hadProfile = mProfiles.size() > 0;
- int user = ActivityManager.getCurrentUser();
- mProfiles.clear();
-
- for (UserInfo ui : mUserManager.getEnabledProfiles(user)) {
- if (ui.isManagedProfile()) {
- mProfiles.add(ui);
- }
- }
- if (mProfiles.size() == 0 && hadProfile && (user == mCurrentUser)) {
- for (Callback callback : mCallbacks) {
- callback.onManagedProfileRemoved();
- }
- }
- mCurrentUser = user;
- }
- }
-
- public boolean hasActiveProfile() {
- if (!mListening) reloadManagedProfiles();
- synchronized (mProfiles) {
- return mProfiles.size() > 0;
- }
- }
-
- public boolean isWorkModeEnabled() {
- if (!mListening) reloadManagedProfiles();
- synchronized (mProfiles) {
- for (UserInfo ui : mProfiles) {
- if (ui.isQuietModeEnabled()) {
- return false;
- }
- }
- return true;
- }
- }
-
- private void setListening(boolean listening) {
- mListening = listening;
- if (listening) {
- reloadManagedProfiles();
-
- final IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_USER_SWITCHED);
- filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
- filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
- filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
- filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
- mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
- } else {
- mContext.unregisterReceiver(mReceiver);
- }
- }
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- reloadManagedProfiles();
- for (Callback callback : mCallbacks) {
- callback.onManagedProfileChanged();
- }
- }
- };
+ boolean isWorkModeEnabled();
public interface Callback {
void onManagedProfileChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
new file mode 100644
index 0000000..fc33ace
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.app.ActivityManager;
+import android.app.StatusBarManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+public class ManagedProfileControllerImpl implements ManagedProfileController {
+
+ private final List<Callback> mCallbacks = new ArrayList<>();
+
+ private final Context mContext;
+ private final UserManager mUserManager;
+ private final LinkedList<UserInfo> mProfiles;
+ private boolean mListening;
+ private int mCurrentUser;
+
+ public ManagedProfileControllerImpl(QSTileHost host) {
+ mContext = host.getContext();
+ mUserManager = UserManager.get(mContext);
+ mProfiles = new LinkedList<UserInfo>();
+ }
+
+ public void addCallback(Callback callback) {
+ mCallbacks.add(callback);
+ if (mCallbacks.size() == 1) {
+ setListening(true);
+ }
+ callback.onManagedProfileChanged();
+ }
+
+ public void removeCallback(Callback callback) {
+ if (mCallbacks.remove(callback) && mCallbacks.size() == 0) {
+ setListening(false);
+ }
+ }
+
+ public void setWorkModeEnabled(boolean enableWorkMode) {
+ synchronized (mProfiles) {
+ for (UserInfo ui : mProfiles) {
+ if (enableWorkMode) {
+ if (!mUserManager.trySetQuietModeDisabled(ui.id, null)) {
+ StatusBarManager statusBarManager = (StatusBarManager) mContext
+ .getSystemService(android.app.Service.STATUS_BAR_SERVICE);
+ statusBarManager.collapsePanels();
+ }
+ } else {
+ mUserManager.setQuietModeEnabled(ui.id, true);
+ }
+ }
+ }
+ }
+
+ private void reloadManagedProfiles() {
+ synchronized (mProfiles) {
+ boolean hadProfile = mProfiles.size() > 0;
+ int user = ActivityManager.getCurrentUser();
+ mProfiles.clear();
+
+ for (UserInfo ui : mUserManager.getEnabledProfiles(user)) {
+ if (ui.isManagedProfile()) {
+ mProfiles.add(ui);
+ }
+ }
+ if (mProfiles.size() == 0 && hadProfile && (user == mCurrentUser)) {
+ for (Callback callback : mCallbacks) {
+ callback.onManagedProfileRemoved();
+ }
+ }
+ mCurrentUser = user;
+ }
+ }
+
+ public boolean hasActiveProfile() {
+ if (!mListening) reloadManagedProfiles();
+ synchronized (mProfiles) {
+ return mProfiles.size() > 0;
+ }
+ }
+
+ public boolean isWorkModeEnabled() {
+ if (!mListening) reloadManagedProfiles();
+ synchronized (mProfiles) {
+ for (UserInfo ui : mProfiles) {
+ if (ui.isQuietModeEnabled()) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ private void setListening(boolean listening) {
+ mListening = listening;
+ if (listening) {
+ reloadManagedProfiles();
+
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
+ mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
+ } else {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ }
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ reloadManagedProfiles();
+ for (Callback callback : mCallbacks) {
+ callback.onManagedProfileChanged();
+ }
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index c420927..b2b093c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -17,12 +17,14 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.util.AttributeSet;
import android.util.SparseArray;
+import android.view.Display;
+import android.view.Display.Mode;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.Space;
@@ -72,12 +74,13 @@
protected FrameLayout mRot0;
protected FrameLayout mRot90;
+ private boolean isRot0Landscape;
private SparseArray<ButtonDispatcher> mButtonDispatchers;
private String mCurrentLayout;
- private View mLastRot0;
- private View mLastRot90;
+ private View mLastPortrait;
+ private View mLastLandscape;
private boolean mAlternativeOrder;
@@ -85,6 +88,10 @@
super(context, attrs);
mDensity = context.getResources().getConfiguration().densityDpi;
createInflaters();
+ Display display = ((WindowManager)
+ context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
+ Mode displayMode = display.getMode();
+ isRot0Landscape = displayMode.getPhysicalWidth() > displayMode.getPhysicalHeight();
}
private void createInflaters() {
@@ -215,17 +222,17 @@
String[] center = sets[1].split(BUTTON_SEPARATOR);
String[] end = sets[2].split(BUTTON_SEPARATOR);
// Inflate these in start to end order or accessibility traversal will be messed up.
- inflateButtons(start, (ViewGroup) mRot0.findViewById(R.id.ends_group), false);
- inflateButtons(start, (ViewGroup) mRot90.findViewById(R.id.ends_group), true);
+ inflateButtons(start, (ViewGroup) mRot0.findViewById(R.id.ends_group), isRot0Landscape);
+ inflateButtons(start, (ViewGroup) mRot90.findViewById(R.id.ends_group), !isRot0Landscape);
- inflateButtons(center, (ViewGroup) mRot0.findViewById(R.id.center_group), false);
- inflateButtons(center, (ViewGroup) mRot90.findViewById(R.id.center_group), true);
+ inflateButtons(center, (ViewGroup) mRot0.findViewById(R.id.center_group), isRot0Landscape);
+ inflateButtons(center, (ViewGroup) mRot90.findViewById(R.id.center_group), !isRot0Landscape);
addGravitySpacer((LinearLayout) mRot0.findViewById(R.id.ends_group));
addGravitySpacer((LinearLayout) mRot90.findViewById(R.id.ends_group));
- inflateButtons(end, (ViewGroup) mRot0.findViewById(R.id.ends_group), false);
- inflateButtons(end, (ViewGroup) mRot90.findViewById(R.id.ends_group), true);
+ inflateButtons(end, (ViewGroup) mRot0.findViewById(R.id.ends_group), isRot0Landscape);
+ inflateButtons(end, (ViewGroup) mRot90.findViewById(R.id.ends_group), !isRot0Landscape);
}
private void addGravitySpacer(LinearLayout layout) {
@@ -234,7 +241,7 @@
private void inflateButtons(String[] buttons, ViewGroup parent, boolean landscape) {
for (int i = 0; i < buttons.length; i++) {
- inflateButton(buttons[i], parent, landscape, i);
+ inflateButton(buttons[i], parent, landscape);
}
}
@@ -247,8 +254,7 @@
}
@Nullable
- protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape,
- int indexInParent) {
+ protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape) {
LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;
float size = extractSize(buttonSpec);
View v = createView(buttonSpec, parent, inflater, landscape);
@@ -259,15 +265,15 @@
params.width = (int) (params.width * size);
}
parent.addView(v);
- addToDispatchers(v, landscape);
- View lastView = landscape ? mLastRot90 : mLastRot0;
+ addToDispatchers(v);
+ View lastView = landscape ? mLastLandscape : mLastPortrait;
if (lastView != null) {
v.setAccessibilityTraversalAfter(lastView.getId());
}
if (landscape) {
- mLastRot90 = v;
+ mLastLandscape = v;
} else {
- mLastRot0 = v;
+ mLastPortrait = v;
}
return v;
}
@@ -283,19 +289,10 @@
}
if (HOME.equals(button)) {
v = inflater.inflate(R.layout.home, parent, false);
- if (landscape && isSw600Dp()) {
- setupLandButton(v);
- }
} else if (BACK.equals(button)) {
v = inflater.inflate(R.layout.back, parent, false);
- if (landscape && isSw600Dp()) {
- setupLandButton(v);
- }
} else if (RECENT.equals(button)) {
v = inflater.inflate(R.layout.recent_apps, parent, false);
- if (landscape && isSw600Dp()) {
- setupLandButton(v);
- }
} else if (MENU_IME.equals(button)) {
v = inflater.inflate(R.layout.menu_ime, parent, false);
} else if (NAVSPACE.equals(button)) {
@@ -348,37 +345,22 @@
return buttonSpec.substring(0, buttonSpec.indexOf(SIZE_MOD_START));
}
- private void addToDispatchers(View v, boolean landscape) {
+ private void addToDispatchers(View v) {
if (mButtonDispatchers != null) {
final int indexOfKey = mButtonDispatchers.indexOfKey(v.getId());
if (indexOfKey >= 0) {
- mButtonDispatchers.valueAt(indexOfKey).addView(v, landscape);
+ mButtonDispatchers.valueAt(indexOfKey).addView(v);
} else if (v instanceof ViewGroup) {
final ViewGroup viewGroup = (ViewGroup)v;
final int N = viewGroup.getChildCount();
for (int i = 0; i < N; i++) {
- addToDispatchers(viewGroup.getChildAt(i), landscape);
+ addToDispatchers(viewGroup.getChildAt(i));
}
}
}
}
- private boolean isSw600Dp() {
- Configuration configuration = mContext.getResources().getConfiguration();
- return (configuration.smallestScreenWidthDp >= 600);
- }
- /**
- * This manually sets the width of sw600dp landscape buttons because despite
- * overriding the configuration from the overridden resources aren't loaded currently.
- */
- private void setupLandButton(View v) {
- Resources res = mContext.getResources();
- v.getLayoutParams().width = res.getDimensionPixelOffset(
- R.dimen.navigation_key_width_sw600dp_land);
- int padding = res.getDimensionPixelOffset(R.dimen.navigation_key_padding_sw600dp_land);
- v.setPadding(padding, v.getPaddingTop(), padding, v.getPaddingBottom());
- }
private void clearViews() {
if (mButtonDispatchers != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 1fe0115..3be5e57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -16,13 +16,11 @@
package com.android.systemui.statusbar.phone;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.os.ServiceManager;
+import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.View;
-import android.view.animation.AccelerateInterpolator;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.R;
@@ -31,6 +29,7 @@
private final NavigationBarView mView;
private final IStatusBarService mBarService;
+ private final LightBarTransitionsController mLightTransitionsController;
private boolean mLightsOut;
@@ -39,6 +38,7 @@
mView = view;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ mLightTransitionsController = new LightBarTransitionsController(this::applyDarkIntensity);
}
public void init() {
@@ -46,6 +46,10 @@
applyMode(getMode(), false /*animate*/, true /*force*/);
}
+ public LightBarTransitionsController getLightTransitionsController() {
+ return mLightTransitionsController;
+ }
+
@Override
protected void onTransition(int oldMode, int newMode, boolean animate) {
super.onTransition(oldMode, newMode, animate);
@@ -81,6 +85,18 @@
}
}
+
+ public void reapplyDarkIntensity() {
+ applyDarkIntensity(mLightTransitionsController.getCurrentDarkIntensity());
+ }
+
+ public void applyDarkIntensity(float darkIntensity) {
+ SparseArray<ButtonDispatcher> buttonDispatchers = mView.getButtonDispatchers();
+ for (int i = buttonDispatchers.size() - 1; i >= 0; i--) {
+ buttonDispatchers.valueAt(i).setDarkIntensity(darkIntensity);
+ }
+ }
+
private final View.OnTouchListener mLightsOutListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent ev) {
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 a0ea9bf..d22f421 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -22,6 +22,7 @@
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
+import android.annotation.DrawableRes;
import android.app.StatusBarManager;
import android.content.Context;
import android.content.res.Configuration;
@@ -34,6 +35,7 @@
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
+import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.IDockedStackListener.Stub;
import android.view.MotionEvent;
@@ -51,8 +53,10 @@
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.plugins.statusbar.phone.NavGesture;
import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
+import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.policy.DeadZone;
+import com.android.systemui.statusbar.policy.KeyButtonDrawable;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -78,14 +82,14 @@
int mDisabledFlags = 0;
int mNavigationIconHints = 0;
- private Drawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
- private Drawable mBackCarModeIcon, mBackLandCarModeIcon;
- private Drawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
- private Drawable mHomeDefaultIcon, mHomeCarModeIcon;
- private Drawable mRecentIcon;
- private Drawable mDockedIcon;
- private Drawable mImeIcon;
- private Drawable mMenuIcon;
+ private KeyButtonDrawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
+ private KeyButtonDrawable mBackCarModeIcon, mBackLandCarModeIcon;
+ private KeyButtonDrawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
+ private KeyButtonDrawable mHomeDefaultIcon, mHomeCarModeIcon;
+ private KeyButtonDrawable mRecentIcon;
+ private KeyButtonDrawable mDockedIcon;
+ private KeyButtonDrawable mImeIcon;
+ private KeyButtonDrawable mMenuIcon;
private GestureHelper mGestureHelper;
private DeadZone mDeadZone;
@@ -217,6 +221,10 @@
return mBarTransitions;
}
+ public LightBarTransitionsController getLightTransitionsController() {
+ return mBarTransitions.getLightTransitionsController();
+ }
+
public void setComponents(RecentsComponent recentsComponent, Divider divider) {
mRecentsComponent = recentsComponent;
mDivider = divider;
@@ -281,29 +289,44 @@
return mButtonDispatchers.get(R.id.ime_switcher);
}
+ public SparseArray<ButtonDispatcher> getButtonDispatchers() {
+ return mButtonDispatchers;
+ }
+
private void updateCarModeIcons(Context ctx) {
- mBackCarModeIcon = ctx.getDrawable(R.drawable.ic_sysbar_back_carmode);
+ mBackCarModeIcon = getDrawable(ctx,
+ R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
mBackLandCarModeIcon = mBackCarModeIcon;
- mBackAltCarModeIcon = ctx.getDrawable(R.drawable.ic_sysbar_back_ime_carmode);
+ mBackAltCarModeIcon = getDrawable(ctx,
+ R.drawable.ic_sysbar_back_ime_carmode, R.drawable.ic_sysbar_back_ime_carmode);
mBackAltLandCarModeIcon = mBackAltCarModeIcon;
- mHomeCarModeIcon = ctx.getDrawable(R.drawable.ic_sysbar_home_carmode);
+ mHomeCarModeIcon = getDrawable(ctx,
+ R.drawable.ic_sysbar_home_carmode, R.drawable.ic_sysbar_home_carmode);
}
private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
if (oldConfig.orientation != newConfig.orientation
|| oldConfig.densityDpi != newConfig.densityDpi) {
- mDockedIcon = ctx.getDrawable(R.drawable.ic_sysbar_docked);
+ mDockedIcon = getDrawable(ctx,
+ R.drawable.ic_sysbar_docked, R.drawable.ic_sysbar_docked_dark);
}
if (oldConfig.densityDpi != newConfig.densityDpi) {
- mBackIcon = ctx.getDrawable(R.drawable.ic_sysbar_back);
+ mBackIcon = getDrawable(ctx, R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_dark);
mBackLandIcon = mBackIcon;
- mBackAltIcon = ctx.getDrawable(R.drawable.ic_sysbar_back_ime);
+ mBackAltIcon = getDrawable(ctx,
+ R.drawable.ic_sysbar_back_ime, R.drawable.ic_sysbar_back_ime_dark);
mBackAltLandIcon = mBackAltIcon;
- mHomeDefaultIcon = ctx.getDrawable(R.drawable.ic_sysbar_home);
- mRecentIcon = ctx.getDrawable(R.drawable.ic_sysbar_recent);
- mMenuIcon = ctx.getDrawable(R.drawable.ic_sysbar_menu);
- mImeIcon = ctx.getDrawable(R.drawable.ic_ime_switcher_default);
+ mHomeDefaultIcon = getDrawable(ctx,
+ R.drawable.ic_sysbar_home, R.drawable.ic_sysbar_home_dark);
+ mRecentIcon = getDrawable(ctx,
+ R.drawable.ic_sysbar_recent, R.drawable.ic_sysbar_recent_dark);
+ mMenuIcon = getDrawable(ctx, R.drawable.ic_sysbar_menu, R.drawable.ic_sysbar_menu_dark);
+
+ Context darkContext = new ContextThemeWrapper(ctx, R.style.DualToneDarkTheme);
+ Context lightContext = new ContextThemeWrapper(ctx, R.style.DualToneLightTheme);
+ mImeIcon = getDrawable(darkContext, lightContext,
+ R.drawable.ic_ime_switcher_default, R.drawable.ic_ime_switcher_default);
if (ALTERNATE_CAR_MODE_UI) {
updateCarModeIcons(ctx);
@@ -311,6 +334,17 @@
}
}
+ private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int lightIcon,
+ @DrawableRes int darkIcon) {
+ return getDrawable(ctx, ctx, lightIcon, darkIcon);
+ }
+
+ private KeyButtonDrawable getDrawable(Context darkContext, Context lightContext,
+ @DrawableRes int lightIcon, @DrawableRes int darkIcon) {
+ return KeyButtonDrawable.create(lightContext.getDrawable(lightIcon),
+ darkContext.getDrawable(darkIcon));
+ }
+
@Override
public void setLayoutDirection(int layoutDirection) {
// Reload all the icons
@@ -328,13 +362,13 @@
setNavigationIconHints(hints, false);
}
- private Drawable getBackIconWithAlt(boolean carMode, boolean landscape) {
+ private KeyButtonDrawable getBackIconWithAlt(boolean carMode, boolean landscape) {
return landscape
? carMode ? mBackAltLandCarModeIcon : mBackAltLandIcon
: carMode ? mBackAltCarModeIcon : mBackAltIcon;
}
- private Drawable getBackIcon(boolean carMode, boolean landscape) {
+ private KeyButtonDrawable getBackIcon(boolean carMode, boolean landscape) {
return landscape
? carMode ? mBackLandCarModeIcon : mBackLandIcon
: carMode ? mBackCarModeIcon : mBackIcon;
@@ -357,7 +391,7 @@
// We have to replace or restore the back and home button icons when exiting or entering
// carmode, respectively. Recents are not available in CarMode in nav bar so change
// to recent icon is not required.
- Drawable backIcon = (backAlt)
+ KeyButtonDrawable backIcon = (backAlt)
? getBackIconWithAlt(mUseCarModeUi, mVertical)
: getBackIcon(mUseCarModeUi, mVertical);
@@ -380,6 +414,8 @@
getMenuButton().setImageDrawable(mMenuIcon);
setDisabledFlags(mDisabledFlags, true);
+
+ mBarTransitions.reapplyDarkIntensity();
}
public void setDisabledFlags(int disabledFlags) {
@@ -565,6 +601,7 @@
private void updateRecentsIcon() {
getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
+ mBarTransitions.reapplyDarkIntensity();
}
public boolean isVertical() {
@@ -590,6 +627,8 @@
updateTaskSwitchHelper();
setNavigationIconHints(mNavigationIconHints, true);
+
+ getHomeButton().setVertical(mVertical);
}
public void onKeyguardOccludedChanged(boolean keyguardOccluded) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index d543f49..345dcbd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -127,9 +127,9 @@
return mPhoneStatusBar.getStatusBarHeight();
}
- protected boolean shouldShowNotification(NotificationData.Entry entry,
- NotificationData notificationData) {
- if (notificationData.isAmbient(entry.key)
+ protected boolean shouldShowNotificationIcon(NotificationData.Entry entry,
+ NotificationData notificationData, boolean showAmbient) {
+ if (notificationData.isAmbient(entry.key) && !showAmbient
&& !NotificationData.showNotificationEvenIfUnprovisioned(entry.notification)) {
return false;
}
@@ -148,8 +148,10 @@
*/
public void updateNotificationIcons(NotificationData notificationData) {
- updateIconsForLayout(notificationData, entry -> entry.icon, mNotificationIcons);
- updateIconsForLayout(notificationData, entry -> entry.expandedIcon, mShelfIcons);
+ updateIconsForLayout(notificationData, entry -> entry.icon, mNotificationIcons,
+ false /* showAmbient */);
+ updateIconsForLayout(notificationData, entry -> entry.expandedIcon, mShelfIcons,
+ NotificationShelf.SHOW_AMBIENT_ICONS);
applyNotificationIconsTint();
ArrayList<NotificationData.Entry> activeNotifications
@@ -173,10 +175,11 @@
* @param notificationData the notification data to look up which notifications are relevant
* @param function A function to look up an icon view based on an entry
* @param hostLayout which layout should be updated
+ * @param showAmbient should ambient notification icons be shown
*/
private void updateIconsForLayout(NotificationData notificationData,
Function<NotificationData.Entry, StatusBarIconView> function,
- NotificationIconContainer hostLayout) {
+ NotificationIconContainer hostLayout, boolean showAmbient) {
ArrayList<StatusBarIconView> toShow = new ArrayList<>(
mNotificationScrollLayout.getChildCount());
@@ -185,7 +188,7 @@
View view = mNotificationScrollLayout.getChildAt(i);
if (view instanceof ExpandableNotificationRow) {
NotificationData.Entry ent = ((ExpandableNotificationRow) view).getEntry();
- if (shouldShowNotification(ent, notificationData)) {
+ if (shouldShowNotificationIcon(ent, notificationData, showAmbient)) {
toShow.add(function.apply(ent));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 03697b8..d323e4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -31,15 +31,23 @@
import com.android.systemui.statusbar.stack.AnimationProperties;
import com.android.systemui.statusbar.stack.ViewState;
-import java.util.WeakHashMap;
+import java.util.HashMap;
/**
* A container for notification icons. It handles overflowing icons properly and positions them
* correctly on the screen.
*/
public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
+ /**
+ * A float value indicating how much before the overflow start the icons should transform into
+ * a dot. A value of 0 means that they are exactly at the end and a value of 1 means it starts
+ * 1 icon width early.
+ */
+ public static final float OVERFLOW_EARLY_AMOUNT = 0.2f;
+ private static final int NO_VALUE = Integer.MIN_VALUE;
private static final String TAG = "NotificationIconContainer";
private static final boolean DEBUG = false;
+ private static final int CANNED_ANIMATION_DURATION = 100;
private static final AnimationProperties DOT_ANIMATION_PROPERTIES = new AnimationProperties() {
private AnimationFilter mAnimationFilter = new AnimationFilter().animateX();
@@ -49,6 +57,26 @@
}
}.setDuration(200);
+ private static final AnimationProperties ICON_ANIMATION_PROPERTIES = new AnimationProperties() {
+ private AnimationFilter mAnimationFilter = new AnimationFilter().animateY().animateAlpha();
+ // TODO: add scale
+
+ @Override
+ public AnimationFilter getAnimationFilter() {
+ return mAnimationFilter;
+ }
+ }.setDuration(CANNED_ANIMATION_DURATION);
+
+ private static final AnimationProperties mTempProperties = new AnimationProperties() {
+ private AnimationFilter mAnimationFilter = new AnimationFilter();
+ // TODO: add scale
+
+ @Override
+ public AnimationFilter getAnimationFilter() {
+ return mAnimationFilter;
+ }
+ }.setDuration(CANNED_ANIMATION_DURATION);
+
private static final AnimationProperties ADD_ICON_PROPERTIES = new AnimationProperties() {
private AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();
@@ -59,14 +87,19 @@
}.setDuration(200).setDelay(50);
private boolean mShowAllIcons = true;
- private WeakHashMap<View, IconState> mIconStates = new WeakHashMap<>();
+ private final HashMap<View, IconState> mIconStates = new HashMap<>();
private int mDotPadding;
private int mStaticDotRadius;
- private int mActualLayoutWidth = -1;
- private float mActualPaddingEnd = -1;
- private float mActualPaddingStart = -1;
+ private int mActualLayoutWidth = NO_VALUE;
+ private float mActualPaddingEnd = NO_VALUE;
+ private float mActualPaddingStart = NO_VALUE;
private boolean mChangingViewPositions;
- private int mAnimationStartIndex = -1;
+ private int mAddAnimationStartIndex = -1;
+ private int mCannedAnimationStartIndex = -1;
+ private int mSpeedBumpIndex = -1;
+ private int mIconSize;
+ private float mOpenedAmount = 0.0f;
+ private float mVisualOverflowAdaption;
public NotificationIconContainer(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -97,6 +130,7 @@
protected void onLayout(boolean changed, int l, int t, int r, int b) {
float centerY = getHeight() / 2.0f;
// we layout all our children on the left at the top
+ mIconSize = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
// We need to layout all children even the GONE ones, such that the heights are
@@ -105,6 +139,9 @@
int height = child.getMeasuredHeight();
int top = (int) (centerY - height / 2.0f);
child.layout(0, top, width, top + height);
+ if (i == 0) {
+ mIconSize = child.getWidth();
+ }
}
if (mShowAllIcons) {
resetViewStates();
@@ -121,7 +158,8 @@
childState.applyToView(child);
}
}
- mAnimationStartIndex = -1;
+ mAddAnimationStartIndex = -1;
+ mCannedAnimationStartIndex = -1;
}
@Override
@@ -133,10 +171,10 @@
int childIndex = indexOfChild(child);
if (childIndex < getChildCount() - 1
&& mIconStates.get(getChildAt(childIndex + 1)).iconAppearAmount > 0.0f) {
- if (mAnimationStartIndex < 0) {
- mAnimationStartIndex = childIndex;
+ if (mAddAnimationStartIndex < 0) {
+ mAddAnimationStartIndex = childIndex;
} else {
- mAnimationStartIndex = Math.min(mAnimationStartIndex, childIndex);
+ mAddAnimationStartIndex = Math.min(mAddAnimationStartIndex, childIndex);
}
}
}
@@ -149,10 +187,10 @@
if (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
&& child.getVisibility() == VISIBLE) {
int animationStartIndex = findFirstViewIndexAfter(icon.getTranslationX());
- if (mAnimationStartIndex < 0) {
- mAnimationStartIndex = animationStartIndex;
+ if (mAddAnimationStartIndex < 0) {
+ mAddAnimationStartIndex = animationStartIndex;
} else {
- mAnimationStartIndex = Math.min(mAnimationStartIndex, animationStartIndex);
+ mAddAnimationStartIndex = Math.min(mAddAnimationStartIndex, animationStartIndex);
}
}
if (!mChangingViewPositions) {
@@ -177,14 +215,13 @@
return getChildCount();
}
- public WeakHashMap<View, IconState> resetViewStates() {
+ public void resetViewStates() {
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
ViewState iconState = mIconStates.get(view);
iconState.initFrom(view);
iconState.alpha = 1.0f;
}
- return mIconStates;
}
/**
@@ -194,42 +231,74 @@
*/
public void calculateIconTranslations() {
float translationX = getActualPaddingStart();
- int overflowingIconIndex = -1;
- int lastTwoIconWidth = 0;
+ int firstOverflowIndex = -1;
int childCount = getChildCount();
+ float layoutEnd = getLayoutEnd();
+ float overflowStart = layoutEnd - mIconSize * (2 + OVERFLOW_EARLY_AMOUNT);
+ boolean hasAmbient = mSpeedBumpIndex != -1 && mSpeedBumpIndex < getChildCount();
+ float visualOverflowStart = 0;
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
IconState iconState = mIconStates.get(view);
iconState.xTranslation = translationX;
- iconState.visibleState = StatusBarIconView.STATE_ICON;
- translationX += iconState.iconAppearAmount * view.getWidth();
- if (translationX > getLayoutEnd()) {
- // we are overflowing it with this icon
- overflowingIconIndex = i - 1;
- lastTwoIconWidth = view.getWidth();
- break;
+ boolean isAmbient = mSpeedBumpIndex != -1 && i >= mSpeedBumpIndex
+ && iconState.iconAppearAmount > 0.0f;
+ boolean noOverflowAfter = i == childCount - 1;
+ if (mOpenedAmount != 0.0f) {
+ noOverflowAfter = noOverflowAfter && !hasAmbient;
}
+ iconState.visibleState = StatusBarIconView.STATE_ICON;
+ if (firstOverflowIndex == -1 && (isAmbient
+ || (translationX >= (noOverflowAfter ? layoutEnd - mIconSize : overflowStart)))) {
+ firstOverflowIndex = noOverflowAfter ? i - 1 : i;
+ int totalDotLength = mStaticDotRadius * 6 + 2 * mDotPadding;
+ visualOverflowStart = overflowStart + mIconSize * (1 + OVERFLOW_EARLY_AMOUNT)
+ - totalDotLength / 2
+ - mIconSize * 0.5f + mStaticDotRadius;
+ if (isAmbient) {
+ visualOverflowStart = Math.min(translationX, visualOverflowStart
+ + mStaticDotRadius * 2 + mDotPadding);
+ } else {
+ visualOverflowStart += (translationX - overflowStart) / mIconSize
+ * (mStaticDotRadius * 2 + mDotPadding);
+ }
+ if (mShowAllIcons) {
+ // We want to perfectly position the overflow in the static state, such that
+ // it's perfectly centered instead of measuring it from the end.
+ mVisualOverflowAdaption = 0;
+ if (firstOverflowIndex != -1) {
+ View firstOverflowView = getChildAt(i);
+ IconState overflowState = mIconStates.get(firstOverflowView);
+ float totalAmount = layoutEnd - overflowState.xTranslation;
+ float newPosition = overflowState.xTranslation + totalAmount / 2
+ - totalDotLength / 2
+ - mIconSize * 0.5f + mStaticDotRadius;
+ mVisualOverflowAdaption = newPosition - visualOverflowStart;
+ visualOverflowStart = newPosition;
+ }
+ } else {
+ visualOverflowStart += mVisualOverflowAdaption * (1f - mOpenedAmount);
+ }
+ }
+ translationX += iconState.iconAppearAmount * view.getWidth();
}
- if (overflowingIconIndex != -1) {
+ if (firstOverflowIndex != -1) {
int numDots = 1;
- View overflowIcon = getChildAt(overflowingIconIndex);
- IconState overflowState = mIconStates.get(overflowIcon);
- lastTwoIconWidth += overflowIcon.getWidth();
- int dotWidth = mStaticDotRadius * 2 + mDotPadding;
- int totalDotLength = mStaticDotRadius * 6 + 2 * mDotPadding;
- translationX = (getLayoutEnd() - lastTwoIconWidth / 2 - totalDotLength / 2)
- - overflowIcon.getWidth() * 0.3f + mStaticDotRadius;
- float overflowStart = getLayoutEnd() - lastTwoIconWidth;
- float overlapAmount = (overflowState.xTranslation - overflowStart)
- / overflowIcon.getWidth();
- translationX += overlapAmount * dotWidth;
- for (int i = overflowingIconIndex; i < childCount; i++) {
+ translationX = visualOverflowStart;
+ for (int i = firstOverflowIndex; i < childCount; i++) {
View view = getChildAt(i);
IconState iconState = mIconStates.get(view);
+ int dotWidth = mStaticDotRadius * 2 + mDotPadding;
iconState.xTranslation = translationX;
if (numDots <= 3) {
- iconState.visibleState = StatusBarIconView.STATE_DOT;
- translationX += numDots == 3 ? 3 * dotWidth : dotWidth;
+ if (numDots == 1 && iconState.iconAppearAmount < 0.8f) {
+ iconState.visibleState = StatusBarIconView.STATE_ICON;
+ numDots--;
+ } else {
+ iconState.visibleState = StatusBarIconView.STATE_DOT;
+ }
+ translationX += (numDots == 3 ? 3 * dotWidth : dotWidth)
+ * iconState.iconAppearAmount;
} else {
iconState.visibleState = StatusBarIconView.STATE_HIDDEN;
}
@@ -250,14 +319,14 @@
}
private float getActualPaddingEnd() {
- if (mActualPaddingEnd < 0) {
+ if (mActualPaddingEnd == NO_VALUE) {
return getPaddingEnd();
}
return mActualPaddingEnd;
}
private float getActualPaddingStart() {
- if (mActualPaddingStart < 0) {
+ if (mActualPaddingStart == NO_VALUE) {
return getPaddingStart();
}
return mActualPaddingStart;
@@ -295,7 +364,7 @@
}
public int getActualWidth() {
- if (mActualLayoutWidth < 0) {
+ if (mActualLayoutWidth == NO_VALUE) {
return getWidth();
}
return mActualLayoutWidth;
@@ -305,28 +374,90 @@
mChangingViewPositions = changingViewPositions;
}
+ public IconState getIconState(StatusBarIconView icon) {
+ return mIconStates.get(icon);
+ }
+
+ public void setSpeedBumpIndex(int speedBumpIndex) {
+ mSpeedBumpIndex = speedBumpIndex;
+ }
+
+ public void setOpenedAmount(float expandAmount) {
+ mOpenedAmount = expandAmount;
+ }
+
+ public float getVisualOverflowAdaption() {
+ return mVisualOverflowAdaption;
+ }
+
+ public void setVisualOverflowAdaption(float visualOverflowAdaption) {
+ mVisualOverflowAdaption = visualOverflowAdaption;
+ }
+
+ public boolean hasOverflow() {
+ float width = (getChildCount() + OVERFLOW_EARLY_AMOUNT) * mIconSize;
+ return width - (getWidth() - getActualPaddingStart() - getActualPaddingEnd()) > 0;
+ }
+
+ public int getIconSize() {
+ return mIconSize;
+ }
+
public class IconState extends ViewState {
public float iconAppearAmount = 1.0f;
+ public float clampedAppearAmount = 1.0f;
public int visibleState;
public boolean justAdded = true;
+ public boolean needsCannedAnimation;
+ public boolean keepClampedPosition;
+ public boolean useFullTransitionAmount;
+ public boolean translateContent;
@Override
public void applyToView(View view) {
if (view instanceof StatusBarIconView) {
StatusBarIconView icon = (StatusBarIconView) view;
- AnimationProperties animationProperties = DOT_ANIMATION_PROPERTIES;
+ boolean animate = false;
+ AnimationProperties animationProperties = null;
if (justAdded) {
super.applyToView(icon);
icon.setAlpha(0.0f);
icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, false /* animate */);
animationProperties = ADD_ICON_PROPERTIES;
+ animate = true;
+ } else if (visibleState != icon.getVisibleState()) {
+ animationProperties = DOT_ANIMATION_PROPERTIES;
+ animate = true;
}
- boolean animate = visibleState != icon.getVisibleState() || justAdded;
- if (!animate && mAnimationStartIndex >= 0
+ if (!animate && mAddAnimationStartIndex >= 0
+ && indexOfChild(view) >= mAddAnimationStartIndex
&& (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
|| visibleState != StatusBarIconView.STATE_HIDDEN)) {
- int viewIndex = indexOfChild(view);
- animate = viewIndex >= mAnimationStartIndex;
+ animationProperties = DOT_ANIMATION_PROPERTIES;
+ animate = true;
+ }
+ if (needsCannedAnimation) {
+ AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
+ animationFilter.reset();
+ animationFilter.combineFilter(ICON_ANIMATION_PROPERTIES.getAnimationFilter());
+ if (animationProperties != null) {
+ animationFilter.combineFilter(animationProperties.getAnimationFilter());
+ }
+ animationProperties = mTempProperties;
+ animationProperties.setDuration(CANNED_ANIMATION_DURATION);
+ animate = true;
+ mCannedAnimationStartIndex = indexOfChild(view);
+ }
+ if (!animate && mCannedAnimationStartIndex >= 0
+ && indexOfChild(view) > mCannedAnimationStartIndex
+ && (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
+ || visibleState != StatusBarIconView.STATE_HIDDEN)) {
+ AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
+ animationFilter.reset();
+ animationFilter.animateX();
+ animationProperties = mTempProperties;
+ animationProperties.setDuration(CANNED_ANIMATION_DURATION);
+ animate = true;
}
icon.setVisibleState(visibleState);
if (animate) {
@@ -336,6 +467,13 @@
}
}
justAdded = false;
+ needsCannedAnimation = false;
+ }
+
+ protected void onYTranslationAnimationFinished(View view) {
+ if (hidden) {
+ view.setVisibility(INVISIBLE);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 99e98f2e..a239cb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -105,7 +105,7 @@
private boolean mAnimateNextTopPaddingChange;
private int mTrackingPointer;
- private VelocityTracker mVelocityTracker;
+ private VelocityTracker mQsVelocityTracker;
private boolean mQsTracking;
/**
@@ -208,6 +208,7 @@
};
private NotificationGroupManager mGroupManager;
private boolean mOpening;
+ private int mIndicationBottomPadding;
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -273,6 +274,8 @@
R.dimen.notification_panel_min_side_margin);
mMaxFadeoutHeight = getResources().getDimensionPixelSize(
R.dimen.max_notification_fadeout_height);
+ mIndicationBottomPadding = getResources().getDimensionPixelSize(
+ R.dimen.keyguard_indication_bottom_padding);
}
public void updateResources() {
@@ -406,7 +409,8 @@
R.dimen.notification_divider_height));
float shelfSize = mNotificationStackScroller.getNotificationShelf().getIntrinsicHeight()
+ notificationPadding;
- float availableSpace = mNotificationStackScroller.getHeight() - minPadding - shelfSize;
+ float availableSpace = mNotificationStackScroller.getHeight() - minPadding - shelfSize
+ - mIndicationBottomPadding;
int count = 0;
for (int i = 0; i < mNotificationStackScroller.getChildCount(); i++) {
ExpandableView child = (ExpandableView) mNotificationStackScroller.getChildAt(i);
@@ -684,7 +688,7 @@
}
private void flingQsWithCurrentVelocity(float y, boolean isCancelMotionEvent) {
- float vel = getCurrentVelocity();
+ float vel = getCurrentQSVelocity();
final boolean expandsQs = flingExpandsQs(vel);
if (expandsQs) {
logQsSwipeDown(y);
@@ -693,7 +697,7 @@
}
private void logQsSwipeDown(float y) {
- float vel = getCurrentVelocity();
+ float vel = getCurrentQSVelocity();
final int gesture = mStatusBarState == StatusBarState.KEYGUARD
? EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_QS
: EventLogConstants.SYSUI_SHADE_GESTURE_SWIPE_DOWN_QS;
@@ -922,9 +926,9 @@
flingQsWithCurrentVelocity(y,
event.getActionMasked() == MotionEvent.ACTION_CANCEL);
}
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
+ if (mQsVelocityTracker != null) {
+ mQsVelocityTracker.recycle();
+ mQsVelocityTracker = null;
}
break;
}
@@ -1286,24 +1290,24 @@
}
private void trackMovement(MotionEvent event) {
- if (mVelocityTracker != null) mVelocityTracker.addMovement(event);
+ if (mQsVelocityTracker != null) mQsVelocityTracker.addMovement(event);
mLastTouchX = event.getX();
mLastTouchY = event.getY();
}
private void initVelocityTracker() {
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
+ if (mQsVelocityTracker != null) {
+ mQsVelocityTracker.recycle();
}
- mVelocityTracker = VelocityTracker.obtain();
+ mQsVelocityTracker = VelocityTracker.obtain();
}
- private float getCurrentVelocity() {
- if (mVelocityTracker == null) {
+ private float getCurrentQSVelocity() {
+ if (mQsVelocityTracker == null) {
return 0;
}
- mVelocityTracker.computeCurrentVelocity(1000);
- return mVelocityTracker.getYVelocity();
+ mQsVelocityTracker.computeCurrentVelocity(1000);
+ return mQsVelocityTracker.getYVelocity();
}
private void cancelQsAnimation() {
@@ -2278,6 +2282,9 @@
}
protected void updateExpandedHeight(float expandedHeight) {
+ if (mTracking) {
+ mNotificationStackScroller.setExpandingVelocity(getCurrentExpandVelocity());
+ }
mNotificationStackScroller.setExpandedHeight(expandedHeight);
updateKeyguardBottomAreaAlpha();
setOpening(expandedHeight <= getOpeningHeight());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index f16c834..55dd578 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -306,6 +306,7 @@
}
break;
case MotionEvent.ACTION_MOVE:
+ trackMovement(event);
float h = y - mInitialTouchY;
// If the panel was collapsed when touching, we only need to check for the
@@ -346,8 +347,6 @@
!isTrackingBlocked()) {
setExpandedHeightInternal(newHeight);
}
-
- trackMovement(event);
break;
case MotionEvent.ACTION_UP:
@@ -449,6 +448,14 @@
mPeekTouching = false;
}
+ protected float getCurrentExpandVelocity() {
+ if (mVelocityTracker == null) {
+ return 0;
+ }
+ mVelocityTracker.computeCurrentVelocity(1000);
+ return mVelocityTracker.getYVelocity();
+ }
+
private int getFalsingThreshold() {
float factor = mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
return (int) (mUnlockFalsingThreshold * factor);
@@ -685,7 +692,7 @@
mOverExpandedBeforeFling = getOverExpansionAmount() > 0f;
ValueAnimator animator = createHeightAnimator(target);
if (expand) {
- if (expandBecauseOfFalsing) {
+ if (expandBecauseOfFalsing && vel < 0) {
vel = 0;
}
mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, getHeight());
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 2b74c847..252b5c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -22,6 +22,7 @@
import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
+
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
@@ -73,6 +74,7 @@
import android.media.session.PlaybackState;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@@ -83,8 +85,8 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
-import android.os.Trace;
import android.os.SystemProperties;
+import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.Vibrator;
@@ -123,13 +125,13 @@
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.keyguard.LatencyTracker;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.DemoMode;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.Interpolators;
-import com.android.keyguard.LatencyTracker;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
@@ -145,10 +147,12 @@
import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSPanel;
+import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
import com.android.systemui.recents.events.activity.UndockingTaskEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.stackdivider.WindowManagerProxy;
import com.android.systemui.statusbar.ActivatableNotificationView;
@@ -178,19 +182,20 @@
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.statusbar.policy.CastControllerImpl;
import com.android.systemui.statusbar.policy.EncryptionHelper;
-import com.android.systemui.statusbar.policy.FlashlightController;
+import com.android.systemui.statusbar.policy.FlashlightControllerImpl;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.HotspotControllerImpl;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.LocationControllerImpl;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
import com.android.systemui.statusbar.policy.SecurityControllerImpl;
-import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
@@ -319,19 +324,19 @@
NetworkControllerImpl mNetworkController;
HotspotControllerImpl mHotspotController;
RotationLockControllerImpl mRotationLockController;
- UserInfoController mUserInfoController;
+ UserInfoControllerImpl mUserInfoController;
protected ZenModeController mZenModeController;
CastControllerImpl mCastController;
VolumeComponent mVolumeComponent;
KeyguardUserSwitcher mKeyguardUserSwitcher;
- FlashlightController mFlashlightController;
+ FlashlightControllerImpl mFlashlightController;
protected UserSwitcherController mUserSwitcherController;
- NextAlarmController mNextAlarmController;
- protected KeyguardMonitor mKeyguardMonitor;
+ NextAlarmControllerImpl mNextAlarmController;
+ protected KeyguardMonitorImpl mKeyguardMonitor;
BrightnessMirrorController mBrightnessMirrorController;
AccessibilityController mAccessibilityController;
protected FingerprintUnlockController mFingerprintUnlockController;
- LightStatusBarController mLightStatusBarController;
+ LightBarController mLightBarController;
protected LockscreenWallpaper mLockscreenWallpaper;
int mNaturalBarHeight = -1;
@@ -827,10 +832,45 @@
mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
}
+ mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
+ mKeyguardStatusView =
+ (KeyguardStatusView) mStatusBarWindow.findViewById(R.id.keyguard_status_view);
+ mKeyguardBottomArea =
+ (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
+ mKeyguardBottomArea.setActivityStarter(this);
+ mKeyguardBottomArea.setAssistManager(mAssistManager);
+ mKeyguardIndicationController = new KeyguardIndicationController(mContext,
+ (ViewGroup) mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
+ mKeyguardBottomArea.getLockIcon());
+ mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
+
+ // set the initial view visibility
+ setAreThereNotifications();
+
+ createIconController();
+
+ mBatteryController = createBatteryController();
+ mBatteryController.addCallback(new BatteryStateChangeCallback() {
+ @Override
+ public void onPowerSaveChanged(boolean isPowerSave) {
+ mHandler.post(mCheckBarModes);
+ if (mDozeServiceHost != null) {
+ mDozeServiceHost.firePowerSaveChanged(isPowerSave);
+ }
+ }
+ @Override
+ public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
+ // noop
+ }
+ });
+
+ mLightBarController = new LightBarController(mIconController, mNavigationBarView,
+ mBatteryController);
+
ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind);
ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front);
View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim);
- mScrimController = SystemUIFactory.getInstance().createScrimController(
+ mScrimController = SystemUIFactory.getInstance().createScrimController(mLightBarController,
scrimBehind, scrimInFront, headsUpScrim, mLockscreenWallpaper);
if (mScrimSrcModeEnabled) {
Runnable runnable = new Runnable() {
@@ -849,23 +889,6 @@
mStatusBarView.setScrimController(mScrimController);
mDozeScrimController = new DozeScrimController(mScrimController, context, mStackScroller);
- mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
- mKeyguardStatusView =
- (KeyguardStatusView) mStatusBarWindow.findViewById(R.id.keyguard_status_view);
- mKeyguardBottomArea =
- (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
- mKeyguardBottomArea.setActivityStarter(this);
- mKeyguardBottomArea.setAssistManager(mAssistManager);
- mKeyguardIndicationController = new KeyguardIndicationController(mContext,
- (ViewGroup) mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
- mKeyguardBottomArea.getLockIcon());
- mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
-
- // set the initial view visibility
- setAreThereNotifications();
-
- createIconController();
-
// Background thread for any controllers that need it.
mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
@@ -873,20 +896,6 @@
// Other icons
mLocationController = new LocationControllerImpl(mContext,
mHandlerThread.getLooper()); // will post a notification
- mBatteryController = createBatteryController();
- mBatteryController.addCallback(new BatteryStateChangeCallback() {
- @Override
- public void onPowerSaveChanged(boolean isPowerSave) {
- mHandler.post(mCheckBarModes);
- if (mDozeServiceHost != null) {
- mDozeServiceHost.firePowerSaveChanged(isPowerSave);
- }
- }
- @Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
- // noop
- }
- });
mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper());
mNetworkController.setUserSetupComplete(mUserSetup);
mHotspotController = new HotspotControllerImpl(mContext);
@@ -895,7 +904,7 @@
if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)) {
mRotationLockController = new RotationLockControllerImpl(mContext);
}
- mUserInfoController = new UserInfoController(mContext);
+ mUserInfoController = new UserInfoControllerImpl(mContext);
mVolumeComponent = getComponent(VolumeComponent.class);
if (mVolumeComponent != null) {
mZenModeController = mVolumeComponent.getZenController();
@@ -906,16 +915,14 @@
initSignalCluster(mKeyguardStatusBar);
initEmergencyCryptkeeperText();
- mFlashlightController = new FlashlightController(mContext);
+ mFlashlightController = new FlashlightControllerImpl(mContext);
mKeyguardBottomArea.setFlashlightController(mFlashlightController);
mKeyguardBottomArea.setPhoneStatusBar(this);
mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
mAccessibilityController = new AccessibilityController(mContext);
mKeyguardBottomArea.setAccessibilityController(mAccessibilityController);
- mNextAlarmController = new NextAlarmController(mContext);
- mLightStatusBarController = new LightStatusBarController(mIconController,
- mBatteryController);
- mKeyguardMonitor = new KeyguardMonitor(mContext);
+ mNextAlarmController = new NextAlarmControllerImpl(mContext);
+ mKeyguardMonitor = new KeyguardMonitorImpl(mContext);
mUserSwitcherController = createUserSwitcherController();
if (UserManager.get(mContext).isUserSwitcherEnabled()) {
createUserSwitcher();
@@ -1303,7 +1310,7 @@
});
mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
- mLightStatusBarController.setFingerprintUnlockController(mFingerprintUnlockController);
+ mLightBarController.setFingerprintUnlockController(mFingerprintUnlockController);
Trace.endSection();
}
@@ -1358,6 +1365,14 @@
return false;
}
+ ActivityManager.RunningTaskInfo runningTask =
+ Recents.getSystemServices().getRunningTask();
+ boolean isRunningTaskInHomeOrRecentsStack = runningTask != null &&
+ ActivityManager.StackId.isHomeOrRecentsStack(runningTask.stackId);
+ if (isRunningTaskInHomeOrRecentsStack) {
+ return false;
+ }
+
toggleSplitScreenMode(MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS,
MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS);
return true;
@@ -1517,6 +1532,7 @@
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
| WindowManager.LayoutParams.FLAG_SLIPPERY,
PixelFormat.TRANSLUCENT);
+ lp.token = new Binder();
// this will allow the navbar to run in an overlay on devices that support this
if (ActivityManager.isHighEndGfx()) {
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
@@ -3078,6 +3094,7 @@
Integer.toHexString(oldVal), Integer.toHexString(newVal),
Integer.toHexString(diff)));
boolean sbModeChanged = false;
+ boolean nbModeChanged = false;
if (diff != 0) {
mSystemUiVisibility = newVal;
@@ -3101,7 +3118,7 @@
View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,
View.NAVIGATION_BAR_TRANSPARENT);
sbModeChanged = sbMode != -1;
- final boolean nbModeChanged = nbMode != -1;
+ nbModeChanged = nbMode != -1;
boolean checkBarModes = false;
if (sbModeChanged && sbMode != mStatusBarMode) {
mStatusBarMode = sbMode;
@@ -3131,8 +3148,9 @@
notifyUiVisibilityChanged(mSystemUiVisibility);
}
- mLightStatusBarController.onSystemUiVisibilityChanged(fullscreenStackVis, dockedStackVis,
- mask, fullscreenStackBounds, dockedStackBounds, sbModeChanged, mStatusBarMode);
+ mLightBarController.onSystemUiVisibilityChanged(vis, fullscreenStackVis, dockedStackVis,
+ mask, fullscreenStackBounds, dockedStackBounds, sbModeChanged, mStatusBarMode,
+ nbModeChanged, mNavigationBarMode);
}
protected int computeStatusBarMode(int oldVal, int newVal) {
@@ -3572,10 +3590,18 @@
final boolean dismissShade,
final boolean afterKeyguardGone,
final boolean deferred) {
- dismissKeyguardThenExecute(() -> {
+ final Runnable dismissAction = () -> {
if (runnable != null) {
AsyncTask.execute(runnable);
}
+ };
+ dismissKeyguardThenExecute(() -> {
+ if (mStatusBarKeyguardViewManager.isShowing()
+ && mStatusBarKeyguardViewManager.isOccluded()) {
+ mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
+ } else {
+ dismissAction.run();
+ }
if (dismissShade) {
if (mExpandedVisible) {
animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */,
@@ -3664,8 +3690,6 @@
private void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
boolean afterKeyguardGone) {
- afterKeyguardGone |= mStatusBarKeyguardViewManager.isShowing()
- && mStatusBarKeyguardViewManager.isOccluded();
if (mStatusBarKeyguardViewManager.isShowing()) {
mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
afterKeyguardGone);
@@ -4187,8 +4211,14 @@
onLaunchTransitionFadingEnded();
}
});
- mIconController.appTransitionStarting(SystemClock.uptimeMillis(),
- StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION);
+ mIconController.getTransitionsController().appTransitionStarting(
+ SystemClock.uptimeMillis(),
+ LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().appTransitionStarting(
+ SystemClock.uptimeMillis(),
+ LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
+ }
}
};
if (mNotificationPanel.isLaunchTransitionRunning()) {
@@ -4319,7 +4349,10 @@
// Treat Keyguard exit animation as an app transition to achieve nice transition for status
// bar.
mKeyguardGoingAway = true;
- mIconController.appTransitionPending();
+ mIconController.getTransitionsController().appTransitionPending();
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().appTransitionPending();
+ }
}
/**
@@ -4334,11 +4367,16 @@
mKeyguardFadingAwayDelay = delay;
mKeyguardFadingAwayDuration = fadeoutDuration;
mWaitingForKeyguardExit = false;
- mIconController.appTransitionStarting(
+ mIconController.getTransitionsController().appTransitionStarting(
startTime + fadeoutDuration
- - StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION,
- StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION);
+ - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
+ LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
recomputeDisableFlags(fadeoutDuration > 0 /* animate */);
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().appTransitionStarting(
+ startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
+ LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
+ }
}
public boolean isKeyguardFadingAway() {
@@ -4559,6 +4597,7 @@
mGroupManager.setStatusBarState(state);
mFalsingManager.setStatusBarState(state);
mStatusBarWindowManager.setStatusBarState(state);
+ mStackScroller.setStatusBarState(state);
updateReportRejectedTouchVisibility();
updateDozing();
}
@@ -4968,13 +5007,19 @@
// Use own timings when Keyguard is going away, see keyguardGoingAway and
// setKeyguardFadingAway
if (!mKeyguardFadingAway) {
- mIconController.appTransitionPending();
+ mIconController.getTransitionsController().appTransitionPending();
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().appTransitionPending();
+ }
}
}
@Override
public void appTransitionCancelled() {
- mIconController.appTransitionCancelled();
+ mIconController.getTransitionsController().appTransitionCancelled();
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().appTransitionCancelled();
+ }
EventBus.getDefault().send(new AppTransitionFinishedEvent());
}
@@ -4984,7 +5029,11 @@
// Use own timings when Keyguard is going away, see keyguardGoingAway and
// setKeyguardFadingAway.
if (!mKeyguardGoingAway) {
- mIconController.appTransitionStarting(startTime, duration);
+ mIconController.getTransitionsController().appTransitionStarting(startTime, duration);
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().appTransitionStarting(
+ startTime, duration);
+ }
}
if (mIconPolicy != null) {
mIconPolicy.appTransitionStarting(startTime, duration);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index fc15477..567ab3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -143,7 +143,7 @@
mBattery = battery;
mIconController = iconController;
mNextAlarmController = nextAlarmController;
- mProfileController = new ManagedProfileController(this);
+ mProfileController = new ManagedProfileControllerImpl(this);
mHandlerThread = new HandlerThread(QSTileHost.class.getSimpleName(),
Process.THREAD_PRIORITY_BACKGROUND);
@@ -335,12 +335,16 @@
QSTile<?> tile = mTiles.get(tileSpec);
if (tile != null && (!(tile instanceof CustomTile)
|| ((CustomTile) tile).getUser() == currentUser)) {
- if (DEBUG) Log.d(TAG, "Adding " + tile);
- tile.removeCallbacks();
- if (!(tile instanceof CustomTile) && mCurrentUser != currentUser) {
- tile.userSwitch(currentUser);
+ if (tile.isAvailable()) {
+ if (DEBUG) Log.d(TAG, "Adding " + tile);
+ tile.removeCallbacks();
+ if (!(tile instanceof CustomTile) && mCurrentUser != currentUser) {
+ tile.userSwitch(currentUser);
+ }
+ newTiles.put(tileSpec, tile);
+ } else {
+ tile.destroy();
}
- newTiles.put(tileSpec, tile);
} else {
if (DEBUG) Log.d(TAG, "Creating tile: " + tileSpec);
try {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 28aed87..08a91bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -32,6 +32,7 @@
import android.widget.TextView;
import android.widget.Toast;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.keyguard.KeyguardStatusView;
@@ -236,10 +237,12 @@
}
@Override
- protected void onDetachedFromWindow() {
+ @VisibleForTesting
+ public void onDetachedFromWindow() {
setListening(false);
mHost.getUserInfoController().removeCallback(this);
mHost.getNetworkController().removeEmergencyListener(this);
+ mHost.getUserInfoController().removeCallback(this);
super.onDetachedFromWindow();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 0e74e57..944495e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -59,6 +59,7 @@
private static final int TAG_START_ALPHA = R.id.scrim_alpha_start;
private static final int TAG_END_ALPHA = R.id.scrim_alpha_end;
+ private final LightBarController mLightBarController;
protected final ScrimView mScrimBehind;
private final ScrimView mScrimInFront;
private final UnlockMethodCache mUnlockMethodCache;
@@ -99,13 +100,15 @@
private boolean mKeyguardFadingOutInProgress;
private ValueAnimator mKeyguardFadeoutAnimation;
- public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim) {
+ public ScrimController(LightBarController lightBarController, ScrimView scrimBehind,
+ ScrimView scrimInFront, View headsUpScrim) {
mScrimBehind = scrimBehind;
mScrimInFront = scrimInFront;
mHeadsUpScrim = headsUpScrim;
final Context context = scrimBehind.getContext();
mUnlockMethodCache = UnlockMethodCache.getInstance(context);
mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
+ mLightBarController = lightBarController;
updateHeadsUpScrim(false);
}
@@ -341,6 +344,7 @@
alpha = Math.max(0.0f, Math.min(1.0f, alpha));
mCurrentHeadsUpAlpha = alpha;
}
+ mLightBarController.setScrimAlpha(mCurrentBehindAlpha);
}
protected void updateScrimColor(View scrim) {
@@ -556,10 +560,6 @@
mScrimBehind.setExcludedArea(area);
}
- public void setLeftInset(int inset) {
- mScrimBehind.setLeftInset(inset);
- }
-
public int getScrimBehindColor() {
return mScrimBehind.getScrimColorWithAlpha();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index a948a08..a0425e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -60,7 +60,6 @@
*/
public class StatusBarIconController extends StatusBarIconList implements Tunable {
- public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
public static final String ICON_BLACKLIST = "icon_blacklist";
public static final int DEFAULT_ICON_TINT = Color.WHITE;
@@ -90,31 +89,16 @@
private static final Rect sTmpRect = new Rect();
private static final int[] sTmpInt2 = new int[2];
- private boolean mTransitionPending;
- private boolean mTintChangePending;
- private float mPendingDarkIntensity;
- private ValueAnimator mTintAnimator;
-
private int mDarkModeIconColorSingleTone;
private int mLightModeIconColorSingleTone;
- private final Handler mHandler;
- private boolean mTransitionDeferring;
- private long mTransitionDeferringStartTime;
- private long mTransitionDeferringDuration;
+ private final LightBarTransitionsController mTransitionsController;
private boolean mClockVisibleByPolicy = true;
private boolean mClockVisibleByUser = true;
private final ArraySet<String> mIconBlacklist = new ArraySet<>();
- private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
- @Override
- public void run() {
- mTransitionDeferring = false;
- }
- };
-
public StatusBarIconController(Context context, View statusBar, View keyguardStatusBar,
PhoneStatusBar phoneStatusBar) {
super(context.getResources().getStringArray(
@@ -144,16 +128,21 @@
mClock = (TextView) statusBar.findViewById(R.id.clock);
mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
- mHandler = new Handler();
loadDimens();
TunerService.get(mContext).addTunable(this, ICON_BLACKLIST);
+
+ mTransitionsController = new LightBarTransitionsController(this::setIconTintInternal);
}
public void setSignalCluster(SignalClusterView signalCluster) {
mSignalCluster = signalCluster;
}
+ public LightBarTransitionsController getTransitionsController() {
+ return mTransitionsController;
+ }
+
/**
* Looks up the scale factor for status bar icons and scales the battery view by that amount.
*/
@@ -444,41 +433,6 @@
mNotificationIconAreaController.setTintArea(darkArea);
}
- public void setIconsDark(boolean dark, boolean animate) {
- if (!animate) {
- setIconTintInternal(dark ? 1.0f : 0.0f);
- } else if (mTransitionPending) {
- deferIconTintChange(dark ? 1.0f : 0.0f);
- } else if (mTransitionDeferring) {
- animateIconTint(dark ? 1.0f : 0.0f,
- Math.max(0, mTransitionDeferringStartTime - SystemClock.uptimeMillis()),
- mTransitionDeferringDuration);
- } else {
- animateIconTint(dark ? 1.0f : 0.0f, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
- }
- }
-
- private void animateIconTint(float targetDarkIntensity, long delay,
- long duration) {
- if (mTintAnimator != null) {
- mTintAnimator.cancel();
- }
- if (mDarkIntensity == targetDarkIntensity) {
- return;
- }
- mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
- mTintAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- setIconTintInternal((Float) animation.getAnimatedValue());
- }
- });
- mTintAnimator.setDuration(duration);
- mTintAnimator.setStartDelay(delay);
- mTintAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- mTintAnimator.start();
- }
-
private void setIconTintInternal(float darkIntensity) {
mDarkIntensity = darkIntensity;
mIconTint = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
@@ -487,14 +441,6 @@
applyIconTint();
}
- private void deferIconTintChange(float darkIntensity) {
- if (mTintChangePending && darkIntensity == mPendingDarkIntensity) {
- return;
- }
- mTintChangePending = true;
- mPendingDarkIntensity = darkIntensity;
- }
-
/**
* @return the tint to apply to {@param view} depending on the desired tint {@param color} and
* the screen {@param tintArea} in which to apply that tint
@@ -551,38 +497,6 @@
mClock.setTextColor(getTint(mTintArea, mClock, mIconTint));
}
- public void appTransitionPending() {
- mTransitionPending = true;
- }
-
- public void appTransitionCancelled() {
- if (mTransitionPending && mTintChangePending) {
- mTintChangePending = false;
- animateIconTint(mPendingDarkIntensity, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
- }
- mTransitionPending = false;
- }
-
- public void appTransitionStarting(long startTime, long duration) {
- if (mTransitionPending && mTintChangePending) {
- mTintChangePending = false;
- animateIconTint(mPendingDarkIntensity,
- Math.max(0, startTime - SystemClock.uptimeMillis()),
- duration);
-
- } else if (mTransitionPending) {
-
- // If we don't have a pending tint change yet, the change might come in the future until
- // startTime is reached.
- mTransitionDeferring = true;
- mTransitionDeferringStartTime = startTime;
- mTransitionDeferringDuration = duration;
- mHandler.removeCallbacks(mTransitionDeferringDoneRunnable);
- mHandler.postAtTime(mTransitionDeferringDoneRunnable, startTime);
- }
- mTransitionPending = false;
- }
-
public static ArraySet<String> getIconBlacklist(String blackListStr) {
ArraySet<String> ret = new ArraySet<String>();
if (blackListStr == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 4263670..2e279b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -40,6 +40,8 @@
import static com.android.keyguard.KeyguardHostView.OnDismissAction;
import static com.android.systemui.statusbar.phone.FingerprintUnlockController.*;
+import java.util.ArrayList;
+
/**
* Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
* via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
@@ -90,6 +92,7 @@
protected boolean mLastRemoteInputActive;
private OnDismissAction mAfterKeyguardGoneAction;
+ private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>();
private boolean mDeviceWillWakeUp;
private boolean mDeferScrimFadeOut;
@@ -165,6 +168,13 @@
}
/**
+ * Adds a {@param runnable} to be executed after Keyguard is gone.
+ */
+ public void addAfterKeyguardGoneRunnable(Runnable runnable) {
+ mAfterKeyguardGoneRunnables.add(runnable);
+ }
+
+ /**
* Reset the state of the view.
*/
public void reset(boolean hideBouncerWhenShowing) {
@@ -418,6 +428,10 @@
mAfterKeyguardGoneAction.onDismiss();
mAfterKeyguardGoneAction = null;
}
+ for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) {
+ mAfterKeyguardGoneRunnables.get(i).run();
+ }
+ mAfterKeyguardGoneRunnables.clear();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 29c0705..0660054 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -22,6 +22,7 @@
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.PixelFormat;
+import android.os.Binder;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.Trace;
@@ -97,6 +98,7 @@
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
PixelFormat.TRANSLUCENT);
+ mLp.token = new Binder();
mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
mLp.gravity = Gravity.TOP;
mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index f6dd88d9..487f0e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -130,7 +130,6 @@
}
private void applyMargins() {
- mService.mScrimController.setLeftInset(mLeftInset);
final int N = getChildCount();
for (int i = 0; i < N; i++) {
View child = getChildAt(i);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
index e5f1e68..0df7859 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
@@ -14,92 +14,14 @@
package com.android.systemui.statusbar.policy;
-import android.content.Context;
-import android.net.INetworkPolicyListener;
-import android.net.NetworkPolicyManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.RemoteException;
-
import com.android.systemui.statusbar.policy.DataSaverController.Listener;
-import java.util.ArrayList;
+public interface DataSaverController extends CallbackController<Listener> {
-public class DataSaverController implements CallbackController<Listener> {
-
- private final Handler mHandler = new Handler(Looper.getMainLooper());
- private final ArrayList<Listener> mListeners = new ArrayList<>();
- private final NetworkPolicyManager mPolicyManager;
-
- public DataSaverController(Context context) {
- mPolicyManager = NetworkPolicyManager.from(context);
- }
-
- private void handleRestrictBackgroundChanged(boolean isDataSaving) {
- synchronized (mListeners) {
- for (int i = 0; i < mListeners.size(); i++) {
- mListeners.get(i).onDataSaverChanged(isDataSaving);
- }
- }
- }
-
- public void addCallback(Listener listener) {
- synchronized (mListeners) {
- mListeners.add(listener);
- if (mListeners.size() == 1) {
- mPolicyManager.registerListener(mPolicyListener);
- }
- }
- listener.onDataSaverChanged(isDataSaverEnabled());
- }
-
- public void removeCallback(Listener listener) {
- synchronized (mListeners) {
- mListeners.remove(listener);
- if (mListeners.size() == 0) {
- mPolicyManager.unregisterListener(mPolicyListener);
- }
- }
- }
-
- public boolean isDataSaverEnabled() {
- return mPolicyManager.getRestrictBackground();
- }
-
- public void setDataSaverEnabled(boolean enabled) {
- mPolicyManager.setRestrictBackground(enabled);
- try {
- mPolicyListener.onRestrictBackgroundChanged(enabled);
- } catch (RemoteException e) {
- }
- }
-
- private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
- @Override
- public void onUidRulesChanged(int uid, int uidRules) throws RemoteException {
- }
-
- @Override
- public void onMeteredIfacesChanged(String[] strings) throws RemoteException {
- }
-
- @Override
- public void onRestrictBackgroundChanged(final boolean isDataSaving) throws RemoteException {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- handleRestrictBackgroundChanged(isDataSaving);
- }
- });
- }
-
- @Override
- public void onUidPoliciesChanged(int uid, int uidPolicies) throws RemoteException {
- }
- };
+ boolean isDataSaverEnabled();
+ void setDataSaverEnabled(boolean enabled);
public interface Listener {
void onDataSaverChanged(boolean isDataSaving);
}
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
new file mode 100644
index 0000000..2951943
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.content.Context;
+import android.net.INetworkPolicyListener;
+import android.net.NetworkPolicyManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+
+import com.android.systemui.statusbar.policy.DataSaverController.Listener;
+
+import java.util.ArrayList;
+
+public class DataSaverControllerImpl implements DataSaverController {
+
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
+ private final ArrayList<Listener> mListeners = new ArrayList<>();
+ private final NetworkPolicyManager mPolicyManager;
+
+ public DataSaverControllerImpl(Context context) {
+ mPolicyManager = NetworkPolicyManager.from(context);
+ }
+
+ private void handleRestrictBackgroundChanged(boolean isDataSaving) {
+ synchronized (mListeners) {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onDataSaverChanged(isDataSaving);
+ }
+ }
+ }
+
+ public void addCallback(Listener listener) {
+ synchronized (mListeners) {
+ mListeners.add(listener);
+ if (mListeners.size() == 1) {
+ mPolicyManager.registerListener(mPolicyListener);
+ }
+ }
+ listener.onDataSaverChanged(isDataSaverEnabled());
+ }
+
+ public void removeCallback(Listener listener) {
+ synchronized (mListeners) {
+ mListeners.remove(listener);
+ if (mListeners.size() == 0) {
+ mPolicyManager.unregisterListener(mPolicyListener);
+ }
+ }
+ }
+
+ public boolean isDataSaverEnabled() {
+ return mPolicyManager.getRestrictBackground();
+ }
+
+ public void setDataSaverEnabled(boolean enabled) {
+ mPolicyManager.setRestrictBackground(enabled);
+ try {
+ mPolicyListener.onRestrictBackgroundChanged(enabled);
+ } catch (RemoteException e) {
+ }
+ }
+
+ private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
+ @Override
+ public void onUidRulesChanged(int uid, int uidRules) throws RemoteException {
+ }
+
+ @Override
+ public void onMeteredIfacesChanged(String[] strings) throws RemoteException {
+ }
+
+ @Override
+ public void onRestrictBackgroundChanged(final boolean isDataSaving) throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ handleRestrictBackgroundChanged(isDataSaving);
+ }
+ });
+ }
+
+ @Override
+ public void onUidPoliciesChanged(int uid, int uidPolicies) throws RemoteException {
+ }
+ };
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
index 8abfb89..a2d1baf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.policy;
import android.annotation.Nullable;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -41,12 +42,20 @@
public class EmergencyCryptkeeperText extends TextView {
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- private KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
+ private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
@Override
public void onPhoneStateChanged(int phoneState) {
update();
}
};
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())) {
+ update();
+ }
+ }
+ };
public EmergencyCryptkeeperText(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
@@ -58,6 +67,8 @@
super.onAttachedToWindow();
mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
mKeyguardUpdateMonitor.registerCallback(mCallback);
+ getContext().registerReceiver(mReceiver,
+ new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
update();
}
@@ -67,6 +78,7 @@
if (mKeyguardUpdateMonitor != null) {
mKeyguardUpdateMonitor.removeCallback(mCallback);
}
+ getContext().unregisterReceiver(mReceiver);
}
public void update() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index 0f77b03..6023f3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -1,255 +1,27 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
+ * 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
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
package com.android.systemui.statusbar.policy;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraManager;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Process;
-import android.text.TextUtils;
-import android.util.Log;
-
import com.android.systemui.statusbar.policy.FlashlightController.FlashlightListener;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
+public interface FlashlightController extends CallbackController<FlashlightListener> {
-/**
- * Manages the flashlight.
- */
-public class FlashlightController implements CallbackController<FlashlightListener> {
-
- private static final String TAG = "FlashlightController";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- private static final int DISPATCH_ERROR = 0;
- private static final int DISPATCH_CHANGED = 1;
- private static final int DISPATCH_AVAILABILITY_CHANGED = 2;
-
- private final CameraManager mCameraManager;
- private final Context mContext;
- /** Call {@link #ensureHandler()} before using */
- private Handler mHandler;
-
- /** Lock on mListeners when accessing */
- private final ArrayList<WeakReference<FlashlightListener>> mListeners = new ArrayList<>(1);
-
- /** Lock on {@code this} when accessing */
- private boolean mFlashlightEnabled;
-
- private String mCameraId;
- private boolean mTorchAvailable;
-
- public FlashlightController(Context context) {
- mContext = context;
- mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
-
- tryInitCamera();
- }
-
- private void tryInitCamera() {
- try {
- mCameraId = getCameraId();
- } catch (Throwable e) {
- Log.e(TAG, "Couldn't initialize.", e);
- return;
- }
-
- if (mCameraId != null) {
- ensureHandler();
- mCameraManager.registerTorchCallback(mTorchCallback, mHandler);
- }
- }
-
- public void setFlashlight(boolean enabled) {
- boolean pendingError = false;
- synchronized (this) {
- if (mCameraId == null) return;
- if (mFlashlightEnabled != enabled) {
- mFlashlightEnabled = enabled;
- try {
- mCameraManager.setTorchMode(mCameraId, enabled);
- } catch (CameraAccessException e) {
- Log.e(TAG, "Couldn't set torch mode", e);
- mFlashlightEnabled = false;
- pendingError = true;
- }
- }
- }
- dispatchModeChanged(mFlashlightEnabled);
- if (pendingError) {
- dispatchError();
- }
- }
-
- public boolean hasFlashlight() {
- return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
- }
-
- public synchronized boolean isEnabled() {
- return mFlashlightEnabled;
- }
-
- public synchronized boolean isAvailable() {
- return mTorchAvailable;
- }
-
- public void addCallback(FlashlightListener l) {
- synchronized (mListeners) {
- if (mCameraId == null) {
- tryInitCamera();
- }
- cleanUpListenersLocked(l);
- mListeners.add(new WeakReference<>(l));
- }
- }
-
- public void removeCallback(FlashlightListener l) {
- synchronized (mListeners) {
- cleanUpListenersLocked(l);
- }
- }
-
- private synchronized void ensureHandler() {
- if (mHandler == null) {
- HandlerThread thread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
- thread.start();
- mHandler = new Handler(thread.getLooper());
- }
- }
-
- private String getCameraId() throws CameraAccessException {
- String[] ids = mCameraManager.getCameraIdList();
- for (String id : ids) {
- CameraCharacteristics c = mCameraManager.getCameraCharacteristics(id);
- Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
- Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING);
- if (flashAvailable != null && flashAvailable
- && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
- return id;
- }
- }
- return null;
- }
-
- private void dispatchModeChanged(boolean enabled) {
- dispatchListeners(DISPATCH_CHANGED, enabled);
- }
-
- private void dispatchError() {
- dispatchListeners(DISPATCH_CHANGED, false /* argument (ignored) */);
- }
-
- private void dispatchAvailabilityChanged(boolean available) {
- dispatchListeners(DISPATCH_AVAILABILITY_CHANGED, available);
- }
-
- private void dispatchListeners(int message, boolean argument) {
- synchronized (mListeners) {
- final int N = mListeners.size();
- boolean cleanup = false;
- for (int i = 0; i < N; i++) {
- FlashlightListener l = mListeners.get(i).get();
- if (l != null) {
- if (message == DISPATCH_ERROR) {
- l.onFlashlightError();
- } else if (message == DISPATCH_CHANGED) {
- l.onFlashlightChanged(argument);
- } else if (message == DISPATCH_AVAILABILITY_CHANGED) {
- l.onFlashlightAvailabilityChanged(argument);
- }
- } else {
- cleanup = true;
- }
- }
- if (cleanup) {
- cleanUpListenersLocked(null);
- }
- }
- }
-
- private void cleanUpListenersLocked(FlashlightListener listener) {
- for (int i = mListeners.size() - 1; i >= 0; i--) {
- FlashlightListener found = mListeners.get(i).get();
- if (found == null || found == listener) {
- mListeners.remove(i);
- }
- }
- }
-
- private final CameraManager.TorchCallback mTorchCallback =
- new CameraManager.TorchCallback() {
-
- @Override
- public void onTorchModeUnavailable(String cameraId) {
- if (TextUtils.equals(cameraId, mCameraId)) {
- setCameraAvailable(false);
- }
- }
-
- @Override
- public void onTorchModeChanged(String cameraId, boolean enabled) {
- if (TextUtils.equals(cameraId, mCameraId)) {
- setCameraAvailable(true);
- setTorchMode(enabled);
- }
- }
-
- private void setCameraAvailable(boolean available) {
- boolean changed;
- synchronized (FlashlightController.this) {
- changed = mTorchAvailable != available;
- mTorchAvailable = available;
- }
- if (changed) {
- if (DEBUG) Log.d(TAG, "dispatchAvailabilityChanged(" + available + ")");
- dispatchAvailabilityChanged(available);
- }
- }
-
- private void setTorchMode(boolean enabled) {
- boolean changed;
- synchronized (FlashlightController.this) {
- changed = mFlashlightEnabled != enabled;
- mFlashlightEnabled = enabled;
- }
- if (changed) {
- if (DEBUG) Log.d(TAG, "dispatchModeChanged(" + enabled + ")");
- dispatchModeChanged(enabled);
- }
- }
- };
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("FlashlightController state:");
-
- pw.print(" mCameraId=");
- pw.println(mCameraId);
- pw.print(" mFlashlightEnabled=");
- pw.println(mFlashlightEnabled);
- pw.print(" mTorchAvailable=");
- pw.println(mTorchAvailable);
- }
+ boolean hasFlashlight();
+ void setFlashlight(boolean newState);
+ boolean isAvailable();
+ boolean isEnabled();
public interface FlashlightListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
new file mode 100644
index 0000000..008d837
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraManager;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Process;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.systemui.statusbar.policy.FlashlightController.FlashlightListener;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+
+/**
+ * Manages the flashlight.
+ */
+public class FlashlightControllerImpl implements FlashlightController {
+
+ private static final String TAG = "FlashlightController";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private static final int DISPATCH_ERROR = 0;
+ private static final int DISPATCH_CHANGED = 1;
+ private static final int DISPATCH_AVAILABILITY_CHANGED = 2;
+
+ private final CameraManager mCameraManager;
+ private final Context mContext;
+ /** Call {@link #ensureHandler()} before using */
+ private Handler mHandler;
+
+ /** Lock on mListeners when accessing */
+ private final ArrayList<WeakReference<FlashlightListener>> mListeners = new ArrayList<>(1);
+
+ /** Lock on {@code this} when accessing */
+ private boolean mFlashlightEnabled;
+
+ private String mCameraId;
+ private boolean mTorchAvailable;
+
+ public FlashlightControllerImpl(Context context) {
+ mContext = context;
+ mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
+
+ tryInitCamera();
+ }
+
+ private void tryInitCamera() {
+ try {
+ mCameraId = getCameraId();
+ } catch (Throwable e) {
+ Log.e(TAG, "Couldn't initialize.", e);
+ return;
+ }
+
+ if (mCameraId != null) {
+ ensureHandler();
+ mCameraManager.registerTorchCallback(mTorchCallback, mHandler);
+ }
+ }
+
+ public void setFlashlight(boolean enabled) {
+ boolean pendingError = false;
+ synchronized (this) {
+ if (mCameraId == null) return;
+ if (mFlashlightEnabled != enabled) {
+ mFlashlightEnabled = enabled;
+ try {
+ mCameraManager.setTorchMode(mCameraId, enabled);
+ } catch (CameraAccessException e) {
+ Log.e(TAG, "Couldn't set torch mode", e);
+ mFlashlightEnabled = false;
+ pendingError = true;
+ }
+ }
+ }
+ dispatchModeChanged(mFlashlightEnabled);
+ if (pendingError) {
+ dispatchError();
+ }
+ }
+
+ public boolean hasFlashlight() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
+ }
+
+ public synchronized boolean isEnabled() {
+ return mFlashlightEnabled;
+ }
+
+ public synchronized boolean isAvailable() {
+ return mTorchAvailable;
+ }
+
+ public void addCallback(FlashlightListener l) {
+ synchronized (mListeners) {
+ if (mCameraId == null) {
+ tryInitCamera();
+ }
+ cleanUpListenersLocked(l);
+ mListeners.add(new WeakReference<>(l));
+ }
+ }
+
+ public void removeCallback(FlashlightListener l) {
+ synchronized (mListeners) {
+ cleanUpListenersLocked(l);
+ }
+ }
+
+ private synchronized void ensureHandler() {
+ if (mHandler == null) {
+ HandlerThread thread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
+ thread.start();
+ mHandler = new Handler(thread.getLooper());
+ }
+ }
+
+ private String getCameraId() throws CameraAccessException {
+ String[] ids = mCameraManager.getCameraIdList();
+ for (String id : ids) {
+ CameraCharacteristics c = mCameraManager.getCameraCharacteristics(id);
+ Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
+ Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING);
+ if (flashAvailable != null && flashAvailable
+ && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
+ return id;
+ }
+ }
+ return null;
+ }
+
+ private void dispatchModeChanged(boolean enabled) {
+ dispatchListeners(DISPATCH_CHANGED, enabled);
+ }
+
+ private void dispatchError() {
+ dispatchListeners(DISPATCH_CHANGED, false /* argument (ignored) */);
+ }
+
+ private void dispatchAvailabilityChanged(boolean available) {
+ dispatchListeners(DISPATCH_AVAILABILITY_CHANGED, available);
+ }
+
+ private void dispatchListeners(int message, boolean argument) {
+ synchronized (mListeners) {
+ final int N = mListeners.size();
+ boolean cleanup = false;
+ for (int i = 0; i < N; i++) {
+ FlashlightListener l = mListeners.get(i).get();
+ if (l != null) {
+ if (message == DISPATCH_ERROR) {
+ l.onFlashlightError();
+ } else if (message == DISPATCH_CHANGED) {
+ l.onFlashlightChanged(argument);
+ } else if (message == DISPATCH_AVAILABILITY_CHANGED) {
+ l.onFlashlightAvailabilityChanged(argument);
+ }
+ } else {
+ cleanup = true;
+ }
+ }
+ if (cleanup) {
+ cleanUpListenersLocked(null);
+ }
+ }
+ }
+
+ private void cleanUpListenersLocked(FlashlightListener listener) {
+ for (int i = mListeners.size() - 1; i >= 0; i--) {
+ FlashlightListener found = mListeners.get(i).get();
+ if (found == null || found == listener) {
+ mListeners.remove(i);
+ }
+ }
+ }
+
+ private final CameraManager.TorchCallback mTorchCallback =
+ new CameraManager.TorchCallback() {
+
+ @Override
+ public void onTorchModeUnavailable(String cameraId) {
+ if (TextUtils.equals(cameraId, mCameraId)) {
+ setCameraAvailable(false);
+ }
+ }
+
+ @Override
+ public void onTorchModeChanged(String cameraId, boolean enabled) {
+ if (TextUtils.equals(cameraId, mCameraId)) {
+ setCameraAvailable(true);
+ setTorchMode(enabled);
+ }
+ }
+
+ private void setCameraAvailable(boolean available) {
+ boolean changed;
+ synchronized (FlashlightControllerImpl.this) {
+ changed = mTorchAvailable != available;
+ mTorchAvailable = available;
+ }
+ if (changed) {
+ if (DEBUG) Log.d(TAG, "dispatchAvailabilityChanged(" + available + ")");
+ dispatchAvailabilityChanged(available);
+ }
+ }
+
+ private void setTorchMode(boolean enabled) {
+ boolean changed;
+ synchronized (FlashlightControllerImpl.this) {
+ changed = mFlashlightEnabled != enabled;
+ mFlashlightEnabled = enabled;
+ }
+ if (changed) {
+ if (DEBUG) Log.d(TAG, "dispatchModeChanged(" + enabled + ")");
+ dispatchModeChanged(enabled);
+ }
+ }
+ };
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("FlashlightController state:");
+
+ pw.print(" mCameraId=");
+ pw.println(mCameraId);
+ pw.print(" mFlashlightEnabled=");
+ pw.println(mFlashlightEnabled);
+ pw.print(" mTorchAvailable=");
+ pw.println(mTorchAvailable);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
new file mode 100644
index 0000000..3ee01de
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.annotation.Nullable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+
+/**
+ * Drawable for {@link KeyButtonView}s which contains an asset for both normal mode and light
+ * navigation bar mode.
+ */
+public class KeyButtonDrawable extends LayerDrawable {
+
+ private final boolean mHasDarkDrawable;
+
+ public static KeyButtonDrawable create(Drawable lightDrawable,
+ @Nullable Drawable darkDrawable) {
+ if (darkDrawable != null) {
+ return new KeyButtonDrawable(
+ new Drawable[] { lightDrawable.mutate(), darkDrawable.mutate() });
+ } else {
+ return new KeyButtonDrawable(new Drawable[] { lightDrawable.mutate() });
+ }
+ }
+
+ private KeyButtonDrawable(Drawable[] drawables) {
+ super(drawables);
+ mutate();
+ mHasDarkDrawable = drawables.length > 1;
+ setDarkIntensity(0f);
+ }
+
+ public void setDarkIntensity(float intensity) {
+ if (!mHasDarkDrawable) {
+ return;
+ }
+ getDrawable(0).setAlpha((int) ((1 - intensity) * 255f));
+ getDrawable(1).setAlpha((int) (intensity * 255f));
+ invalidateSelf();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
index 57e092a..8e51ddb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
@@ -41,6 +41,7 @@
private static final float GLOW_MAX_SCALE_FACTOR = 1.35f;
private static final float GLOW_MAX_ALPHA = 0.2f;
+ private static final float GLOW_MAX_ALPHA_DARK = 0.1f;
private static final int ANIMATION_DURATION_SCALE = 350;
private static final int ANIMATION_DURATION_FADE = 450;
@@ -57,6 +58,8 @@
private boolean mPressed;
private boolean mDrawingHardwareGlow;
private int mMaxWidth;
+ private boolean mLastDark;
+ private boolean mDark;
private final Interpolator mInterpolator = new LogInterpolator();
private boolean mSupportHardware;
@@ -70,11 +73,15 @@
mTargetView = targetView;
}
+ public void setDarkIntensity(float darkIntensity) {
+ mDark = darkIntensity >= 0.5f;
+ }
+
private Paint getRipplePaint() {
if (mRipplePaint == null) {
mRipplePaint = new Paint();
mRipplePaint.setAntiAlias(true);
- mRipplePaint.setColor(0xffffffff);
+ mRipplePaint.setColor(mLastDark ? 0xff000000 : 0xffffffff);
}
return mRipplePaint;
}
@@ -155,6 +162,10 @@
invalidateSelf();
}
+ private float getMaxGlowAlpha() {
+ return mLastDark ? GLOW_MAX_ALPHA_DARK : GLOW_MAX_ALPHA;
+ }
+
@Override
protected boolean onStateChange(int[] state) {
boolean pressed = false;
@@ -184,6 +195,10 @@
}
public void setPressed(boolean pressed) {
+ if (mDark != mLastDark && pressed) {
+ mRipplePaint = null;
+ mLastDark = mDark;
+ }
if (mSupportHardware) {
setPressedHardware(pressed);
} else {
@@ -212,7 +227,7 @@
private void enterSoftware() {
cancelAnimations();
- mGlowAlpha = GLOW_MAX_ALPHA;
+ mGlowAlpha = getMaxGlowAlpha();
ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(this, "glowScale",
0f, GLOW_MAX_SCALE_FACTOR);
scaleAnimator.setInterpolator(mInterpolator);
@@ -312,7 +327,7 @@
}
mGlowScale = GLOW_MAX_SCALE_FACTOR;
- mGlowAlpha = GLOW_MAX_ALPHA;
+ mGlowAlpha = getMaxGlowAlpha();
mRipplePaint = getRipplePaint();
mRipplePaint.setAlpha((int) (mGlowAlpha * 255));
mPaintProp = CanvasProperty.createPaint(mRipplePaint);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index bcc5a3f..45cfbdc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.policy;
-import android.annotation.DrawableRes;
-import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Configuration;
@@ -60,6 +58,7 @@
private boolean mGestureAborted;
private boolean mLongClicked;
private OnClickListener mOnClickListener;
+ private final KeyButtonRipple mRipple;
private final Runnable mCheckLongPress = new Runnable() {
public void run() {
@@ -99,11 +98,12 @@
a.recycle();
-
setClickable(true);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- setBackground(new KeyButtonRipple(context, this));
+
+ mRipple = new KeyButtonRipple(context, this);
+ setBackground(mRipple);
}
public void setCode(int code) {
@@ -265,17 +265,20 @@
}
@Override
- public void setImageResource(@DrawableRes int resId) {
- super.setImageResource(resId);
+ public void setDarkIntensity(float darkIntensity) {
+ Drawable drawable = getDrawable();
+ if (drawable != null) {
+ ((KeyButtonDrawable) getDrawable()).setDarkIntensity(darkIntensity);
+
+ // Since we reuse the same drawable for multiple views, we need to invalidate the view
+ // manually.
+ invalidate();
+ }
+ mRipple.setDarkIntensity(darkIntensity);
}
@Override
- public void setImageDrawable(@Nullable Drawable drawable) {
- super.setImageDrawable(drawable);
- }
-
- @Override
- public void setLandscape(boolean landscape) {
+ public void setVertical(boolean vertical) {
//no op
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index 0396613..de47267 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -1,126 +1,28 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
+ * 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.
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
package com.android.systemui.statusbar.policy;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.os.RemoteException;
-import android.view.WindowManagerGlobal;
-
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback;
-import java.util.ArrayList;
+public interface KeyguardMonitor extends CallbackController<Callback> {
-public class KeyguardMonitor extends KeyguardUpdateMonitorCallback
- implements CallbackController<Callback> {
-
- private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
-
- private final Context mContext;
- private final CurrentUserTracker mUserTracker;
- private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-
- private int mCurrentUser;
- private boolean mShowing;
- private boolean mSecure;
- private boolean mOccluded;
- private boolean mCanSkipBouncer;
-
- private boolean mListening;
-
- public KeyguardMonitor(Context context) {
- mContext = context;
- mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
- mUserTracker = new CurrentUserTracker(mContext) {
- @Override
- public void onUserSwitched(int newUserId) {
- mCurrentUser = newUserId;
- updateCanSkipBouncerState();
- }
- };
- }
-
- public void addCallback(Callback callback) {
- mCallbacks.add(callback);
- if (mCallbacks.size() != 0 && !mListening) {
- mListening = true;
- mCurrentUser = ActivityManager.getCurrentUser();
- updateCanSkipBouncerState();
- mKeyguardUpdateMonitor.registerCallback(this);
- mUserTracker.startTracking();
- }
- }
-
- public void removeCallback(Callback callback) {
- if (mCallbacks.remove(callback) && mCallbacks.size() == 0 && mListening) {
- mListening = false;
- mKeyguardUpdateMonitor.removeCallback(this);
- mUserTracker.stopTracking();
- }
- }
-
- public boolean isShowing() {
- return mShowing;
- }
-
- public boolean isSecure() {
- return mSecure;
- }
-
- public boolean isOccluded() {
- return mOccluded;
- }
-
- public boolean canSkipBouncer() {
- return mCanSkipBouncer;
- }
-
- public void notifyKeyguardState(boolean showing, boolean secure, boolean occluded) {
- if (mShowing == showing && mSecure == secure && mOccluded == occluded) return;
- mShowing = showing;
- mSecure = secure;
- mOccluded = occluded;
- notifyKeyguardChanged();
- }
-
- @Override
- public void onTrustChanged(int userId) {
- updateCanSkipBouncerState();
- notifyKeyguardChanged();
- }
-
- public boolean isDeviceInteractive() {
- return mKeyguardUpdateMonitor.isDeviceInteractive();
- }
-
- private void updateCanSkipBouncerState() {
- mCanSkipBouncer = mKeyguardUpdateMonitor.getUserCanSkipBouncer(mCurrentUser);
- }
-
- private void notifyKeyguardChanged() {
- for (Callback callback : mCallbacks) {
- callback.onKeyguardChanged();
- }
- }
+ boolean isSecure();
+ boolean canSkipBouncer();
+ boolean isShowing();
public interface Callback {
void onKeyguardChanged();
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
new file mode 100644
index 0000000..769f93f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.RemoteException;
+import android.view.WindowManagerGlobal;
+
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback;
+
+import java.util.ArrayList;
+
+public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback
+ implements KeyguardMonitor {
+
+ private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
+
+ private final Context mContext;
+ private final CurrentUserTracker mUserTracker;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+
+ private int mCurrentUser;
+ private boolean mShowing;
+ private boolean mSecure;
+ private boolean mOccluded;
+ private boolean mCanSkipBouncer;
+
+ private boolean mListening;
+
+ public KeyguardMonitorImpl(Context context) {
+ mContext = context;
+ mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+ mUserTracker = new CurrentUserTracker(mContext) {
+ @Override
+ public void onUserSwitched(int newUserId) {
+ mCurrentUser = newUserId;
+ updateCanSkipBouncerState();
+ }
+ };
+ }
+
+ public void addCallback(Callback callback) {
+ mCallbacks.add(callback);
+ if (mCallbacks.size() != 0 && !mListening) {
+ mListening = true;
+ mCurrentUser = ActivityManager.getCurrentUser();
+ updateCanSkipBouncerState();
+ mKeyguardUpdateMonitor.registerCallback(this);
+ mUserTracker.startTracking();
+ }
+ }
+
+ public void removeCallback(Callback callback) {
+ if (mCallbacks.remove(callback) && mCallbacks.size() == 0 && mListening) {
+ mListening = false;
+ mKeyguardUpdateMonitor.removeCallback(this);
+ mUserTracker.stopTracking();
+ }
+ }
+
+ public boolean isShowing() {
+ return mShowing;
+ }
+
+ public boolean isSecure() {
+ return mSecure;
+ }
+
+ public boolean isOccluded() {
+ return mOccluded;
+ }
+
+ public boolean canSkipBouncer() {
+ return mCanSkipBouncer;
+ }
+
+ public void notifyKeyguardState(boolean showing, boolean secure, boolean occluded) {
+ if (mShowing == showing && mSecure == secure && mOccluded == occluded) return;
+ mShowing = showing;
+ mSecure = secure;
+ mOccluded = occluded;
+ notifyKeyguardChanged();
+ }
+
+ @Override
+ public void onTrustChanged(int userId) {
+ updateCanSkipBouncerState();
+ notifyKeyguardChanged();
+ }
+
+ public boolean isDeviceInteractive() {
+ return mKeyguardUpdateMonitor.isDeviceInteractive();
+ }
+
+ private void updateCanSkipBouncerState() {
+ mCanSkipBouncer = mKeyguardUpdateMonitor.getUserCanSkipBouncer(mCurrentUser);
+ }
+
+ private void notifyKeyguardChanged() {
+ for (Callback callback : mCallbacks) {
+ callback.onKeyguardChanged();
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 1a9756f..a7fab41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -159,7 +159,7 @@
mConfig = config;
mReceiverHandler = new Handler(bgLooper);
mCallbackHandler = callbackHandler;
- mDataSaverController = new DataSaverController(context);
+ mDataSaverController = new DataSaverControllerImpl(context);
mSubscriptionManager = subManager;
mSubDefaults = defaultsHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmController.java
index 28935bf..e5b0c03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmController.java
@@ -1,84 +1,24 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
+ * 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
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
package com.android.systemui.statusbar.policy;
import android.app.AlarmManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.UserHandle;
import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-
-public class NextAlarmController extends BroadcastReceiver
- implements CallbackController<NextAlarmChangeCallback> {
-
- private final ArrayList<NextAlarmChangeCallback> mChangeCallbacks = new ArrayList<>();
-
- private AlarmManager mAlarmManager;
- private AlarmManager.AlarmClockInfo mNextAlarm;
-
- public NextAlarmController(Context context) {
- mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_USER_SWITCHED);
- filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
- context.registerReceiverAsUser(this, UserHandle.ALL, filter, null, null);
- updateNextAlarm();
- }
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("NextAlarmController state:");
- pw.print(" mNextAlarm="); pw.println(mNextAlarm);
- }
-
- public void addCallback(NextAlarmChangeCallback cb) {
- mChangeCallbacks.add(cb);
- cb.onNextAlarmChanged(mNextAlarm);
- }
-
- public void removeCallback(NextAlarmChangeCallback cb) {
- mChangeCallbacks.remove(cb);
- }
-
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (action.equals(Intent.ACTION_USER_SWITCHED)
- || action.equals(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)) {
- updateNextAlarm();
- }
- }
-
- private void updateNextAlarm() {
- mNextAlarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
- fireNextAlarmChanged();
- }
-
- private void fireNextAlarmChanged() {
- int n = mChangeCallbacks.size();
- for (int i = 0; i < n; i++) {
- mChangeCallbacks.get(i).onNextAlarmChanged(mNextAlarm);
- }
- }
+public interface NextAlarmController extends CallbackController<NextAlarmChangeCallback> {
public interface NextAlarmChangeCallback {
void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
new file mode 100644
index 0000000..dfdeae1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.app.AlarmManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.UserHandle;
+
+import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+public class NextAlarmControllerImpl extends BroadcastReceiver
+ implements NextAlarmController {
+
+ private final ArrayList<NextAlarmChangeCallback> mChangeCallbacks = new ArrayList<>();
+
+ private AlarmManager mAlarmManager;
+ private AlarmManager.AlarmClockInfo mNextAlarm;
+
+ public NextAlarmControllerImpl(Context context) {
+ mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
+ context.registerReceiverAsUser(this, UserHandle.ALL, filter, null, null);
+ updateNextAlarm();
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("NextAlarmController state:");
+ pw.print(" mNextAlarm="); pw.println(mNextAlarm);
+ }
+
+ public void addCallback(NextAlarmChangeCallback cb) {
+ mChangeCallbacks.add(cb);
+ cb.onNextAlarmChanged(mNextAlarm);
+ }
+
+ public void removeCallback(NextAlarmChangeCallback cb) {
+ mChangeCallbacks.remove(cb);
+ }
+
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (action.equals(Intent.ACTION_USER_SWITCHED)
+ || action.equals(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)) {
+ updateNextAlarm();
+ }
+ }
+
+ private void updateNextAlarm() {
+ mNextAlarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
+ fireNextAlarmChanged();
+ }
+
+ private void fireNextAlarmChanged() {
+ int n = mChangeCallbacks.size();
+ for (int i = 0; i < n; i++) {
+ mChangeCallbacks.get(i).onNextAlarmChanged(mNextAlarm);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
index 43ced48..3142228 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
@@ -23,6 +23,8 @@
boolean hasProfileOwner();
String getDeviceOwnerName();
String getProfileOwnerName();
+ CharSequence getDeviceOwnerOrganizationName();
+ boolean isNetworkLoggingEnabled();
boolean isVpnEnabled();
boolean isVpnRestricted();
/** Whether the VPN app should use branded VPN iconography. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 07d3b59..df959bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -130,6 +130,11 @@
}
@Override
+ public CharSequence getDeviceOwnerOrganizationName() {
+ return mDevicePolicyManager.getDeviceOwnerOrganizationName();
+ }
+
+ @Override
public String getPrimaryVpnName() {
VpnConfig cfg = mCurrentVpns.get(mVpnUserId);
if (cfg != null) {
@@ -154,6 +159,11 @@
}
@Override
+ public boolean isNetworkLoggingEnabled() {
+ return mDevicePolicyManager.isNetworkLoggingEnabled(null);
+ }
+
+ @Override
public boolean isVpnEnabled() {
for (int profileId : mUserManager.getProfileIdsWithDisabled(mVpnUserId)) {
if (mCurrentVpns.get(profileId) != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
index c09747b..1e23a20 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
@@ -1,233 +1,28 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
+ * 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
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
package com.android.systemui.statusbar.policy;
-import android.app.ActivityManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.ContactsContract;
-import android.util.Log;
-import com.android.internal.util.UserIcons;
-import com.android.settingslib.drawable.UserIconDrawable;
-import com.android.systemui.R;
import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
-import java.util.ArrayList;
+public interface UserInfoController extends CallbackController<OnUserInfoChangedListener> {
-public class UserInfoController implements CallbackController<OnUserInfoChangedListener> {
-
- private static final String TAG = "UserInfoController";
-
- private final Context mContext;
- private final ArrayList<OnUserInfoChangedListener> mCallbacks =
- new ArrayList<OnUserInfoChangedListener>();
- private AsyncTask<Void, Void, UserInfoQueryResult> mUserInfoTask;
-
- private String mUserName;
- private Drawable mUserDrawable;
- private String mUserAccount;
-
- public UserInfoController(Context context) {
- mContext = context;
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_USER_SWITCHED);
- mContext.registerReceiver(mReceiver, filter);
-
- IntentFilter profileFilter = new IntentFilter();
- profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED);
- profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
- mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,
- null, null);
- }
-
- public void addCallback(OnUserInfoChangedListener callback) {
- mCallbacks.add(callback);
- callback.onUserInfoChanged(mUserName, mUserDrawable, mUserAccount);
- }
-
- public void removeCallback(OnUserInfoChangedListener callback) {
- mCallbacks.remove(callback);
- }
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- reloadUserInfo();
- }
- }
- };
-
- private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) ||
- Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
- try {
- final int currentUser = ActivityManager.getService().getCurrentUser().id;
- final int changedUser =
- intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId());
- if (changedUser == currentUser) {
- reloadUserInfo();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Couldn't get current user id for profile change", e);
- }
- }
- }
- };
-
- public void reloadUserInfo() {
- if (mUserInfoTask != null) {
- mUserInfoTask.cancel(false);
- mUserInfoTask = null;
- }
- queryForUserInformation();
- }
-
- private void queryForUserInformation() {
- Context currentUserContext;
- UserInfo userInfo;
- try {
- userInfo = ActivityManager.getService().getCurrentUser();
- currentUserContext = mContext.createPackageContextAsUser("android", 0,
- new UserHandle(userInfo.id));
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, "Couldn't create user context", e);
- throw new RuntimeException(e);
- } catch (RemoteException e) {
- Log.e(TAG, "Couldn't get user info", e);
- throw new RuntimeException(e);
- }
- final int userId = userInfo.id;
- final boolean isGuest = userInfo.isGuest();
- final String userName = userInfo.name;
-
- final Resources res = mContext.getResources();
- final int avatarSize = Math.max(
- res.getDimensionPixelSize(R.dimen.multi_user_avatar_expanded_size),
- res.getDimensionPixelSize(R.dimen.multi_user_avatar_keyguard_size));
-
- final Context context = currentUserContext;
- mUserInfoTask = new AsyncTask<Void, Void, UserInfoQueryResult>() {
-
- @Override
- protected UserInfoQueryResult doInBackground(Void... params) {
- final UserManager um = UserManager.get(mContext);
-
- // Fall back to the UserManager nickname if we can't read the name from the local
- // profile below.
- String name = userName;
- Drawable avatar = null;
- Bitmap rawAvatar = um.getUserIcon(userId);
- if (rawAvatar != null) {
- avatar = new UserIconDrawable(avatarSize)
- .setIcon(rawAvatar).setBadgeIfManagedUser(mContext, userId).bake();
- } else {
- avatar = UserIcons.getDefaultUserIcon(isGuest? UserHandle.USER_NULL : userId,
- /* light= */ true);
- }
-
- // If it's a single-user device, get the profile name, since the nickname is not
- // usually valid
- if (um.getUsers().size() <= 1) {
- // Try and read the display name from the local profile
- final Cursor cursor = context.getContentResolver().query(
- ContactsContract.Profile.CONTENT_URI, new String[] {
- ContactsContract.CommonDataKinds.Phone._ID,
- ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
- }, null, null, null);
- if (cursor != null) {
- try {
- if (cursor.moveToFirst()) {
- name = cursor.getString(cursor.getColumnIndex(
- ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
- }
- } finally {
- cursor.close();
- }
- }
- }
- String userAccount = um.getUserAccount(userId);
- return new UserInfoQueryResult(name, avatar, userAccount);
- }
-
- @Override
- protected void onPostExecute(UserInfoQueryResult result) {
- mUserName = result.getName();
- mUserDrawable = result.getAvatar();
- mUserAccount = result.getUserAccount();
- mUserInfoTask = null;
- notifyChanged();
- }
- };
- mUserInfoTask.execute();
- }
-
- private void notifyChanged() {
- for (OnUserInfoChangedListener listener : mCallbacks) {
- listener.onUserInfoChanged(mUserName, mUserDrawable, mUserAccount);
- }
- }
-
- public void onDensityOrFontScaleChanged() {
- reloadUserInfo();
- }
+ void reloadUserInfo();
public interface OnUserInfoChangedListener {
public void onUserInfoChanged(String name, Drawable picture, String userAccount);
}
-
- private static class UserInfoQueryResult {
- private String mName;
- private Drawable mAvatar;
- private String mUserAccount;
-
- public UserInfoQueryResult(String name, Drawable avatar, String userAccount) {
- mName = name;
- mAvatar = avatar;
- mUserAccount = userAccount;
- }
-
- public String getName() {
- return mName;
- }
-
- public Drawable getAvatar() {
- return mAvatar;
- }
-
- public String getUserAccount() {
- return mUserAccount;
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
new file mode 100644
index 0000000..b1e4b03
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.ContactsContract;
+import android.util.Log;
+
+import com.android.internal.util.UserIcons;
+import com.android.settingslib.drawable.UserIconDrawable;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
+
+import java.util.ArrayList;
+
+public class UserInfoControllerImpl implements UserInfoController {
+
+ private static final String TAG = "UserInfoController";
+
+ private final Context mContext;
+ private final ArrayList<OnUserInfoChangedListener> mCallbacks =
+ new ArrayList<OnUserInfoChangedListener>();
+ private AsyncTask<Void, Void, UserInfoQueryResult> mUserInfoTask;
+
+ private String mUserName;
+ private Drawable mUserDrawable;
+ private String mUserAccount;
+
+ public UserInfoControllerImpl(Context context) {
+ mContext = context;
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ mContext.registerReceiver(mReceiver, filter);
+
+ IntentFilter profileFilter = new IntentFilter();
+ profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED);
+ profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
+ mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,
+ null, null);
+ }
+
+ public void addCallback(OnUserInfoChangedListener callback) {
+ mCallbacks.add(callback);
+ callback.onUserInfoChanged(mUserName, mUserDrawable, mUserAccount);
+ }
+
+ public void removeCallback(OnUserInfoChangedListener callback) {
+ mCallbacks.remove(callback);
+ }
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ reloadUserInfo();
+ }
+ }
+ };
+
+ private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) ||
+ Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
+ try {
+ final int currentUser = ActivityManager.getService().getCurrentUser().id;
+ final int changedUser =
+ intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId());
+ if (changedUser == currentUser) {
+ reloadUserInfo();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't get current user id for profile change", e);
+ }
+ }
+ }
+ };
+
+ public void reloadUserInfo() {
+ if (mUserInfoTask != null) {
+ mUserInfoTask.cancel(false);
+ mUserInfoTask = null;
+ }
+ queryForUserInformation();
+ }
+
+ private void queryForUserInformation() {
+ Context currentUserContext;
+ UserInfo userInfo;
+ try {
+ userInfo = ActivityManager.getService().getCurrentUser();
+ currentUserContext = mContext.createPackageContextAsUser("android", 0,
+ new UserHandle(userInfo.id));
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Couldn't create user context", e);
+ throw new RuntimeException(e);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't get user info", e);
+ throw new RuntimeException(e);
+ }
+ final int userId = userInfo.id;
+ final boolean isGuest = userInfo.isGuest();
+ final String userName = userInfo.name;
+
+ final Resources res = mContext.getResources();
+ final int avatarSize = Math.max(
+ res.getDimensionPixelSize(R.dimen.multi_user_avatar_expanded_size),
+ res.getDimensionPixelSize(R.dimen.multi_user_avatar_keyguard_size));
+
+ final Context context = currentUserContext;
+ mUserInfoTask = new AsyncTask<Void, Void, UserInfoQueryResult>() {
+
+ @Override
+ protected UserInfoQueryResult doInBackground(Void... params) {
+ final UserManager um = UserManager.get(mContext);
+
+ // Fall back to the UserManager nickname if we can't read the name from the local
+ // profile below.
+ String name = userName;
+ Drawable avatar = null;
+ Bitmap rawAvatar = um.getUserIcon(userId);
+ if (rawAvatar != null) {
+ avatar = new UserIconDrawable(avatarSize)
+ .setIcon(rawAvatar).setBadgeIfManagedUser(mContext, userId).bake();
+ } else {
+ avatar = UserIcons.getDefaultUserIcon(isGuest? UserHandle.USER_NULL : userId,
+ /* light= */ true);
+ }
+
+ // If it's a single-user device, get the profile name, since the nickname is not
+ // usually valid
+ if (um.getUsers().size() <= 1) {
+ // Try and read the display name from the local profile
+ final Cursor cursor = context.getContentResolver().query(
+ ContactsContract.Profile.CONTENT_URI, new String[] {
+ ContactsContract.CommonDataKinds.Phone._ID,
+ ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
+ }, null, null, null);
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ name = cursor.getString(cursor.getColumnIndex(
+ ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+ String userAccount = um.getUserAccount(userId);
+ return new UserInfoQueryResult(name, avatar, userAccount);
+ }
+
+ @Override
+ protected void onPostExecute(UserInfoQueryResult result) {
+ mUserName = result.getName();
+ mUserDrawable = result.getAvatar();
+ mUserAccount = result.getUserAccount();
+ mUserInfoTask = null;
+ notifyChanged();
+ }
+ };
+ mUserInfoTask.execute();
+ }
+
+ private void notifyChanged() {
+ for (OnUserInfoChangedListener listener : mCallbacks) {
+ listener.onUserInfoChanged(mUserName, mUserDrawable, mUserAccount);
+ }
+ }
+
+ public void onDensityOrFontScaleChanged() {
+ reloadUserInfo();
+ }
+
+ private static class UserInfoQueryResult {
+ private String mName;
+ private Drawable mAvatar;
+ private String mUserAccount;
+
+ public UserInfoQueryResult(String name, Drawable avatar, String userAccount) {
+ mName = name;
+ mAvatar = avatar;
+ mUserAccount = userAccount;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public Drawable getAvatar() {
+ return mAvatar;
+ }
+
+ public String getUserAccount() {
+ return mUserAccount;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index 26f74ea..e1ff297 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -22,6 +22,7 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.ActivatableNotificationView;
import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import java.util.ArrayList;
@@ -52,6 +53,11 @@
private int mBaseZHeight;
private int mMaxLayoutHeight;
private ActivatableNotificationView mLastVisibleBackgroundChild;
+ private float mCurrentScrollVelocity;
+ private int mStatusBarState;
+ private float mExpandingVelocity;
+ private boolean mPanelTracking;
+ private boolean mExpansionChanging;
public AmbientState(Context context) {
reload(context);
@@ -241,4 +247,44 @@
public ActivatableNotificationView getLastVisibleBackgroundChild() {
return mLastVisibleBackgroundChild;
}
+
+ public void setCurrentScrollVelocity(float currentScrollVelocity) {
+ mCurrentScrollVelocity = currentScrollVelocity;
+ }
+
+ public float getCurrentScrollVelocity() {
+ return mCurrentScrollVelocity;
+ }
+
+ public boolean isOnKeyguard() {
+ return mStatusBarState == StatusBarState.KEYGUARD;
+ }
+
+ public void setStatusBarState(int statusBarState) {
+ mStatusBarState = statusBarState;
+ }
+
+ public void setExpandingVelocity(float expandingVelocity) {
+ mExpandingVelocity = expandingVelocity;
+ }
+
+ public void setExpansionChanging(boolean expansionChanging) {
+ mExpansionChanging = expansionChanging;
+ }
+
+ public boolean isExpansionChanging() {
+ return mExpansionChanging;
+ }
+
+ public float getExpandingVelocity() {
+ return mExpandingVelocity;
+ }
+
+ public void setPanelTracking(boolean panelTracking) {
+ mPanelTracking = panelTracking;
+ }
+
+ public boolean isPanelTracking() {
+ return mPanelTracking;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
index d3d58f9..38bb40e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
@@ -120,7 +120,7 @@
}
}
- private void combineFilter(AnimationFilter filter) {
+ public void combineFilter(AnimationFilter filter) {
animateAlpha |= filter.animateAlpha;
animateX |= filter.animateX;
animateY |= filter.animateY;
@@ -134,7 +134,7 @@
hasDelays |= filter.hasDelays;
}
- private void reset() {
+ public void reset() {
animateAlpha = false;
animateX = false;
animateY = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index b8f8cb2..22709f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -213,7 +213,7 @@
mDividers.add(newIndex, divider);
updateGroupOverflow();
- row.setIconTransformationAmount(0, false /* isLastChild */);
+ row.setContentTransformationAmount(0, false /* isLastChild */);
}
public void removeNotification(ExpandableNotificationRow row) {
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 10d995c..7d4927b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -357,6 +357,7 @@
private Rect mRequestedClipBounds;
private boolean mInHeadsUpPinnedMode;
private boolean mHeadsUpAnimatingAway;
+ private int mStatusBarState;
public NotificationStackScrollLayout(Context context) {
this(context, null);
@@ -575,6 +576,9 @@
*/
private void updateChildren() {
updateScrollStateForAddedChildren();
+ mAmbientState.setCurrentScrollVelocity(mScroller.isFinished()
+ ? 0
+ : mScroller.getCurrVelocity());
mAmbientState.setScrollY(mOwnScrollY);
mStackScrollAlgorithm.getStackScrollState(mAmbientState, mCurrentStackScrollState);
if (!isCurrentlyAnimating() && !mNeedsAnimation) {
@@ -715,7 +719,6 @@
requestChildrenUpdate();
}
setStackTranslation(translationY);
- requestChildrenUpdate();
}
private void setRequestedClipBounds(Rect clipRect) {
@@ -1185,7 +1188,7 @@
}
private boolean onKeyguard() {
- return mPhoneStatusBar.getBarState() == StatusBarState.KEYGUARD;
+ return mStatusBarState == StatusBarState.KEYGUARD;
}
private void setSwipingInProgress(boolean isSwiped) {
@@ -2122,7 +2125,7 @@
top = mTopPadding;
bottom = top;
}
- if (mPhoneStatusBar.getBarState() != StatusBarState.KEYGUARD) {
+ if (mStatusBarState != StatusBarState.KEYGUARD) {
top = (int) Math.max(mTopPadding + mStackTranslation, top);
} else {
// otherwise the animation from the shade to the keyguard will jump as it's maxed
@@ -2356,7 +2359,7 @@
}
break;
case MotionEvent.ACTION_UP:
- if (mPhoneStatusBar.getBarState() != StatusBarState.KEYGUARD && mTouchIsClick &&
+ if (mStatusBarState != StatusBarState.KEYGUARD && mTouchIsClick &&
isBelowLastNotification(mInitialTouchX, mInitialTouchY)) {
mOnEmptySpaceClickListener.onEmptySpaceClicked(mInitialTouchX, mInitialTouchY);
}
@@ -3121,10 +3124,12 @@
public void onExpansionStarted() {
mIsExpansionChanging = true;
+ mAmbientState.setExpansionChanging(true);
}
public void onExpansionStopped() {
mIsExpansionChanging = false;
+ mAmbientState.setExpansionChanging(false);
if (!mIsExpanded) {
setOwnScrollY(0);
mPhoneStatusBar.resetUserExpandedStates();
@@ -3152,9 +3157,11 @@
public void onPanelTrackingStarted() {
mPanelTracking = true;
+ mAmbientState.setPanelTracking(true);
}
public void onPanelTrackingStopped() {
mPanelTracking = false;
+ mAmbientState.setPanelTracking(false);
}
public void resetScrollPosition() {
@@ -3979,6 +3986,15 @@
updateClipping();
}
+ public void setStatusBarState(int statusBarState) {
+ mStatusBarState = statusBarState;
+ mAmbientState.setStatusBarState(statusBarState);
+ }
+
+ public void setExpandingVelocity(float expandingVelocity) {
+ mAmbientState.setExpandingVelocity(expandingVelocity);
+ }
+
/**
* 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 7afc7ba..50b6d70 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -124,7 +124,8 @@
private void updateClipping(StackScrollState resultState,
StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
- float drawStart = ambientState.getTopPadding() + ambientState.getStackTranslation();
+ float drawStart = !ambientState.isOnKeyguard() ? ambientState.getTopPadding()
+ + ambientState.getStackTranslation() : 0;
float previousNotificationEnd = 0;
float previousNotificationStart = 0;
int childCount = algorithmState.visibleChildren.size();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
index 8a5ddd4..b747592 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
@@ -99,36 +99,6 @@
// don't do anything with it
return;
}
- boolean becomesInvisible = this.alpha == 0.0f || this.hidden;
- boolean animatingAlpha = isAnimating(view, TAG_ANIMATOR_ALPHA);
- if (animatingAlpha) {
- updateAlphaAnimation(view);
- } else if (view.getAlpha() != this.alpha) {
- // apply layer type
- boolean becomesFullyVisible = this.alpha == 1.0f;
- boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible
- && view.hasOverlappingRendering();
- int layerType = view.getLayerType();
- int newLayerType = newLayerTypeIsHardware
- ? View.LAYER_TYPE_HARDWARE
- : View.LAYER_TYPE_NONE;
- if (layerType != newLayerType) {
- view.setLayerType(newLayerType, null);
- }
-
- // apply alpha
- view.setAlpha(this.alpha);
- }
-
- // apply visibility
- int oldVisibility = view.getVisibility();
- int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
- if (newVisibility != oldVisibility) {
- if (!(view instanceof ExpandableView) || !((ExpandableView) view).willBeGone()) {
- // We don't want views to change visibility when they are animating to GONE
- view.setVisibility(newVisibility);
- }
- }
// apply xTranslation
boolean animatingX = isAnimating(view, TAG_ANIMATOR_TRANSLATION_X);
@@ -163,6 +133,53 @@
if (view.getScaleY() != this.scaleY) {
view.setScaleY(this.scaleY);
}
+
+ boolean becomesInvisible = this.alpha == 0.0f || (this.hidden && !isAnimating(view));
+ boolean animatingAlpha = isAnimating(view, TAG_ANIMATOR_ALPHA);
+ if (animatingAlpha) {
+ updateAlphaAnimation(view);
+ } else if (view.getAlpha() != this.alpha) {
+ // apply layer type
+ boolean becomesFullyVisible = this.alpha == 1.0f;
+ boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible
+ && view.hasOverlappingRendering();
+ int layerType = view.getLayerType();
+ int newLayerType = newLayerTypeIsHardware
+ ? View.LAYER_TYPE_HARDWARE
+ : View.LAYER_TYPE_NONE;
+ if (layerType != newLayerType) {
+ view.setLayerType(newLayerType, null);
+ }
+
+ // apply alpha
+ view.setAlpha(this.alpha);
+ }
+
+ // apply visibility
+ int oldVisibility = view.getVisibility();
+ int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
+ if (newVisibility != oldVisibility) {
+ if (!(view instanceof ExpandableView) || !((ExpandableView) view).willBeGone()) {
+ // We don't want views to change visibility when they are animating to GONE
+ view.setVisibility(newVisibility);
+ }
+ }
+ }
+
+ protected boolean isAnimating(View view) {
+ if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_X)) {
+ return true;
+ }
+ if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_Y)) {
+ return true;
+ }
+ if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_Z)) {
+ return true;
+ }
+ if (isAnimating(view, TAG_ANIMATOR_ALPHA)) {
+ return true;
+ }
+ return false;
}
private boolean isAnimating(View view, int tag) {
@@ -482,7 +499,7 @@
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
child.setTag(TAG_START_TRANSLATION_Y, null);
child.setTag(TAG_END_TRANSLATION_Y, null);
- onYTranslationAnimationFinished();
+ onYTranslationAnimationFinished(child);
}
});
startAnimator(animator, listener);
@@ -491,7 +508,10 @@
child.setTag(TAG_END_TRANSLATION_Y, newEndValue);
}
- protected void onYTranslationAnimationFinished() {
+ protected void onYTranslationAnimationFinished(View view) {
+ if (hidden) {
+ view.setVisibility(View.INVISIBLE);
+ }
}
protected void startAnimator(Animator animator, AnimatorListenerAdapter listener) {
@@ -548,7 +568,26 @@
}
}
- public static boolean isAnimatingY(ExpandableView child) {
+ public static boolean isAnimatingY(View child) {
return getChildTag(child, TAG_ANIMATOR_TRANSLATION_Y) != null;
}
+
+ public void cancelAnimations(View view) {
+ Animator animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_X);
+ if (animator != null) {
+ animator.cancel();
+ }
+ animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Y);
+ if (animator != null) {
+ animator.cancel();
+ }
+ animator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Z);
+ if (animator != null) {
+ animator.cancel();
+ }
+ animator = getChildTag(view, TAG_ANIMATOR_ALPHA);
+ if (animator != null) {
+ animator.cancel();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index ebc962d..565ac08 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -92,6 +92,10 @@
mUserTracker.startTracking();
}
+ public void destroy() {
+ mUserTracker.stopTracking();
+ }
+
private void upgradeTuner(int oldVersion, int newVersion) {
if (oldVersion < 1) {
String blacklistStr = getValue(StatusBarIconController.ICON_BLACKLIST);
diff --git a/packages/SystemUI/src/com/android/systemui/util/LayoutInflaterBuilder.java b/packages/SystemUI/src/com/android/systemui/util/LayoutInflaterBuilder.java
new file mode 100644
index 0000000..f420921
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/LayoutInflaterBuilder.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Builder class to create a {@link LayoutInflater} with various properties.
+ *
+ * Call any desired configuration methods on the Builder and then use
+ * {@link Builder#build} to create the LayoutInflater. This is an alternative to directly using
+ * {@link LayoutInflater#setFilter} and {@link LayoutInflater#setFactory}.
+ * @hide for use by framework
+ */
+public class LayoutInflaterBuilder {
+ private static final String TAG = "LayoutInflaterBuilder";
+
+ private Context mFromContext;
+ private Context mTargetContext;
+ private Map<String, String> mReplaceMap;
+ private Set<Class> mDisallowedClasses;
+ private LayoutInflater mBuiltInflater;
+
+ /**
+ * Creates a new Builder which will construct a LayoutInflater.
+ *
+ * @param fromContext This context's LayoutInflater will be cloned by the Builder using
+ * {@link LayoutInflater#cloneInContext}. By default, the new LayoutInflater will point at
+ * this same Context.
+ */
+ public LayoutInflaterBuilder(@NonNull Context fromContext) {
+ mFromContext = fromContext;
+ mTargetContext = fromContext;
+ mReplaceMap = null;
+ mDisallowedClasses = null;
+ mBuiltInflater = null;
+ }
+
+ /**
+ * Instructs the Builder to point the LayoutInflater at a different Context.
+ *
+ * @param targetContext Context to be provided to
+ * {@link LayoutInflater#cloneInContext(Context)}.
+ * @return Builder object post-modification.
+ */
+ public LayoutInflaterBuilder target(@NonNull Context targetContext) {
+ assertIfAlreadyBuilt();
+ mTargetContext = targetContext;
+ return this;
+ }
+
+ /**
+ * Instructs the Builder to configure the LayoutInflater such that all instances
+ * of one {@link View} will be replaced with instances of another during inflation.
+ *
+ * @param from Instances of this class will be replaced during inflation.
+ * @param to Instances of this class will be inflated as replacements.
+ * @return Builder object post-modification.
+ */
+ public LayoutInflaterBuilder replace(@NonNull Class from, @NonNull Class to) {
+ assertIfAlreadyBuilt();
+ if (mReplaceMap == null) {
+ mReplaceMap = new ArrayMap<String, String>();
+ }
+ mReplaceMap.put(from.getName(), to.getName());
+ return this;
+ }
+
+ /**
+ * Instructs the Builder to configure the LayoutInflater such that any attempt to inflate
+ * a {@link View} of a given type will throw a {@link InflateException}.
+ *
+ * @param disallowedClass The Class type that will be disallowed.
+ * @return Builder object post-modification.
+ */
+ public LayoutInflaterBuilder disallow(@NonNull Class disallowedClass) {
+ assertIfAlreadyBuilt();
+ if (mDisallowedClasses == null) {
+ mDisallowedClasses = new ArraySet<Class>();
+ }
+ mDisallowedClasses.add(disallowedClass);
+ return this;
+ }
+
+ /**
+ * Builds and returns the LayoutInflater. Afterwards, this Builder can no longer can be
+ * used, all future calls on the Builder will throw {@link AssertionError}.
+ */
+ public LayoutInflater build() {
+ assertIfAlreadyBuilt();
+ mBuiltInflater =
+ LayoutInflater.from(mFromContext).cloneInContext(mTargetContext);
+ setFactoryIfNeeded(mBuiltInflater);
+ setFilterIfNeeded(mBuiltInflater);
+ return mBuiltInflater;
+ }
+
+ private void assertIfAlreadyBuilt() {
+ if (mBuiltInflater != null) {
+ throw new AssertionError("Cannot use this Builder after build() has been called.");
+ }
+ }
+
+ private void setFactoryIfNeeded(LayoutInflater inflater) {
+ if (mReplaceMap == null) {
+ return;
+ }
+ inflater.setFactory(
+ new LayoutInflater.Factory() {
+ @Override
+ public View onCreateView(String name, Context context, AttributeSet attrs) {
+ String replacingClassName = mReplaceMap.get(name);
+ if (replacingClassName != null) {
+ try {
+ return inflater.createView(replacingClassName, null, attrs);
+ } catch (ClassNotFoundException e) {
+ Log.e(TAG, "Could not replace " + name
+ + " with " + replacingClassName
+ + ", Exception: ", e);
+ }
+ }
+ return null;
+ }
+ });
+ }
+
+ private void setFilterIfNeeded(LayoutInflater inflater) {
+ if (mDisallowedClasses == null) {
+ return;
+ }
+ inflater.setFilter(
+ new LayoutInflater.Filter() {
+ @Override
+ public boolean onLoadClass(Class clazz) {
+ return !mDisallowedClasses.contains(clazz);
+ }
+ });
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
index ec0e4cd..bb5632b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
@@ -78,6 +78,7 @@
AudioSystem.STREAM_SYSTEM_ENFORCED,
AudioSystem.STREAM_TTS,
AudioSystem.STREAM_VOICE_CALL,
+ AudioSystem.STREAM_ACCESSIBILITY,
};
private final HandlerThread mWorkerThread;
@@ -119,7 +120,26 @@
mObserver = new SettingObserver(mWorker);
mObserver.init();
mReceiver.init();
- mStreamTitles = mContext.getResources().getStringArray(R.array.volume_stream_titles);
+ final String[] titles =
+ mContext.getResources().getStringArray(R.array.volume_stream_titles);
+ if (STREAMS.length == titles.length) {
+ mStreamTitles = titles;
+ } else if (STREAMS.length > titles.length) {
+ Log.e(TAG, String.format("Missing stream titles (found %d, expected %d): "
+ + " invalid resources for volume_stream_titles",
+ titles.length, STREAMS.length));
+ mStreamTitles = new String[STREAMS.length];
+ System.arraycopy(titles, 0, mStreamTitles, 0, titles.length);
+ for (int i = titles.length ; i < STREAMS.length ; i++) {
+ mStreamTitles[i] = "";
+ }
+ } else { // STREAMS.length < titles.length
+ Log.e(TAG, String.format("Too many stream titles (found %d, expected %d): "
+ + " invalid resources for volume_stream_titles",
+ titles.length, STREAMS.length));
+ mStreamTitles = new String[STREAMS.length];
+ System.arraycopy(titles, 0, mStreamTitles, 0, STREAMS.length);
+ }
mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
mHasVibrator = mVibrator != null && mVibrator.hasVibrator();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/FragmentTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/FragmentTestCase.java
index f87336c..447edac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/FragmentTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/FragmentTestCase.java
@@ -26,6 +26,8 @@
import android.view.View;
import android.widget.FrameLayout;
+import com.android.systemui.utils.leaks.LeakCheckedTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -139,7 +141,7 @@
private class HostCallbacks extends FragmentHostCallback<FragmentTestCase> {
public HostCallbacks() {
- super(getTrackedContext(), FragmentTestCase.this.mHandler, 0);
+ super(mContext, FragmentTestCase.this.mHandler, 0);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/LeakCheckedTest.java b/packages/SystemUI/tests/src/com/android/systemui/LeakCheckedTest.java
deleted file mode 100644
index d64669d..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/LeakCheckedTest.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.content.BroadcastReceiver;
-import android.content.ComponentCallbacks;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.ServiceConnection;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import com.android.systemui.statusbar.phone.ManagedProfileController;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BluetoothController;
-import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.DataSaverController;
-import com.android.systemui.statusbar.policy.FlashlightController;
-import com.android.systemui.statusbar.policy.HotspotController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.policy.SecurityController;
-import com.android.systemui.statusbar.policy.CallbackController;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.statusbar.policy.ZenModeController;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.rules.TestWatcher;
-import org.junit.runner.Description;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Base class for tests to check if receivers are left registered, services bound, or other
- * listeners listening.
- */
-public class LeakCheckedTest extends SysuiTestCase {
- private static final String TAG = "LeakCheckedTest";
-
- private final Map<String, Tracker> mTrackers = new HashMap<>();
- private final Map<Class, Object> mLeakCheckers = new ArrayMap<>();
- private TrackingContext mTrackedContext;
-
- @Rule
- public TestWatcher successWatcher = new TestWatcher() {
- @Override
- protected void succeeded(Description description) {
- verify();
- }
- };
-
- @Before
- public void setup() {
- mTrackedContext = new TrackingContext(mContext);
- addSupportedLeakCheckers();
- }
-
- public <T> T getLeakChecker(Class<T> cls) {
- T obj = (T) mLeakCheckers.get(cls);
- if (obj == null) {
- Assert.fail(cls.getName() + " is not supported by LeakCheckedTest yet");
- }
- return obj;
- }
-
- public Context getTrackedContext() {
- return mTrackedContext;
- }
-
- private Tracker getTracker(String tag) {
- Tracker t = mTrackers.get(tag);
- if (t == null) {
- t = new Tracker();
- mTrackers.put(tag, t);
- }
- return t;
- }
-
- public void verify() {
- mTrackers.values().forEach(Tracker::verify);
- }
-
- public static class Tracker {
- private Map<Object, LeakInfo> mObjects = new ArrayMap<>();
-
- LeakInfo getLeakInfo(Object object) {
- LeakInfo leakInfo = mObjects.get(object);
- if (leakInfo == null) {
- leakInfo = new LeakInfo();
- mObjects.put(object, leakInfo);
- }
- return leakInfo;
- }
-
- private void verify() {
- mObjects.values().forEach(LeakInfo::verify);
- }
- }
-
- public static class LeakInfo {
- private List<Throwable> mThrowables = new ArrayList<>();
-
- private LeakInfo() {
- }
-
- private void addAllocation(Throwable t) {
- // TODO: Drop off the first element in the stack trace here to have a cleaner stack.
- mThrowables.add(t);
- }
-
- private void clearAllocations() {
- mThrowables.clear();
- }
-
- public void verify() {
- if (mThrowables.size() == 0) return;
- Log.e(TAG, "Listener or binding not properly released");
- for (Throwable t : mThrowables) {
- Log.e(TAG, "Allocation found", t);
- }
- StringWriter writer = new StringWriter();
- mThrowables.get(0).printStackTrace(new PrintWriter(writer));
- Assert.fail("Listener or binding not properly released\n"
- + writer.toString());
- }
- }
-
- private void addSupportedLeakCheckers() {
- addListening("bluetooth", BluetoothController.class);
- addListening("location", LocationController.class);
- addListening("rotation", RotationLockController.class);
- addListening("zen", ZenModeController.class);
- addListening("cast", CastController.class);
- addListening("hotspot", HotspotController.class);
- addListening("flashlight", FlashlightController.class);
- addListening("user", UserInfoController.class);
- addListening("keyguard", KeyguardMonitor.class);
- addListening("battery", BatteryController.class);
- addListening("security", SecurityController.class);
- addListening("profile", ManagedProfileController.class);
- addListening("alarm", NextAlarmController.class);
- NetworkController network = addListening("network", NetworkController.class);
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- getTracker("emergency").getLeakInfo(invocation.getArguments()[0])
- .addAllocation(new Throwable());
- return null;
- }
- }).when(network).addEmergencyListener(any());
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- getTracker("emergency").getLeakInfo(invocation.getArguments()[0]).clearAllocations();
- return null;
- }
- }).when(network).removeEmergencyListener(any());
- DataSaverController datasaver = addListening("datasaver", DataSaverController.class);
- when(network.getDataSaverController()).thenReturn(datasaver);
- }
-
- private <T extends CallbackController> T addListening(final String tag, Class<T> cls) {
- T mock = mock(cls);
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- getTracker(tag).getLeakInfo(invocation.getArguments()[0])
- .addAllocation(new Throwable());
- return null;
- }
- }).when(mock).addCallback(any());
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- getTracker(tag).getLeakInfo(invocation.getArguments()[0]).clearAllocations();
- return null;
- }
- }).when(mock).removeCallback(any());
- mLeakCheckers.put(cls, mock);
- return mock;
- }
-
- class TrackingContext extends ContextWrapper {
- public TrackingContext(Context base) {
- super(base);
- }
-
- @Override
- public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
- getTracker("receiver").getLeakInfo(receiver).addAllocation(new Throwable());
- return super.registerReceiver(receiver, filter);
- }
-
- @Override
- public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
- String broadcastPermission, Handler scheduler) {
- getTracker("receiver").getLeakInfo(receiver).addAllocation(new Throwable());
- return super.registerReceiver(receiver, filter, broadcastPermission, scheduler);
- }
-
- @Override
- public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
- IntentFilter filter, String broadcastPermission, Handler scheduler) {
- getTracker("receiver").getLeakInfo(receiver).addAllocation(new Throwable());
- return super.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
- scheduler);
- }
-
- @Override
- public void unregisterReceiver(BroadcastReceiver receiver) {
- getTracker("receiver").getLeakInfo(receiver).clearAllocations();
- super.unregisterReceiver(receiver);
- }
-
- @Override
- public boolean bindService(Intent service, ServiceConnection conn, int flags) {
- getTracker("service").getLeakInfo(conn).addAllocation(new Throwable());
- return super.bindService(service, conn, flags);
- }
-
- @Override
- public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
- Handler handler, UserHandle user) {
- getTracker("service").getLeakInfo(conn).addAllocation(new Throwable());
- return super.bindServiceAsUser(service, conn, flags, handler, user);
- }
-
- @Override
- public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
- UserHandle user) {
- getTracker("service").getLeakInfo(conn).addAllocation(new Throwable());
- return super.bindServiceAsUser(service, conn, flags, user);
- }
-
- @Override
- public void unbindService(ServiceConnection conn) {
- getTracker("service").getLeakInfo(conn).clearAllocations();
- super.unbindService(conn);
- }
-
- @Override
- public void registerComponentCallbacks(ComponentCallbacks callback) {
- getTracker("component").getLeakInfo(callback).addAllocation(new Throwable());
- super.registerComponentCallbacks(callback);
- }
-
- @Override
- public void unregisterComponentCallbacks(ComponentCallbacks callback) {
- getTracker("component").getLeakInfo(callback).clearAllocations();
- super.unregisterComponentCallbacks(callback);
- }
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 5dac8e5..008580a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -22,6 +22,7 @@
import android.os.MessageQueue;
import com.android.systemui.utils.TestableContext;
+import com.android.systemui.utils.leaks.Tracker;
import org.junit.After;
import org.junit.Before;
@@ -29,14 +30,14 @@
/**
* Base class that does System UI specific setup.
*/
-public class SysuiTestCase {
+public abstract class SysuiTestCase {
private Handler mHandler;
protected TestableContext mContext;
@Before
public void SysuiSetup() throws Exception {
- mContext = new TestableContext(InstrumentationRegistry.getTargetContext());
+ mContext = new TestableContext(InstrumentationRegistry.getTargetContext(), this);
}
@After
@@ -71,6 +72,11 @@
}
}
+ // Used for leak tracking, returns null to indicate no leak tracking by default.
+ public Tracker getTracker(String tag) {
+ return null;
+ }
+
public static final class EmptyRunnable implements Runnable {
public void run() {
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 863f0e5..8b99d72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -202,6 +202,18 @@
@Test
@UiThreadTest
+ public void testPulseDuringPulse_doesntCrash() {
+ mMachine.requestState(INITIALIZED);
+
+ mMachine.requestState(DOZE);
+ mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestState(DOZE_PULSING);
+ mMachine.requestState(DOZE_REQUEST_PULSE);
+ mMachine.requestState(DOZE_PULSE_DONE);
+ }
+
+ @Test
+ @UiThreadTest
public void testScreen_offInDoze() {
mMachine.requestState(INITIALIZED);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
new file mode 100644
index 0000000..4c25c62e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Looper;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.SpannableStringBuilder;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.policy.SecurityController;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static junit.framework.Assert.assertEquals;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class QSFooterTest extends SysuiTestCase {
+
+ private final String MANAGING_ORGANIZATION = "organization";
+ private final String DEVICE_OWNER_PACKAGE = "TestDPC";
+ private final String VPN_PACKAGE = "TestVPN";
+
+ private ViewGroup mRootView = mock(ViewGroup.class);
+ private TextView mFooterText = mock(TextView.class);
+ private ImageView mFooterIcon = mock(ImageView.class);
+ private ImageView mFooterIcon2 = mock(ImageView.class);
+ private QSFooter mFooter;
+ private Resources mResources;
+ private SecurityController mSecurityController = mock(SecurityController.class);
+
+ @Before
+ public void setUp() {
+ when(mRootView.findViewById(R.id.footer_text)).thenReturn(mFooterText);
+ when(mRootView.findViewById(R.id.footer_icon)).thenReturn(mFooterIcon);
+ when(mRootView.findViewById(R.id.footer_icon2)).thenReturn(mFooterIcon2);
+ final LayoutInflater layoutInflater = mock(LayoutInflater.class);
+ when(layoutInflater.inflate(eq(R.layout.quick_settings_footer), anyObject(), anyBoolean()))
+ .thenReturn(mRootView);
+ final Context context = mock(Context.class);
+ when(context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).thenReturn(layoutInflater);
+ mResources = mContext.getResources();
+ when(context.getResources()).thenReturn(mResources);
+ mFooter = new QSFooter(null, context);
+ reset(mRootView);
+ mFooter.setHostEnvironment(null, mSecurityController, Looper.getMainLooper());
+ }
+
+ @Test
+ public void testUnmanaged() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(false);
+ when(mSecurityController.isVpnEnabled()).thenReturn(false);
+ when(mSecurityController.isVpnBranded()).thenReturn(false);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mRootView).setVisibility(View.GONE);
+ verifyNoMoreInteractions(mRootView);
+ }
+
+ @Test
+ public void testManagedNoOwnerName() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(true);
+ when(mSecurityController.getDeviceOwnerOrganizationName()).thenReturn(null);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mFooterText).setText(mResources.getString(R.string.do_disclosure_generic));
+ verifyNoMoreInteractions(mFooterText);
+ verify(mRootView).setVisibility(View.VISIBLE);
+ verifyNoMoreInteractions(mRootView);
+ }
+
+ @Test
+ public void testManagedOwnerName() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(true);
+ when(mSecurityController.getDeviceOwnerOrganizationName())
+ .thenReturn(MANAGING_ORGANIZATION);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mFooterText).setText(mResources.getString(R.string.do_disclosure_with_name,
+ MANAGING_ORGANIZATION));
+ verifyNoMoreInteractions(mFooterText);
+ verify(mRootView).setVisibility(View.VISIBLE);
+ verifyNoMoreInteractions(mRootView);
+ }
+
+ @Test
+ public void testNetworkLoggingEnabled() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(true);
+ when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
+ when(mSecurityController.isVpnEnabled()).thenReturn(false);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mFooterIcon).setVisibility(View.VISIBLE);
+ verify(mFooterIcon).setImageResource(R.drawable.ic_qs_network_logging);
+ verify(mFooterIcon2).setVisibility(View.INVISIBLE);
+ }
+
+ @Test
+ public void testVpnEnabled() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(true);
+ when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(false);
+ when(mSecurityController.isVpnEnabled()).thenReturn(true);
+ when(mSecurityController.isVpnBranded()).thenReturn(false);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mFooterIcon).setVisibility(View.VISIBLE);
+ verify(mFooterIcon, never()).setImageResource(anyInt());
+ verify(mFooterIcon2).setVisibility(View.INVISIBLE);
+ }
+
+ @Test
+ public void testNetworkLoggingAndVpnEnabled() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(true);
+ when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
+ when(mSecurityController.isVpnEnabled()).thenReturn(true);
+ when(mSecurityController.isVpnBranded()).thenReturn(false);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mFooterIcon).setVisibility(View.VISIBLE);
+ verify(mFooterIcon, never()).setImageResource(anyInt());
+ verify(mFooterIcon2).setVisibility(View.VISIBLE);
+ verify(mFooterIcon2, never()).setImageResource(anyInt());
+ }
+
+ @Test
+ public void testGetMessageWithNoOrganizationAndNoVPN() {
+ assertEquals(getExpectedMessage(false /* hasDeviceOwnerOrganization */, false /* hasVPN */),
+ mFooter.getMessage(DEVICE_OWNER_PACKAGE,
+ null /* profileOwnerPackage */,
+ null /* primaryVpn */,
+ null /* profileVpn */,
+ null /* deviceOwnerOrganization */,
+ false /* hasProfileOwner */,
+ false /* isBranded */));
+ }
+
+ @Test
+ public void testGetMessageWithNoOrganizationAndVPN() {
+ assertEquals(getExpectedMessage(false /* hasDeviceOwnerOrganization */, true /* hasVPN */),
+ mFooter.getMessage(DEVICE_OWNER_PACKAGE,
+ null /* profileOwnerPackage */,
+ VPN_PACKAGE,
+ null /* profileVpn */,
+ null /* deviceOwnerOrganization */,
+ false /* hasProfileOwner */,
+ false /* isBranded */));
+ }
+
+ @Test
+ public void testGetMessageWithOrganizationAndNoVPN() {
+ assertEquals(getExpectedMessage(true /* hasDeviceOwnerOrganization */, false /* hasVPN */),
+ mFooter.getMessage(DEVICE_OWNER_PACKAGE,
+ null /* profileOwnerPackage */,
+ null /* primaryVpn */,
+ null /* profileVpn */,
+ MANAGING_ORGANIZATION,
+ false /* hasProfileOwner */,
+ false /* isBranded */));
+ }
+
+ @Test
+ public void testGetMessageWithOrganizationAndVPN() {
+ assertEquals(getExpectedMessage(true /* hasDeviceOwnerOrganization */, true /* hasVPN */),
+ mFooter.getMessage(DEVICE_OWNER_PACKAGE,
+ null /* profileOwnerPackage */,
+ VPN_PACKAGE,
+ null /* profileVpn */,
+ MANAGING_ORGANIZATION,
+ false /* hasProfileOwner */,
+ false /* isBranded */));
+ }
+
+ private CharSequence getExpectedMessage(boolean hasDeviceOwnerOrganization, boolean hasVPN) {
+ final SpannableStringBuilder message = new SpannableStringBuilder();
+ message.append(hasDeviceOwnerOrganization ?
+ mResources.getString(R.string.monitoring_description_do_header_with_name,
+ MANAGING_ORGANIZATION, DEVICE_OWNER_PACKAGE) :
+ mResources.getString(R.string.monitoring_description_do_header_generic,
+ DEVICE_OWNER_PACKAGE));
+ message.append("\n\n");
+ message.append(mResources.getString(R.string.monitoring_description_do_body));
+ if (hasVPN) {
+ message.append("\n\n");
+ message.append(mResources.getString(R.string.monitoring_description_do_body_vpn,
+ VPN_PACKAGE));
+ }
+ message.append(mResources.getString(
+ R.string.monitoring_description_do_learn_more_separator));
+ message.append(mResources.getString(R.string.monitoring_description_do_learn_more),
+ mFooter.new EnterprisePrivacySpan(), 0);
+ return message;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 6ceaead..350a95f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -21,8 +21,10 @@
import android.support.test.runner.AndroidJUnit4;
import com.android.systemui.FragmentTestCase;
+import com.android.systemui.R;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.statusbar.phone.QuickStatusBarHeader;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
@@ -38,6 +40,7 @@
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.tuner.TunerService;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -59,7 +62,7 @@
KeyguardMonitor keyguardMonitor = getLeakChecker(KeyguardMonitor.class);
when(userSwitcher.getKeyguardMonitor()).thenReturn(keyguardMonitor);
when(userSwitcher.getUsers()).thenReturn(new ArrayList<>());
- QSTileHost host = new QSTileHost(getTrackedContext(),
+ QSTileHost host = new QSTileHost(mContext,
mock(PhoneStatusBar.class),
getLeakChecker(BluetoothController.class),
getLeakChecker(LocationController.class),
@@ -85,6 +88,12 @@
qs.setListening(false);
waitForIdleSync(h);
+ // Manually push header through detach so it can handle standard cleanup it does on
+ // removed from window.
+ ((QuickStatusBarHeader) qs.getView().findViewById(R.id.header)).onDetachedFromWindow();
+
host.destroy();
+ // Ensure the tuner cleans up its persistent listeners.
+ TunerService.get(mContext).destroy();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
new file mode 100644
index 0000000..9a697ee
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.net.ConnectivityManager;
+import android.os.UserManager;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SecurityControllerTest extends SysuiTestCase {
+ private final DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class);
+ private SecurityControllerImpl mSecurityController;
+
+ @Before
+ public void setUp() throws Exception {
+ final Context context = mock(Context.class);
+ when(context.getSystemService(Context.DEVICE_POLICY_SERVICE))
+ .thenReturn(mDevicePolicyManager);
+ when(context.getSystemService(Context.CONNECTIVITY_SERVICE))
+ .thenReturn(mock(ConnectivityManager.class));
+ final UserManager userManager = mock(UserManager.class);
+ when(userManager.getUserInfo(anyInt())).thenReturn(mock(UserInfo.class));
+ when(context.getSystemService(Context.USER_SERVICE))
+ .thenReturn(userManager);
+ mSecurityController = new SecurityControllerImpl(context);
+ }
+
+ @Test
+ public void testIsDeviceManaged() {
+ when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true);
+ assertTrue(mSecurityController.isDeviceManaged());
+
+ when(mDevicePolicyManager.isDeviceManaged()).thenReturn(false);
+ assertFalse(mSecurityController.isDeviceManaged());
+ }
+
+ @Test
+ public void testGetDeviceOwnerOrganizationName() {
+ when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn("organization");
+ assertEquals("organization", mSecurityController.getDeviceOwnerOrganizationName());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java b/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
index 5179823..bf73416 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
@@ -14,18 +14,31 @@
package com.android.systemui.utils;
+import android.content.BroadcastReceiver;
+import android.content.ComponentCallbacks;
import android.content.ContentProviderClient;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.UserHandle;
import android.provider.Settings;
+import com.android.systemui.utils.leaks.Tracker;
+import com.android.systemui.SysuiTestCase;
+
public class TestableContext extends ContextWrapper {
private final FakeContentResolver mFakeContentResolver;
private final FakeSettingsProvider mSettingsProvider;
- public TestableContext(Context base) {
+ private Tracker mReceiver;
+ private Tracker mService;
+ private Tracker mComponent;
+
+ public TestableContext(Context base, SysuiTestCase test) {
super(base);
mFakeContentResolver = new FakeContentResolver(base);
ContentProviderClient settings = base.getContentResolver()
@@ -33,6 +46,9 @@
mSettingsProvider = FakeSettingsProvider.getFakeSettingsProvider(settings,
mFakeContentResolver);
mFakeContentResolver.addProvider(Settings.AUTHORITY, mSettingsProvider);
+ mReceiver = test.getTracker("receiver");
+ mService = test.getTracker("service");
+ mComponent = test.getTracker("component");
}
public FakeSettingsProvider getSettingsProvider() {
@@ -49,4 +65,69 @@
// Return this so its always a TestableContext.
return this;
}
+
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+ if (mReceiver != null) mReceiver.getLeakInfo(receiver).addAllocation(new Throwable());
+ return super.registerReceiver(receiver, filter);
+ }
+
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
+ String broadcastPermission, Handler scheduler) {
+ if (mReceiver != null) mReceiver.getLeakInfo(receiver).addAllocation(new Throwable());
+ return super.registerReceiver(receiver, filter, broadcastPermission, scheduler);
+ }
+
+ @Override
+ public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+ IntentFilter filter, String broadcastPermission, Handler scheduler) {
+ if (mReceiver != null) mReceiver.getLeakInfo(receiver).addAllocation(new Throwable());
+ return super.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
+ scheduler);
+ }
+
+ @Override
+ public void unregisterReceiver(BroadcastReceiver receiver) {
+ if (mReceiver != null) mReceiver.getLeakInfo(receiver).clearAllocations();
+ super.unregisterReceiver(receiver);
+ }
+
+ @Override
+ public boolean bindService(Intent service, ServiceConnection conn, int flags) {
+ if (mService != null) mService.getLeakInfo(conn).addAllocation(new Throwable());
+ return super.bindService(service, conn, flags);
+ }
+
+ @Override
+ public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
+ Handler handler, UserHandle user) {
+ if (mService != null) mService.getLeakInfo(conn).addAllocation(new Throwable());
+ return super.bindServiceAsUser(service, conn, flags, handler, user);
+ }
+
+ @Override
+ public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
+ UserHandle user) {
+ if (mService != null) mService.getLeakInfo(conn).addAllocation(new Throwable());
+ return super.bindServiceAsUser(service, conn, flags, user);
+ }
+
+ @Override
+ public void unbindService(ServiceConnection conn) {
+ if (mService != null) mService.getLeakInfo(conn).clearAllocations();
+ super.unbindService(conn);
+ }
+
+ @Override
+ public void registerComponentCallbacks(ComponentCallbacks callback) {
+ if (mComponent != null) mComponent.getLeakInfo(callback).addAllocation(new Throwable());
+ super.registerComponentCallbacks(callback);
+ }
+
+ @Override
+ public void unregisterComponentCallbacks(ComponentCallbacks callback) {
+ if (mComponent != null) mComponent.getLeakInfo(callback).clearAllocations();
+ super.unregisterComponentCallbacks(callback);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/BaseLeakChecker.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/BaseLeakChecker.java
new file mode 100644
index 0000000..0238bf7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/BaseLeakChecker.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.CallbackController;
+
+public class BaseLeakChecker<T> implements CallbackController<T> {
+
+ private final Tracker mTracker;
+
+ public BaseLeakChecker(LeakCheckedTest test, String tag) {
+ mTracker = test.getTracker(tag);
+ }
+
+ protected final Tracker getTracker() {
+ return mTracker;
+ }
+
+ @Override
+ public void addCallback(T listener) {
+ mTracker.getLeakInfo(listener).addAllocation(new Throwable());
+ }
+
+ @Override
+ public void removeCallback(T listener) {
+ mTracker.getLeakInfo(listener).clearAllocations();
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java
new file mode 100644
index 0000000..fa07d33
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import android.os.Bundle;
+
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+public class FakeBatteryController extends BaseLeakChecker<BatteryStateChangeCallback>
+ implements BatteryController {
+ public FakeBatteryController(LeakCheckedTest test) {
+ super(test, "battery");
+ }
+
+ @Override
+ public void dispatchDemoCommand(String command, Bundle args) {
+
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+
+ }
+
+ @Override
+ public void setPowerSaveMode(boolean powerSave) {
+
+ }
+
+ @Override
+ public boolean isPowerSave() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java
new file mode 100644
index 0000000..6074a01
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.systemui.statusbar.policy.BluetoothController;
+import com.android.systemui.statusbar.policy.BluetoothController.Callback;
+
+import java.util.Collection;
+
+public class FakeBluetoothController extends BaseLeakChecker<Callback> implements
+ BluetoothController {
+
+ public FakeBluetoothController(LeakCheckedTest test) {
+ super(test, "bluetooth");
+ }
+
+ @Override
+ public boolean isBluetoothSupported() {
+ return false;
+ }
+
+ @Override
+ public boolean isBluetoothEnabled() {
+ return false;
+ }
+
+ @Override
+ public int getBluetoothState() {
+ return 0;
+ }
+
+ @Override
+ public boolean isBluetoothConnected() {
+ return false;
+ }
+
+ @Override
+ public boolean isBluetoothConnecting() {
+ return false;
+ }
+
+ @Override
+ public String getLastDeviceName() {
+ return null;
+ }
+
+ @Override
+ public void setBluetoothEnabled(boolean enabled) {
+
+ }
+
+ @Override
+ public Collection<CachedBluetoothDevice> getDevices() {
+ return null;
+ }
+
+ @Override
+ public void connect(CachedBluetoothDevice device) {
+
+ }
+
+ @Override
+ public void disconnect(CachedBluetoothDevice device) {
+
+ }
+
+ @Override
+ public boolean canConfigBluetooth() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeCastController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeCastController.java
new file mode 100644
index 0000000..08211f8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeCastController.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.CastController.Callback;
+
+import java.util.Set;
+
+public class FakeCastController extends BaseLeakChecker<Callback> implements CastController {
+ public FakeCastController(LeakCheckedTest test) {
+ super(test, "cast");
+ }
+
+ @Override
+ public void setDiscovering(boolean request) {
+
+ }
+
+ @Override
+ public void setCurrentUserId(int currentUserId) {
+
+ }
+
+ @Override
+ public Set<CastDevice> getCastDevices() {
+ return null;
+ }
+
+ @Override
+ public void startCasting(CastDevice device) {
+
+ }
+
+ @Override
+ public void stopCasting(CastDevice device) {
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeDataSaverController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeDataSaverController.java
new file mode 100644
index 0000000..857a785
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeDataSaverController.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.DataSaverController;
+import com.android.systemui.statusbar.policy.DataSaverController.Listener;
+
+public class FakeDataSaverController extends BaseLeakChecker<Listener> implements DataSaverController {
+
+ public FakeDataSaverController(LeakCheckedTest test) {
+ super(test, "datasaver");
+ }
+
+ @Override
+ public boolean isDataSaverEnabled() {
+ return false;
+ }
+
+ @Override
+ public void setDataSaverEnabled(boolean enabled) {
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeFlashlightController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeFlashlightController.java
new file mode 100644
index 0000000..630abd7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeFlashlightController.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.FlashlightController;
+import com.android.systemui.statusbar.policy.FlashlightController.FlashlightListener;
+
+public class FakeFlashlightController extends BaseLeakChecker<FlashlightListener>
+ implements FlashlightController {
+ public FakeFlashlightController(LeakCheckedTest test) {
+ super(test, "flashlight");
+ }
+
+ @Override
+ public boolean hasFlashlight() {
+ return false;
+ }
+
+ @Override
+ public void setFlashlight(boolean newState) {
+
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return false;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeHotspotController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeHotspotController.java
new file mode 100644
index 0000000..781960d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeHotspotController.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.HotspotController.Callback;
+
+public class FakeHotspotController extends BaseLeakChecker<Callback> implements HotspotController {
+
+ public FakeHotspotController(LeakCheckedTest test) {
+ super(test, "hotspot");
+ }
+
+ @Override
+ public boolean isHotspotEnabled() {
+ return false;
+ }
+
+ @Override
+ public void setHotspotEnabled(boolean enabled) {
+
+ }
+
+ @Override
+ public boolean isHotspotSupported() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
new file mode 100644
index 0000000..39bbf2d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+
+public class FakeKeyguardMonitor implements KeyguardMonitor {
+
+ private final BaseLeakChecker<Callback> mCallbackController;
+
+ public FakeKeyguardMonitor(LeakCheckedTest test) {
+ mCallbackController = new BaseLeakChecker<Callback>(test, "keyguard");
+ }
+
+ @Override
+ public void addCallback(Callback callback) {
+ mCallbackController.addCallback(callback);
+ }
+
+ @Override
+ public void removeCallback(Callback callback) {
+ mCallbackController.removeCallback(callback);
+ }
+
+ @Override
+ public boolean isSecure() {
+ return false;
+ }
+
+ @Override
+ public boolean isShowing() {
+ return false;
+ }
+
+ @Override
+ public boolean canSkipBouncer() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeLocationController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeLocationController.java
new file mode 100644
index 0000000..eab436c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeLocationController.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.LocationController.LocationSettingsChangeCallback;
+
+public class FakeLocationController extends BaseLeakChecker<LocationSettingsChangeCallback>
+ implements LocationController {
+ public FakeLocationController(LeakCheckedTest test) {
+ super(test, "location");
+ }
+
+ @Override
+ public boolean isLocationEnabled() {
+ return false;
+ }
+
+ @Override
+ public boolean setLocationEnabled(boolean enabled) {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeManagedProfileController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeManagedProfileController.java
new file mode 100644
index 0000000..0ec0d77
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeManagedProfileController.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.phone.ManagedProfileController;
+import com.android.systemui.statusbar.phone.ManagedProfileController.Callback;
+
+public class FakeManagedProfileController extends BaseLeakChecker<Callback> implements
+ ManagedProfileController {
+ public FakeManagedProfileController(LeakCheckedTest test) {
+ super(test, "profile");
+ }
+
+ @Override
+ public void setWorkModeEnabled(boolean enabled) {
+
+ }
+
+ @Override
+ public boolean hasActiveProfile() {
+ return false;
+ }
+
+ @Override
+ public boolean isWorkModeEnabled() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java
new file mode 100644
index 0000000..fcfe9aa
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.settingslib.net.DataUsageController;
+import com.android.systemui.statusbar.policy.DataSaverController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
+
+public class FakeNetworkController extends BaseLeakChecker<SignalCallback>
+ implements NetworkController {
+
+ private final FakeDataSaverController mDataSaverController;
+ private final BaseLeakChecker<EmergencyListener> mEmergencyChecker;
+
+ public FakeNetworkController(LeakCheckedTest test) {
+ super(test, "network");
+ mDataSaverController = new FakeDataSaverController(test);
+ mEmergencyChecker = new BaseLeakChecker<EmergencyListener>(test, "emergency");
+ }
+
+ @Override
+ public void addEmergencyListener(EmergencyListener listener) {
+ mEmergencyChecker.addCallback(listener);
+ }
+
+ @Override
+ public void removeEmergencyListener(EmergencyListener listener) {
+ mEmergencyChecker.removeCallback(listener);
+ }
+
+ @Override
+ public DataSaverController getDataSaverController() {
+ return mDataSaverController;
+ }
+
+ @Override
+ public boolean hasMobileDataFeature() {
+ return false;
+ }
+
+ @Override
+ public void setWifiEnabled(boolean enabled) {
+
+ }
+
+ @Override
+ public void onUserSwitched(int newUserId) {
+
+ }
+
+ @Override
+ public AccessPointController getAccessPointController() {
+ return null;
+ }
+
+ @Override
+ public DataUsageController getMobileDataController() {
+ return null;
+ }
+
+ @Override
+ public boolean hasVoiceCallingFeature() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNextAlarmController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNextAlarmController.java
new file mode 100644
index 0000000..707fc4b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNextAlarmController.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
+
+public class FakeNextAlarmController extends BaseLeakChecker<NextAlarmChangeCallback>
+ implements NextAlarmController {
+
+ public FakeNextAlarmController(LeakCheckedTest test) {
+ super(test, "alarm");
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeRotationLockController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeRotationLockController.java
new file mode 100644
index 0000000..00e2404
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeRotationLockController.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
+
+public class FakeRotationLockController extends BaseLeakChecker<RotationLockControllerCallback>
+ implements RotationLockController {
+ public FakeRotationLockController(LeakCheckedTest test) {
+ super(test, "rotation");
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+
+ }
+
+ @Override
+ public int getRotationLockOrientation() {
+ return 0;
+ }
+
+ @Override
+ public boolean isRotationLockAffordanceVisible() {
+ return false;
+ }
+
+ @Override
+ public boolean isRotationLocked() {
+ return false;
+ }
+
+ @Override
+ public void setRotationLocked(boolean locked) {
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java
new file mode 100644
index 0000000..2d53c77
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.SecurityController;
+import com.android.systemui.statusbar.policy.SecurityController.SecurityControllerCallback;
+
+public class FakeSecurityController extends BaseLeakChecker<SecurityControllerCallback>
+ implements SecurityController {
+ public FakeSecurityController(LeakCheckedTest test) {
+ super(test, "security");
+ }
+
+ @Override
+ public boolean isDeviceManaged() {
+ return false;
+ }
+
+ @Override
+ public boolean hasProfileOwner() {
+ return false;
+ }
+
+ @Override
+ public String getDeviceOwnerName() {
+ return null;
+ }
+
+ @Override
+ public String getProfileOwnerName() {
+ return null;
+ }
+
+ @Override
+ public CharSequence getDeviceOwnerOrganizationName() {
+ return null;
+ }
+
+ @Override
+ public boolean isNetworkLoggingEnabled() {
+ return false;
+ }
+
+ @Override
+ public boolean isVpnEnabled() {
+ return false;
+ }
+
+ @Override
+ public boolean isVpnRestricted() {
+ return false;
+ }
+
+ @Override
+ public boolean isVpnBranded() {
+ return false;
+ }
+
+ @Override
+ public String getPrimaryVpnName() {
+ return null;
+ }
+
+ @Override
+ public String getProfileVpnName() {
+ return null;
+ }
+
+ @Override
+ public void onUserSwitched(int newUserId) {
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeUserInfoController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeUserInfoController.java
new file mode 100644
index 0000000..578b310
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeUserInfoController.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
+
+public class FakeUserInfoController extends BaseLeakChecker<OnUserInfoChangedListener>
+ implements UserInfoController {
+ public FakeUserInfoController(LeakCheckedTest test) {
+ super(test, "user_info");
+ }
+
+ @Override
+ public void reloadUserInfo() {
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java
new file mode 100644
index 0000000..13ea385
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import android.content.ComponentName;
+import android.net.Uri;
+import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenModeConfig.ZenRule;
+
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.statusbar.policy.ZenModeController.Callback;
+
+public class FakeZenModeController extends BaseLeakChecker<Callback> implements ZenModeController {
+ public FakeZenModeController(LeakCheckedTest test) {
+ super(test, "zen");
+ }
+
+ @Override
+ public void setZen(int zen, Uri conditionId, String reason) {
+
+ }
+
+ @Override
+ public int getZen() {
+ return 0;
+ }
+
+ @Override
+ public ZenRule getManualRule() {
+ return null;
+ }
+
+ @Override
+ public ZenModeConfig getConfig() {
+ return null;
+ }
+
+ @Override
+ public long getNextAlarm() {
+ return 0;
+ }
+
+ @Override
+ public void setUserId(int userId) {
+
+ }
+
+ @Override
+ public boolean isZenAvailable() {
+ return false;
+ }
+
+ @Override
+ public ComponentName getEffectsSuppressor() {
+ return null;
+ }
+
+ @Override
+ public boolean isCountdownConditionSupported() {
+ return false;
+ }
+
+ @Override
+ public int getCurrentUser() {
+ return 0;
+ }
+
+ @Override
+ public boolean isVolumeRestricted() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
new file mode 100644
index 0000000..728ed60
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+
+import android.util.ArrayMap;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.phone.ManagedProfileController;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BluetoothController;
+import com.android.systemui.statusbar.policy.CallbackController;
+import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.FlashlightController;
+import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.policy.SecurityController;
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.ZenModeController;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Base class for tests to check if receivers are left registered, services bound, or other
+ * listeners listening.
+ */
+public abstract class LeakCheckedTest extends SysuiTestCase {
+ private static final String TAG = "LeakCheckedTest";
+
+ private final Map<String, Tracker> mTrackers = new HashMap<>();
+ private final Map<Class, Object> mLeakCheckers = new ArrayMap<>();
+
+ @Rule
+ public TestWatcher successWatcher = new TestWatcher() {
+ @Override
+ protected void succeeded(Description description) {
+ verify();
+ }
+ };
+
+ public <T> T getLeakChecker(Class<T> cls) {
+ Object obj = mLeakCheckers.get(cls);
+ if (obj == null) {
+ // Lazy create checkers so we only have the ones we need.
+ if (cls == BluetoothController.class) {
+ obj = new FakeBluetoothController(this);
+ } else if (cls == LocationController.class) {
+ obj = new FakeLocationController(this);
+ } else if (cls == RotationLockController.class) {
+ obj = new FakeRotationLockController(this);
+ } else if (cls == ZenModeController.class) {
+ obj = new FakeZenModeController(this);
+ } else if (cls == CastController.class) {
+ obj = new FakeCastController(this);
+ } else if (cls == HotspotController.class) {
+ obj = new FakeHotspotController(this);
+ } else if (cls == FlashlightController.class) {
+ obj = new FakeFlashlightController(this);
+ } else if (cls == UserInfoController.class) {
+ obj = new FakeUserInfoController(this);
+ } else if (cls == KeyguardMonitor.class) {
+ obj = new FakeKeyguardMonitor(this);
+ } else if (cls == BatteryController.class) {
+ obj = new FakeBatteryController(this);
+ } else if (cls == SecurityController.class) {
+ obj = new FakeSecurityController(this);
+ } else if (cls == ManagedProfileController.class) {
+ obj = new FakeManagedProfileController(this);
+ } else if (cls == NextAlarmController.class) {
+ obj = new FakeNextAlarmController(this);
+ } else if (cls == NetworkController.class) {
+ obj = new FakeNetworkController(this);
+ } else {
+ Assert.fail(cls.getName() + " is not supported by LeakCheckedTest yet");
+ }
+ mLeakCheckers.put(cls, obj);
+ }
+ return (T) obj;
+ }
+
+ @Override
+ public Tracker getTracker(String tag) {
+ Tracker t = mTrackers.get(tag);
+ if (t == null) {
+ t = new Tracker();
+ mTrackers.put(tag, t);
+ }
+ return t;
+ }
+
+ public void verify() {
+ mTrackers.values().forEach(Tracker::verify);
+ }
+
+ public <T extends CallbackController> T addListening(T mock, Class<T> cls, String tag) {
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ getTracker(tag).getLeakInfo(invocation.getArguments()[0])
+ .addAllocation(new Throwable());
+ return null;
+ }
+ }).when(mock).addCallback(any());
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ getTracker(tag).getLeakInfo(invocation.getArguments()[0]).clearAllocations();
+ return null;
+ }
+ }).when(mock).removeCallback(any());
+ mLeakCheckers.put(cls, mock);
+ return mock;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakInfo.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakInfo.java
new file mode 100644
index 0000000..1d016fb
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakInfo.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import android.util.Log;
+
+import org.junit.Assert;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+public class LeakInfo {
+ private static final String TAG = "LeakInfo";
+ private List<Throwable> mThrowables = new ArrayList<>();
+
+ LeakInfo() {
+ }
+
+ public void addAllocation(Throwable t) {
+ // TODO: Drop off the first element in the stack trace here to have a cleaner stack.
+ mThrowables.add(t);
+ }
+
+ public void clearAllocations() {
+ mThrowables.clear();
+ }
+
+ void verify() {
+ if (mThrowables.size() == 0) return;
+ Log.e(TAG, "Listener or binding not properly released");
+ for (Throwable t : mThrowables) {
+ Log.e(TAG, "Allocation found", t);
+ }
+ StringWriter writer = new StringWriter();
+ mThrowables.get(0).printStackTrace(new PrintWriter(writer));
+ Assert.fail("Listener or binding not properly released\n"
+ + writer.toString());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/Tracker.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/Tracker.java
new file mode 100644
index 0000000..26ffd10
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/Tracker.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.utils.leaks;
+
+import android.util.ArrayMap;
+
+import com.android.systemui.utils.leaks.LeakInfo;
+
+import java.util.Map;
+
+public class Tracker {
+ private Map<Object, LeakInfo> mObjects = new ArrayMap<>();
+
+ public LeakInfo getLeakInfo(Object object) {
+ LeakInfo leakInfo = mObjects.get(object);
+ if (leakInfo == null) {
+ leakInfo = new LeakInfo();
+ mObjects.put(object, leakInfo);
+ }
+ return leakInfo;
+ }
+
+ void verify() {
+ mObjects.values().forEach(LeakInfo::verify);
+ }
+}
diff --git a/preloaded-classes b/preloaded-classes
index a79ae50..da3861a 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -365,6 +365,8 @@
android.app.BackStackRecord
android.app.BackStackRecord$Op
android.app.BackStackRecord$TransitionState
+android.app.ContentProviderHolder
+android.app.ContentProviderHolder$1
android.app.ContextImpl
android.app.ContextImpl$ApplicationContentResolver
android.app.Dialog
@@ -383,8 +385,8 @@
android.app.FragmentManagerImpl$1
android.app.FragmentTransaction
android.app.IActivityManager
-android.app.IActivityManager$ContentProviderHolder
-android.app.IActivityManager$ContentProviderHolder$1
+android.app.IActivityManager$Stub
+android.app.IActivityManager$Stub$Proxy
android.app.IAlarmManager
android.app.IAlarmManager$Stub
android.app.IAlarmManager$Stub$Proxy
diff --git a/proto/src/ipconnectivity.proto b/proto/src/ipconnectivity.proto
index 29b318f..cf372bc 100644
--- a/proto/src/ipconnectivity.proto
+++ b/proto/src/ipconnectivity.proto
@@ -17,6 +17,22 @@
optional int32 network_id = 1;
};
+// Transport describes a physical technology used by a network. It is a subset
+// of the TRANSPORT_* constants defined in android.net.NetworkCapabilities.
+enum Transport {
+ UNKNOWN = 0;
+ BLUETOOTH = 1;
+ CELLULAR = 2;
+ ETHERNET = 3;
+ WIFI = 4;
+};
+
+// A pair of (key, value) integers for describing histogram-like statistics.
+message Pair {
+ optional int32 key = 1;
+ optional int32 value = 2;
+};
+
// Logs changes in the system default network. Changes can be 1) acquiring a
// default network with no previous default, 2) a switch of the system default
// network to a new default network, 3) a loss of the system default network.
@@ -49,7 +65,8 @@
// This message is associated to android.net.metrics.IpReachabilityEvent.
message IpReachabilityEvent {
// The interface name (wlan, rmnet, lo, ...) on which the probe was sent.
- optional string if_name = 1;
+ // Deprecated since version 2, replaced by transport field.
+ optional string if_name = 1 [deprecated = true];
// The event type code of the probe, represented by constants defined in
// android.net.metrics.IpReachabilityEvent.
@@ -93,6 +110,7 @@
// Logs DNS lookup latencies. Repeated fields must have the same length.
// This message is associated to android.net.metrics.DnsEvent.
+// Deprecated since version 2.
message DNSLookupBatch {
// The id of the network on which the DNS lookups took place.
optional NetworkId network_id = 1;
@@ -107,13 +125,62 @@
repeated int32 latencies_ms = 4;
};
+// Represents a collections of DNS lookup latencies and counters for a
+// particular combination of DNS query type and return code.
+// Since version 2.
+message DNSLatencies {
+ // The type of the DNS lookups, as defined in android.net.metrics.DnsEvent.
+ // Acts as a key for a set of DNS query results.
+ // Possible values are: 0 for getaddrinfo, 1 for gethostbyname.
+ optional int32 type = 1;
+
+ // The return value of the DNS resolver for the DNS lookups.
+ // Acts as a key for a set of DNS query results.
+ // Possible values are: 0 for success, or errno code for failures.
+ optional int32 return_code = 2;
+
+ // The number of query operations recorded.
+ optional int32 query_count = 3;
+
+ // The number of query operations returning A IPv4 records.
+ optional int32 a_count = 4;
+
+ // The number of query operations returning AAAA IPv6 records.
+ optional int32 aaaa_count = 5;
+
+ // The time it took for each DNS lookup to complete. The number of repeated
+ // values can be less than query_count in case of event rate-limiting.
+ repeated int32 latencies_ms = 6;
+};
+
+// Represents latency and errno statistics of the connect() system call.
+// Since version 2.
+message ConnectStatistics {
+ // The number of connect() operations recorded.
+ optional int32 connect_count = 1;
+
+ // The number of connect() operations with IPv6 socket address.
+ optional int32 ipv6_addr_count = 2;
+
+ // The time it took for each successful connect() operation to complete.
+ // The number of repeated values can be less than connect_count in case of
+ // event rate-limiting.
+ repeated int32 latencies_ms = 3;
+
+ // Counts of all error values returned by failed connect() operations.
+ // The Pair key field is the errno code. The Pair value field is the count
+ // for that errno code.
+ repeated Pair errnos_counters = 4;
+};
+
// Represents a DHCP event on a single interface, which can be a DHCPClient
// state transition or a response packet parsing error.
// This message is associated to android.net.metrics.DhcpClientEvent and
// android.net.metrics.DhcpErrorEvent.
message DHCPEvent {
// The interface name (wlan, rmnet, lo, ...) on which the event happened.
- optional string if_name = 1;
+ // Deprecated since version 2, replaced by transport field.
+ optional string if_name = 1 [deprecated = true];
oneof value {
// The name of a state in the DhcpClient state machine, represented by
@@ -217,7 +284,8 @@
// This message is associated to android.net.metrics.IpManagerEvent.
message IpProvisioningEvent {
// The interface name (wlan, rmnet, lo, ...) on which the probe was sent.
- optional string if_name = 1;
+ // Deprecated since version 2, replaced by transport field.
+ optional string if_name = 1 [deprecated = true];
// The code of the IP provisioning event, represented by constants defined in
// android.net.metrics.IpManagerEvent.
@@ -228,11 +296,15 @@
}
// Represents one of the IP connectivity event defined in this file.
-// Next tag: 12
+// Next tag: 15
message IpConnectivityEvent {
// Time in ms when the event was recorded.
optional int64 time_ms = 1;
+ // Physical transport of the network on which the event happened.
+ // Since version 2.
+ optional Transport transport = 12;
+
// Event type.
oneof event {
@@ -246,7 +318,14 @@
NetworkEvent network_event = 4;
// A batch of DNS lookups.
- DNSLookupBatch dns_lookup_batch = 5;
+ // Deprecated in the nyc-mr2 release since version 2, and replaced by dns_latencies.
+ DNSLookupBatch dns_lookup_batch = 5 [deprecated = true];
+
+ // DNS lookup latency statistics.
+ DNSLatencies dns_latencies = 13;
+
+ // Connect latency and errno statistics.
+ ConnectStatistics connect_statistics = 14;
// A DHCP client event or DHCP receive error.
DHCPEvent dhcp_event = 6;
@@ -277,9 +356,9 @@
optional int32 dropped_events = 2;
// The version number of the metrics events being collected.
- // nyc-dev: not populated, implicitly 0
- // nyc-dr1: not populated, implicitly 1 (sailfish and marlin only)
- // nyc-mr1: not populated, implicitly 1
- // nyc-mr2: 2
+ // nyc-dev: not populated, implicitly 0.
+ // nyc-dr1: not populated, implicitly 1 (sailfish and marlin only).
+ // nyc-mr1: not populated, implicitly 1.
+ // nyc-mr2: 2.
optional int32 version = 3;
};
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index f08408b..ef9d8f2 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3083,6 +3083,28 @@
// PACKAGE: The package name of the app the permission was revoked for
ACTION_PERMISSION_REVOKE_WRITE_EXTERNAL_STORAGE = 733;
+ // ACTION: Logged when a provisioning session has started
+ PROVISIONING_SESSION_STARTED = 734;
+
+ // ACTION: Logged when a provisioning session has completed
+ PROVISIONING_SESSION_COMPLETED = 735;
+
+ // ACTION: An app requested the permission READ_PHONE_NUMBER
+ // PACKAGE: The package name of the app requesting the permission
+ ACTION_PERMISSION_REQUEST_READ_PHONE_NUMBER = 736;
+
+ // ACTION: An app was granted the permission READ_PHONE_NUMBER
+ // PACKAGE: The package name of the app that was granted the permission
+ ACTION_PERMISSION_GRANT_READ_PHONE_NUMBER = 737;
+
+ // ACTION: An app requested the permission READ_PHONE_NUMBER and the request was denied
+ // PACKAGE: The package name of the app requesting the permission
+ ACTION_PERMISSION_DENIED_READ_PHONE_NUMBER = 738;
+
+ // ACTION: The permission READ_PHONE_NUMBER was revoked for an app
+ // PACKAGE: The package name of the app the permission was revoked for
+ ACTION_PERMISSION_REVOKE_READ_PHONE_NUMBER = 739;
+
// ---- End O Constants, all O constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index ab111a0..386fbc9 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -560,7 +560,7 @@
@Override
public void interrupt(int userId) {
- CopyOnWriteArrayList<Service> services;
+ List<IAccessibilityServiceClient> interfacesToInterrupt;
synchronized (mLock) {
// We treat calls from a profile as if made by its parent as profiles
// share the accessibility state of the parent. The call below
@@ -571,15 +571,24 @@
if (resolvedUserId != mCurrentUserId) {
return;
}
- services = getUserStateLocked(resolvedUserId).mBoundServices;
+ List<Service> services = getUserStateLocked(resolvedUserId).mBoundServices;
+ int numServices = services.size();
+ interfacesToInterrupt = new ArrayList<>(numServices);
+ for (int i = 0; i < numServices; i++) {
+ Service service = services.get(i);
+ IBinder a11yServiceBinder = service.mService;
+ IAccessibilityServiceClient a11yServiceInterface = service.mServiceInterface;
+ if ((a11yServiceBinder != null) && (a11yServiceInterface != null)) {
+ interfacesToInterrupt.add(a11yServiceInterface);
+ }
+ }
}
- for (int i = 0, count = services.size(); i < count; i++) {
- Service service = services.get(i);
+ for (int i = 0, count = interfacesToInterrupt.size(); i < count; i++) {
try {
- service.mServiceInterface.onInterrupt();
+ interfacesToInterrupt.get(i).onInterrupt();
} catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error during sending interrupt request to "
- + service.mService, re);
+ Slog.e(LOG_TAG, "Error sending interrupt request to "
+ + interfacesToInterrupt.get(i), re);
}
}
}
@@ -2843,15 +2852,8 @@
}
if (mMotionEventInjector != null) {
List<GestureDescription.GestureStep> steps = gestureSteps.getList();
- List<MotionEvent> events = GestureDescription.MotionEventGenerator
- .getMotionEventsFromGestureSteps(steps);
- // Confirm that the motion events end with an UP event.
- if (events.get(events.size() - 1).getAction() == MotionEvent.ACTION_UP) {
- mMotionEventInjector.injectEvents(events, mServiceInterface, sequence);
- return;
- } else {
- Slog.e(LOG_TAG, "Gesture is not well-formed");
- }
+ mMotionEventInjector.injectEvents(steps, mServiceInterface, sequence);
+ return;
} else {
Slog.e(LOG_TAG, "MotionEventInjector installation timed out");
}
diff --git a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
index 8042ddb..48041ad 100644
--- a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
+++ b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
@@ -16,49 +16,67 @@
package com.android.server.accessibility;
+import android.accessibilityservice.GestureDescription;
+import android.accessibilityservice.GestureDescription.GestureStep;
+import android.accessibilityservice.GestureDescription.TouchPoint;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.WindowManagerPolicy;
import android.view.accessibility.AccessibilityEvent;
import com.android.internal.os.SomeArgs;
-import com.android.server.accessibility.AccessibilityManagerService.Service;
+import java.util.ArrayList;
import java.util.List;
/**
* Injects MotionEvents to permit {@code AccessibilityService}s to touch the screen on behalf of
* users.
- *
+ * <p>
* All methods except {@code injectEvents} must be called only from the main thread.
*/
public class MotionEventInjector implements EventStreamTransformation, Handler.Callback {
private static final String LOG_TAG = "MotionEventInjector";
private static final int MESSAGE_SEND_MOTION_EVENT = 1;
private static final int MESSAGE_INJECT_EVENTS = 2;
- private static final int MAX_POINTERS = 11; // Non-binding maximum
+
+ /**
+ * Constants used to initialize all MotionEvents
+ */
+ private static final int EVENT_META_STATE = 0;
+ private static final int EVENT_BUTTON_STATE = 0;
+ private static final int EVENT_DEVICE_ID = 0;
+ private static final int EVENT_EDGE_FLAGS = 0;
+ private static final int EVENT_SOURCE = InputDevice.SOURCE_TOUCHSCREEN;
+ private static final int EVENT_FLAGS = 0;
+ private static final float EVENT_X_PRECISION = 1;
+ private static final float EVENT_Y_PRECISION = 1;
+
+ private static MotionEvent.PointerCoords[] sPointerCoords;
+ private static MotionEvent.PointerProperties[] sPointerProps;
private final Handler mHandler;
private final SparseArray<Boolean> mOpenGesturesInProgress = new SparseArray<>();
- // These two arrays must be the same length
- private MotionEvent.PointerProperties[] mPointerProperties =
- new MotionEvent.PointerProperties[MAX_POINTERS];
- private MotionEvent.PointerCoords[] mPointerCoords =
- new MotionEvent.PointerCoords[MAX_POINTERS];
private EventStreamTransformation mNext;
private IAccessibilityServiceClient mServiceInterfaceForCurrentGesture;
- private int mSequenceForCurrentGesture;
- private int mSourceOfInjectedGesture = InputDevice.SOURCE_UNKNOWN;
+ private IntArray mSequencesInProgress = new IntArray(5);
private boolean mIsDestroyed = false;
+ private TouchPoint[] mLastTouchPoints;
+ private int mNumLastTouchPoints;
+ private long mDownTime;
+ private long mLastScheduledEventTime;
+ private SparseIntArray mStrokeIdToPointerId = new SparseIntArray(5);
/**
* @param looper A looper on the main thread to use for dispatching new events
@@ -75,18 +93,18 @@
}
/**
- * Schedule a series of events for injection. These events must comprise a complete, valid
- * sequence. All gestures currently in progress will be cancelled, and all {@code downTime}
- * and {@code eventTime} fields will be offset by the current time.
+ * Schedule a gesture for injection. The gesture is defined by a set of {@code GestureStep}s,
+ * from which {@code MotionEvent}s will be derived. All gestures currently in progress will be
+ * cancelled.
*
- * @param events The events to inject. Must all be from the same source.
+ * @param gestureSteps The gesture steps to inject.
* @param serviceInterface The interface to call back with a result when the gesture is
* either complete or cancelled.
*/
- public void injectEvents(List<MotionEvent> events,
+ public void injectEvents(List<GestureStep> gestureSteps,
IAccessibilityServiceClient serviceInterface, int sequence) {
SomeArgs args = SomeArgs.obtain();
- args.arg1 = events;
+ args.arg1 = gestureSteps;
args.arg2 = serviceInterface;
args.argi1 = sequence;
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_INJECT_EVENTS, args));
@@ -138,7 +156,7 @@
public boolean handleMessage(Message message) {
if (message.what == MESSAGE_INJECT_EVENTS) {
SomeArgs args = (SomeArgs) message.obj;
- injectEventsMainThread((List<MotionEvent>) args.arg1,
+ injectEventsMainThread((List<GestureStep>) args.arg1,
(IAccessibilityServiceClient) args.arg2, args.argi1);
args.recycle();
return true;
@@ -148,16 +166,16 @@
return false;
}
MotionEvent motionEvent = (MotionEvent) message.obj;
- sendMotionEventToNext(motionEvent, motionEvent,
- WindowManagerPolicy.FLAG_PASS_TO_USER);
- // If the message queue is now empty, then this gesture is complete
- if (!mHandler.hasMessages(MESSAGE_SEND_MOTION_EVENT)) {
- notifyService(true);
+ sendMotionEventToNext(motionEvent, motionEvent, WindowManagerPolicy.FLAG_PASS_TO_USER);
+ boolean isEndOfSequence = message.arg1 != 0;
+ if (isEndOfSequence) {
+ notifyService(mServiceInterfaceForCurrentGesture, mSequencesInProgress.get(0), true);
+ mSequencesInProgress.remove(0);
}
return true;
}
- private void injectEventsMainThread(List<MotionEvent> events,
+ private void injectEventsMainThread(List<GestureStep> gestureSteps,
IAccessibilityServiceClient serviceInterface, int sequence) {
if (mIsDestroyed) {
try {
@@ -168,48 +186,110 @@
}
return;
}
- cancelAnyPendingInjectedEvents();
- mSourceOfInjectedGesture = events.get(0).getSource();
- cancelAnyGestureInProgress(mSourceOfInjectedGesture);
- mServiceInterfaceForCurrentGesture = serviceInterface;
- mSequenceForCurrentGesture = sequence;
+
if (mNext == null) {
- notifyService(false);
+ notifyService(serviceInterface, sequence, false);
return;
}
- long startTime = SystemClock.uptimeMillis();
+ boolean continuingGesture = newGestureTriesToContinueOldOne(gestureSteps);
+
+ if (continuingGesture) {
+ if ((serviceInterface != mServiceInterfaceForCurrentGesture)
+ || !prepareToContinueOldGesture(gestureSteps)) {
+ cancelAnyPendingInjectedEvents();
+ notifyService(serviceInterface, sequence, false);
+ return;
+ }
+ }
+ if (!continuingGesture) {
+ cancelAnyPendingInjectedEvents();
+ // Injected gestures have been canceled, but real gestures still need cancelling
+ cancelAnyGestureInProgress(EVENT_SOURCE);
+ }
+ mServiceInterfaceForCurrentGesture = serviceInterface;
+
+ long currentTime = SystemClock.uptimeMillis();
+ List<MotionEvent> events = getMotionEventsFromGestureSteps(gestureSteps,
+ (mSequencesInProgress.size() == 0) ? currentTime : mLastScheduledEventTime);
+ if (events.isEmpty()) {
+ notifyService(serviceInterface, sequence, false);
+ return;
+ }
+ mSequencesInProgress.add(sequence);
+
for (int i = 0; i < events.size(); i++) {
MotionEvent event = events.get(i);
- int numPointers = event.getPointerCount();
- if (numPointers > mPointerCoords.length) {
- mPointerCoords = new MotionEvent.PointerCoords[numPointers];
- mPointerProperties = new MotionEvent.PointerProperties[numPointers];
- }
- for (int j = 0; j < numPointers; j++) {
- if (mPointerCoords[j] == null) {
- mPointerCoords[j] = new MotionEvent.PointerCoords();
- mPointerProperties[j] = new MotionEvent.PointerProperties();
- }
- event.getPointerCoords(j, mPointerCoords[j]);
- event.getPointerProperties(j, mPointerProperties[j]);
- }
-
- /*
- * MotionEvent doesn't have a setEventTime() method (it carries around history data,
- * which could become inconsistent), so we need to obtain a new one.
- */
- MotionEvent offsetEvent = MotionEvent.obtain(startTime + event.getDownTime(),
- startTime + event.getEventTime(), event.getAction(), numPointers,
- mPointerProperties, mPointerCoords, event.getMetaState(),
- event.getButtonState(), event.getXPrecision(), event.getYPrecision(),
- event.getDeviceId(), event.getEdgeFlags(), event.getSource(),
- event.getFlags());
- Message message = mHandler.obtainMessage(MESSAGE_SEND_MOTION_EVENT, offsetEvent);
- mHandler.sendMessageDelayed(message, event.getEventTime());
+ int isEndOfSequence = (i == events.size() - 1) ? 1 : 0;
+ Message message = mHandler.obtainMessage(
+ MESSAGE_SEND_MOTION_EVENT, isEndOfSequence, 0, event);
+ mLastScheduledEventTime = event.getEventTime();
+ mHandler.sendMessageDelayed(message, Math.max(0, event.getEventTime() - currentTime));
}
}
+ private boolean newGestureTriesToContinueOldOne(List<GestureStep> gestureSteps) {
+ if (gestureSteps.isEmpty()) {
+ return false;
+ }
+ GestureStep firstStep = gestureSteps.get(0);
+ for (int i = 0; i < firstStep.numTouchPoints; i++) {
+ if (!firstStep.touchPoints[i].mIsStartOfPath) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * A gesture can only continue a gesture if it contains intermediate points that continue
+ * each continued stroke of the last gesture, and no extra points.
+ *
+ * @param gestureSteps The steps of the new gesture
+ * @return {@code true} if the new gesture could continue the last one dispatched. {@code false}
+ * otherwise.
+ */
+ private boolean prepareToContinueOldGesture(List<GestureStep> gestureSteps) {
+ if (gestureSteps.isEmpty() || (mLastTouchPoints == null) || (mNumLastTouchPoints == 0)) {
+ return false;
+ }
+ GestureStep firstStep = gestureSteps.get(0);
+ // Make sure all of the continuing paths match up
+ int numContinuedStrokes = 0;
+ for (int i = 0; i < firstStep.numTouchPoints; i++) {
+ TouchPoint touchPoint = firstStep.touchPoints[i];
+ if (!touchPoint.mIsStartOfPath) {
+ int continuedPointerId = mStrokeIdToPointerId
+ .get(touchPoint.mContinuedStrokeId, -1);
+ if (continuedPointerId == -1) {
+ return false;
+ }
+ mStrokeIdToPointerId.put(touchPoint.mStrokeId, continuedPointerId);
+ int lastPointIndex = findPointByStrokeId(
+ mLastTouchPoints, mNumLastTouchPoints, touchPoint.mContinuedStrokeId);
+ if (lastPointIndex < 0) {
+ return false;
+ }
+ if (mLastTouchPoints[lastPointIndex].mIsEndOfPath
+ || (mLastTouchPoints[lastPointIndex].mX != touchPoint.mX)
+ || (mLastTouchPoints[lastPointIndex].mY != touchPoint.mY)) {
+ return false;
+ }
+ // Update the last touch point to match the continuation, so the gestures will
+ // line up
+ mLastTouchPoints[lastPointIndex].mStrokeId = touchPoint.mStrokeId;
+ }
+ numContinuedStrokes++;
+ }
+ // Make sure we didn't miss any paths
+ for (int i = 0; i < mNumLastTouchPoints; i++) {
+ if (!mLastTouchPoints[i].mIsEndOfPath) {
+ numContinuedStrokes--;
+ }
+ }
+ return numContinuedStrokes == 0;
+ }
+
private void sendMotionEventToNext(MotionEvent event, MotionEvent rawEvent,
int policyFlags) {
if (mNext != null) {
@@ -228,7 +308,7 @@
if ((mNext != null) && mOpenGesturesInProgress.get(source, false)) {
long now = SystemClock.uptimeMillis();
MotionEvent cancelEvent =
- MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
+ obtainMotionEvent(now, now, MotionEvent.ACTION_CANCEL, getLastTouchPoints(), 1);
sendMotionEventToNext(cancelEvent, cancelEvent,
WindowManagerPolicy.FLAG_PASS_TO_USER);
mOpenGesturesInProgress.put(source, false);
@@ -237,19 +317,187 @@
private void cancelAnyPendingInjectedEvents() {
if (mHandler.hasMessages(MESSAGE_SEND_MOTION_EVENT)) {
- cancelAnyGestureInProgress(mSourceOfInjectedGesture);
mHandler.removeMessages(MESSAGE_SEND_MOTION_EVENT);
- notifyService(false);
+ cancelAnyGestureInProgress(EVENT_SOURCE);
+ for (int i = mSequencesInProgress.size() - 1; i >= 0; i--) {
+ notifyService(mServiceInterfaceForCurrentGesture,
+ mSequencesInProgress.get(i), false);
+ mSequencesInProgress.remove(i);
+ }
+ } else if (mNumLastTouchPoints != 0) {
+ // An injected gesture is in progress and waiting for a continuation. Cancel it.
+ cancelAnyGestureInProgress(EVENT_SOURCE);
}
+ mNumLastTouchPoints = 0;
+ mStrokeIdToPointerId.clear();
}
- private void notifyService(boolean success) {
+ private void notifyService(IAccessibilityServiceClient service, int sequence, boolean success) {
try {
- mServiceInterfaceForCurrentGesture.onPerformGestureResult(
- mSequenceForCurrentGesture, success);
+ service.onPerformGestureResult(sequence, success);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error sending motion event injection status to "
+ mServiceInterfaceForCurrentGesture, re);
}
}
+
+ private List<MotionEvent> getMotionEventsFromGestureSteps(
+ List<GestureStep> steps, long startTime) {
+ final List<MotionEvent> motionEvents = new ArrayList<>();
+
+ TouchPoint[] lastTouchPoints = getLastTouchPoints();
+
+ for (int i = 0; i < steps.size(); i++) {
+ GestureDescription.GestureStep step = steps.get(i);
+ int currentTouchPointSize = step.numTouchPoints;
+ if (currentTouchPointSize > lastTouchPoints.length) {
+ mNumLastTouchPoints = 0;
+ motionEvents.clear();
+ return motionEvents;
+ }
+
+ appendMoveEventIfNeeded(motionEvents, step.touchPoints, currentTouchPointSize,
+ startTime + step.timeSinceGestureStart);
+ appendUpEvents(motionEvents, step.touchPoints, currentTouchPointSize,
+ startTime + step.timeSinceGestureStart);
+ appendDownEvents(motionEvents, step.touchPoints, currentTouchPointSize,
+ startTime + step.timeSinceGestureStart);
+ }
+ return motionEvents;
+ }
+
+ private TouchPoint[] getLastTouchPoints() {
+ if (mLastTouchPoints == null) {
+ int capacity = GestureDescription.getMaxStrokeCount();
+ mLastTouchPoints = new TouchPoint[capacity];
+ for (int i = 0; i < capacity; i++) {
+ mLastTouchPoints[i] = new GestureDescription.TouchPoint();
+ }
+ }
+ return mLastTouchPoints;
+ }
+
+ private void appendMoveEventIfNeeded(List<MotionEvent> motionEvents,
+ TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
+ /* Look for pointers that have moved */
+ boolean moveFound = false;
+ TouchPoint[] lastTouchPoints = getLastTouchPoints();
+ for (int i = 0; i < currentTouchPointsSize; i++) {
+ int lastPointsIndex = findPointByStrokeId(lastTouchPoints, mNumLastTouchPoints,
+ currentTouchPoints[i].mStrokeId);
+ if (lastPointsIndex >= 0) {
+ moveFound |= (lastTouchPoints[lastPointsIndex].mX != currentTouchPoints[i].mX)
+ || (lastTouchPoints[lastPointsIndex].mY != currentTouchPoints[i].mY);
+ lastTouchPoints[lastPointsIndex].copyFrom(currentTouchPoints[i]);
+ }
+ }
+
+ if (moveFound) {
+ motionEvents.add(obtainMotionEvent(mDownTime, currentTime, MotionEvent.ACTION_MOVE,
+ lastTouchPoints, mNumLastTouchPoints));
+ }
+ }
+
+ private void appendUpEvents(List<MotionEvent> motionEvents,
+ TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
+ /* Look for a pointer at the end of its path */
+ TouchPoint[] lastTouchPoints = getLastTouchPoints();
+ for (int i = 0; i < currentTouchPointsSize; i++) {
+ if (currentTouchPoints[i].mIsEndOfPath) {
+ int indexOfUpEvent = findPointByStrokeId(lastTouchPoints, mNumLastTouchPoints,
+ currentTouchPoints[i].mStrokeId);
+ if (indexOfUpEvent < 0) {
+ continue; // Should not happen
+ }
+ int action = (mNumLastTouchPoints == 1) ? MotionEvent.ACTION_UP
+ : MotionEvent.ACTION_POINTER_UP;
+ action |= indexOfUpEvent << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ motionEvents.add(obtainMotionEvent(mDownTime, currentTime, action,
+ lastTouchPoints, mNumLastTouchPoints));
+ /* Remove this point from lastTouchPoints */
+ for (int j = indexOfUpEvent; j < mNumLastTouchPoints - 1; j++) {
+ lastTouchPoints[j].copyFrom(mLastTouchPoints[j + 1]);
+ }
+ mNumLastTouchPoints--;
+ if (mNumLastTouchPoints == 0) {
+ mStrokeIdToPointerId.clear();
+ }
+ }
+ }
+ }
+
+ private void appendDownEvents(List<MotionEvent> motionEvents,
+ TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
+ /* Look for a pointer that is just starting */
+ TouchPoint[] lastTouchPoints = getLastTouchPoints();
+ for (int i = 0; i < currentTouchPointsSize; i++) {
+ if (currentTouchPoints[i].mIsStartOfPath) {
+ /* Add the point to last coords and use the new array to generate the event */
+ lastTouchPoints[mNumLastTouchPoints++].copyFrom(currentTouchPoints[i]);
+ int action = (mNumLastTouchPoints == 1) ? MotionEvent.ACTION_DOWN
+ : MotionEvent.ACTION_POINTER_DOWN;
+ if (action == MotionEvent.ACTION_DOWN) {
+ mDownTime = currentTime;
+ }
+ action |= i << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ motionEvents.add(obtainMotionEvent(mDownTime, currentTime, action,
+ lastTouchPoints, mNumLastTouchPoints));
+ }
+ }
+ }
+
+ private MotionEvent obtainMotionEvent(long downTime, long eventTime, int action,
+ TouchPoint[] touchPoints, int touchPointsSize) {
+ if ((sPointerCoords == null) || (sPointerCoords.length < touchPointsSize)) {
+ sPointerCoords = new MotionEvent.PointerCoords[touchPointsSize];
+ for (int i = 0; i < touchPointsSize; i++) {
+ sPointerCoords[i] = new MotionEvent.PointerCoords();
+ }
+ }
+ if ((sPointerProps == null) || (sPointerProps.length < touchPointsSize)) {
+ sPointerProps = new MotionEvent.PointerProperties[touchPointsSize];
+ for (int i = 0; i < touchPointsSize; i++) {
+ sPointerProps[i] = new MotionEvent.PointerProperties();
+ }
+ }
+ for (int i = 0; i < touchPointsSize; i++) {
+ int pointerId = mStrokeIdToPointerId.get(touchPoints[i].mStrokeId, -1);
+ if (pointerId == -1) {
+ pointerId = getUnusedPointerId();
+ mStrokeIdToPointerId.put(touchPoints[i].mStrokeId, pointerId);
+ }
+ sPointerProps[i].id = pointerId;
+ sPointerProps[i].toolType = MotionEvent.TOOL_TYPE_UNKNOWN;
+ sPointerCoords[i].clear();
+ sPointerCoords[i].pressure = 1.0f;
+ sPointerCoords[i].size = 1.0f;
+ sPointerCoords[i].x = touchPoints[i].mX;
+ sPointerCoords[i].y = touchPoints[i].mY;
+ }
+ return MotionEvent.obtain(downTime, eventTime, action, touchPointsSize,
+ sPointerProps, sPointerCoords, EVENT_META_STATE, EVENT_BUTTON_STATE,
+ EVENT_X_PRECISION, EVENT_Y_PRECISION, EVENT_DEVICE_ID, EVENT_EDGE_FLAGS,
+ EVENT_SOURCE, EVENT_FLAGS);
+ }
+
+ private static int findPointByStrokeId(TouchPoint[] touchPoints, int touchPointsSize,
+ int strokeId) {
+ for (int i = 0; i < touchPointsSize; i++) {
+ if (touchPoints[i].mStrokeId == strokeId) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ private int getUnusedPointerId() {
+ int MAX_POINTER_ID = 10;
+ int pointerId = 0;
+ while (mStrokeIdToPointerId.indexOfValue(pointerId) >= 0) {
+ pointerId++;
+ if (pointerId >= MAX_POINTER_ID) {
+ return MAX_POINTER_ID;
+ }
+ }
+ return pointerId;
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
index d70c439..6a16131 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
@@ -18,10 +18,13 @@
import static android.Manifest.permission.MANAGE_AUTO_FILL;
import static android.content.Context.AUTO_FILL_MANAGER_SERVICE;
+import static android.view.View.ASSIST_FLAG_SANITIZED_TEXT;
+import static android.view.View.ASSIST_FLAG_NON_SANITIZED_TEXT;
import android.Manifest;
import android.app.AppGlobals;
import android.app.Notification;
+import android.app.Notification.Action;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -248,13 +251,14 @@
final class AutoFillManagerServiceStub extends IAutoFillManagerService.Stub {
@Override
- public void requestAutoFill(int userId, IBinder activityToken) {
+ public void requestAutoFill(IBinder activityToken, int userId, int flags) {
+ if (DEBUG) Slog.d(TAG, "requestAutoFill: flags=" + flags + ", userId=" + userId);
mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
synchronized (mLock) {
final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
if (service != null) {
- service.requestAutoFill(activityToken);
+ service.requestAutoFill(activityToken, flags);
}
}
}
@@ -307,7 +311,7 @@
synchronized (mLock) {
removeCachedServiceForUserLocked(userId);
final ComponentName serviceComponent = getProviderForUser(userId);
- if (serviceComponent== null) {
+ if (serviceComponent == null) {
cancelNotificationLocked(userId);
} else {
showNotification(serviceComponent, userId);
@@ -322,9 +326,10 @@
////////////////////////////////////////////////////////////////////////////
// TODO: remove from frameworks/base/core/res/AndroidManifest.xml once it's not used anymore
- private static final String NOTIFICATION_INTENT =
+ private static final String NOTIFICATION_AUTO_FILL_INTENT =
"com.android.internal.autofill.action.REQUEST_AUTOFILL";
private static final String EXTRA_USER_ID = "user_id";
+ private static final String EXTRA_FLAGS = "flags";
private static final int MSG_SHOW_ALL_NOTIFICATIONS = 42;
private static final int SHOW_ALL_NOTIFICATIONS_DELAY_MS = 5000;
@@ -335,13 +340,14 @@
@Override
public void onReceive(Context context, Intent intent) {
final int userId = intent.getIntExtra(EXTRA_USER_ID, -1);
+ final int flags = intent.getIntExtra(EXTRA_FLAGS, 0);
if (DEBUG) Slog.d(TAG, "Requesting autofill by notification for user " + userId);
synchronized (mLock) {
final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
if (service == null) {
Slog.w(TAG, "no auto-fill service for user " + userId);
} else {
- service.requestAutoFill(null);
+ service.requestAutoFill(null, flags);
}
}
}
@@ -393,14 +399,23 @@
if (mNotificationReceiver == null) {
mNotificationReceiver = new NotificationReceiver();
mContext.registerReceiver(mNotificationReceiver,
- new IntentFilter(NOTIFICATION_INTENT));
+ new IntentFilter(NOTIFICATION_AUTO_FILL_INTENT));
}
}
- final Intent intent = new Intent(NOTIFICATION_INTENT);
- intent.putExtra(EXTRA_USER_ID, userId);
- final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent,
- PendingIntent.FLAG_UPDATE_CURRENT);
+ final Intent fillIntent = new Intent(NOTIFICATION_AUTO_FILL_INTENT);
+ fillIntent.putExtra(EXTRA_USER_ID, userId);
+ fillIntent.putExtra(EXTRA_FLAGS, ASSIST_FLAG_SANITIZED_TEXT);
+ final PendingIntent fillPendingIntent = PendingIntent.getBroadcast(mContext,
+ ASSIST_FLAG_SANITIZED_TEXT, fillIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ final Action fillAction = new Action.Builder(null, "FILL", fillPendingIntent).build();
+
+ final Intent saveIntent = new Intent(NOTIFICATION_AUTO_FILL_INTENT);
+ saveIntent.putExtra(EXTRA_USER_ID, userId);
+ saveIntent.putExtra(EXTRA_FLAGS, ASSIST_FLAG_NON_SANITIZED_TEXT);
+ final PendingIntent savePendingIntent = PendingIntent.getBroadcast(mContext,
+ ASSIST_FLAG_NON_SANITIZED_TEXT, saveIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ final Action saveAction = new Action.Builder(null, "SAVE", savePendingIntent).build();
final String packageName = serviceComponent.getPackageName();
String providerName = null;
@@ -413,8 +428,8 @@
} catch (Exception e) {
providerName = packageName;
}
- final String title = "AutoFill by '" + providerName + "'";
- final String subTitle = "Tap notification to auto-fill top activity for user " + userId;
+ final String title = "AutoFill actions";
+ final String subTitle = "Provider: " + providerName + "\n" + "User: " + userId;
final Notification notification = new Notification.Builder(mContext)
.setCategory(Notification.CATEGORY_SYSTEM)
@@ -425,7 +440,7 @@
com.android.internal.R.color.system_notification_accent_color))
.setContentTitle(title)
.setStyle(new Notification.BigTextStyle().bigText(subTitle))
- .setContentIntent(pi)
+ .setActions(fillAction, saveAction)
.build();
NotificationManager.from(mContext).notify(userId, notification);
}
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index e409cb0..82356c8 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -47,7 +47,6 @@
import com.android.server.LocalServices;
import java.io.PrintWriter;
-import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
@@ -70,13 +69,13 @@
private final AutoFillServiceInfo mInfo;
private final AutoFillManagerService mManagerService;
- // TODO: improve its usage
+ // TODO(b/33197203): improve its usage
// - set maximum number of entries
// - disable on low-memory devices.
private final List<String> mRequestHistory = new LinkedList<>();
@GuardedBy("mLock")
- private final List<IBinder> mQueuedRequests = new LinkedList<>();
+ private final List<QueuedRequest> mQueuedRequests = new LinkedList<>();
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -84,7 +83,8 @@
if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
final String reason = intent.getStringExtra("reason");
if (DEBUG) Slog.d(TAG, "close system dialogs: " + reason);
- // TODO: close any pending UI like account selection (or remove this receiver)
+ // TODO(b/33197203): close any pending UI like account selection (or remove this
+ // receiver)
}
}
};
@@ -104,8 +104,8 @@
if (!mQueuedRequests.isEmpty()) {
if (DEBUG) Log.d(TAG, "queued requests:" + mQueuedRequests.size());
}
- for (IBinder activityToken : mQueuedRequests) {
- requestAutoFillLocked(activityToken, false);
+ for (final QueuedRequest request: mQueuedRequests) {
+ requestAutoFillLocked(request.activityToken, request.flags, false);
}
}
}
@@ -180,7 +180,7 @@
if (DEBUG) Slog.d(TAG, "Bound to " + mComponent);
}
- void requestAutoFill(IBinder activityToken) {
+ void requestAutoFill(IBinder activityToken, int flags) {
synchronized (mLock) {
if (!mBound) {
Slog.w(TAG, "requestAutoFill() failed because it's not bound to service");
@@ -188,14 +188,14 @@
}
}
- // TODO: activityToken should probably not be null, but we need to wait until the UI is
- // triggering the call (for now it's trough 'adb shell cmd autofill request'
+ // TODO(b/33197203): activityToken should probably not be null, but we need to wait until
+ // the UI is triggering the call (for now it's trough 'adb shell cmd autofill request'
if (activityToken == null) {
// Let's get top activities from all visible stacks.
- // TODO: overload getTopVisibleActivities() to take userId, otherwise it could return
- // activities for different users when a work profile app is displayed in another
- // window (in a multi-window environment).
+ // TODO(b/33197203): overload getTopVisibleActivities() to take userId, otherwise it
+ // could return activities for different users when a work profile app is displayed in
+ // another window (in a multi-window environment).
final List<IBinder> topActivities = LocalServices
.getService(ActivityManagerInternal.class).getTopVisibleActivities();
if (DEBUG)
@@ -211,32 +211,34 @@
DateFormat.getDateTimeInstance().format(new Date()) + " - " + activityToken;
synchronized (mLock) {
mRequestHistory.add(historyItem);
- requestAutoFillLocked(activityToken, true);
+ requestAutoFillLocked(activityToken, flags, true);
}
}
- private void requestAutoFillLocked(IBinder activityToken, boolean queueIfNecessary) {
+ private void requestAutoFillLocked(IBinder activityToken, int flags, boolean queueIfNecessary) {
if (mService == null) {
if (!queueIfNecessary) {
Slog.w(TAG, "requestAutoFillLocked(): service is null");
return;
}
if (DEBUG) Slog.d(TAG, "requestAutoFill(): service not set yet, queuing it");
- mQueuedRequests.add(activityToken);
+ mQueuedRequests.add(new QueuedRequest(activityToken, flags));
return;
}
/*
- * TODO: apply security checks below:
+ * TODO(b/33197203): apply security checks below:
* - checks if disabled by secure settings / device policy
* - log operation using noteOp()
* - check flags
* - display disclosure if needed
*/
try {
- // TODO: add MetricsLogger call
- if (!mAm.requestAutoFillData(mService.getAssistReceiver(), null, activityToken)) {
- // TODO: might need a way to warn user (perhaps a new method on AutoFillService).
+ // TODO(b/33197203): add MetricsLogger call
+ if (!mAm.requestAutoFillData(mService.getAssistReceiver(), null, activityToken,
+ flags)) {
+ // TODO(b/33197203): might need a way to warn user (perhaps a new method on
+ // AutoFillService).
Slog.w(TAG, "failed to request auto-fill data for " + activityToken);
}
} catch (RemoteException e) {
@@ -322,4 +324,19 @@
return "[AutoFillManagerServiceImpl: userId=" + mUserId + ", uid=" + mUid
+ ", component=" + mComponent.flattenToShortString() + "]";
}
+
+ private static final class QueuedRequest {
+ final IBinder activityToken;
+ final int flags;
+
+ QueuedRequest(IBinder activityToken, int flags) {
+ this.activityToken = activityToken;
+ this.flags = flags;
+ }
+
+ @Override
+ public String toString() {
+ return "flags: " + flags + " token: " + activityToken;
+ }
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
index 6406b8a..aa3503b 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
@@ -16,6 +16,9 @@
package com.android.server.autofill;
+import static android.view.View.ASSIST_FLAG_SANITIZED_TEXT;
+import static android.view.View.ASSIST_FLAG_NON_SANITIZED_TEXT;
+
import android.app.ActivityManager;
import android.os.RemoteException;
import android.os.ShellCommand;
@@ -40,8 +43,10 @@
final PrintWriter pw = getOutPrintWriter();
try {
switch (cmd) {
- case "request":
- return requestAutoFill();
+ case "fill":
+ return requestAutoFill(ASSIST_FLAG_SANITIZED_TEXT);
+ case "save":
+ return requestAutoFill(ASSIST_FLAG_NON_SANITIZED_TEXT);
default:
return handleDefaultCommands(cmd);
}
@@ -58,15 +63,17 @@
pw.println(" help");
pw.println(" Prints this help text.");
pw.println("");
- pw.println(" request [--user USER_ID]");
- pw.println(" Request auto-fill on the top activity. ");
+ pw.println(" fill [--user USER_ID]");
+ pw.println(" Request provider to auto-fill the top activity. ");
+ pw.println(" save [--user USER_ID]");
+ pw.println(" Request provider to save contents of the top activity. ");
pw.println("");
}
}
- private int requestAutoFill() throws RemoteException {
+ private int requestAutoFill(int flags) throws RemoteException {
final int userId = getUserIdFromArgs();
- mService.requestAutoFill(userId, null);
+ mService.requestAutoFill(null, userId, flags);
return 0;
}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 8151c8a..31ecb75 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2399,16 +2399,15 @@
} catch (InterruptedException e) {
// just bail
Slog.w(TAG, "Interrupted: " + e);
- mActivityManager.clearPendingBackup();
- return null;
+ mConnecting = false;
+ mConnectedAgent = null;
}
}
// if we timed out with no connect, abort and move on
if (mConnecting == true) {
Slog.w(TAG, "Timeout waiting for agent " + app);
- mActivityManager.clearPendingBackup();
- return null;
+ mConnectedAgent = null;
}
if (DEBUG) Slog.i(TAG, "got agent " + mConnectedAgent);
agent = mConnectedAgent;
@@ -2417,6 +2416,13 @@
// can't happen - ActivityManager is local
}
}
+ if (agent == null) {
+ try {
+ mActivityManager.clearPendingBackup();
+ } catch (RemoteException e) {
+ // can't happen - ActivityManager is local
+ }
+ }
return agent;
}
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 88a8385..efadbef 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -12,6 +12,7 @@
java/com/android/server/am/EventLogTags.logtags \
../../../../system/netd/server/binder/android/net/INetd.aidl \
../../../../system/netd/server/binder/android/net/metrics/INetdEventListener.aidl \
+ ../../../native/cmds/installd/binder/android/os/IInstalld.aidl \
LOCAL_AIDL_INCLUDES += \
system/netd/server/binder
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index f7068cf..b0c5603 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -42,6 +42,7 @@
import android.database.ContentObserver;
import android.os.Binder;
import android.os.Build;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -52,6 +53,8 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.UserManagerInternal;
+import android.os.UserManagerInternal.UserRestrictionsListener;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Slog;
@@ -177,6 +180,24 @@
}
};
+ private final UserRestrictionsListener mUserRestrictionsListener =
+ new UserRestrictionsListener() {
+ @Override
+ public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
+ Bundle prevRestrictions) {
+ final boolean bluetoothDisallowed =
+ newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH);
+ if ((mEnable || mEnableExternal) && bluetoothDisallowed) {
+ try {
+ disable(null, true);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Exception when disabling Bluetooth from UserRestrictionsListener",
+ e);
+ }
+ }
+ }
+ };
+
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -634,6 +655,13 @@
public boolean enableNoAutoConnect()
{
+ if (isBluetoothDisallowed()) {
+ if (DBG) {
+ Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed");
+ }
+ return false;
+ }
+
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
@@ -659,6 +687,13 @@
final int callingUid = Binder.getCallingUid();
final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
+ if (isBluetoothDisallowed()) {
+ if (DBG) {
+ Slog.d(TAG,"enable(): not enabling - bluetooth disallowed");
+ }
+ return false;
+ }
+
if (!callerSystem) {
if (!checkIfCallerIsForegroundUser()) {
Slog.w(TAG, "enable(): not allowed for non-active and non system user");
@@ -872,6 +907,12 @@
*/
public void handleOnBootPhase() {
if (DBG) Slog.d(TAG, "Bluetooth boot completed");
+ UserManagerInternal userManagerInternal =
+ LocalServices.getService(UserManagerInternal.class);
+ userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
+ if (isBluetoothDisallowed()) {
+ return;
+ }
if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth.");
sendEnableMsg(mQuietEnableExternal);
@@ -1916,6 +1957,16 @@
}
}
+ private boolean isBluetoothDisallowed() {
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ return mContext.getSystemService(UserManager.class)
+ .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM);
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 5eceb9f1..7572dfe 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -720,16 +720,6 @@
mHandler = new InternalHandler(mHandlerThread.getLooper());
mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
- // setup our unique device name
- if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) {
- String id = Settings.Secure.getString(context.getContentResolver(),
- Settings.Secure.ANDROID_ID);
- if (id != null && id.length() > 0) {
- String name = new String("android-").concat(id);
- SystemProperties.set("net.hostname", name);
- }
- }
-
mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
@@ -866,6 +856,7 @@
mAvoidBadWifiTracker = createAvoidBadWifiTracker(
mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
+ mAvoidBadWifiTracker.start();
}
private NetworkRequest createInternetRequestForTransport(
@@ -4606,28 +4597,9 @@
} catch (Exception e) {
loge("Exception in setDnsConfigurationForNetwork: " + e);
}
- final NetworkAgentInfo defaultNai = getDefaultNetwork();
- if (defaultNai != null && defaultNai.network.netId == netId) {
- setDefaultDnsSystemProperties(dnses);
- }
flushVmDnsCache();
}
- private void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
- int last = 0;
- for (InetAddress dns : dnses) {
- ++last;
- String key = "net.dns" + last;
- String value = dns.getHostAddress();
- SystemProperties.set(key, value);
- }
- for (int i = last + 1; i <= mNumDnsEntries; ++i) {
- String key = "net.dns" + i;
- SystemProperties.set(key, "");
- }
- mNumDnsEntries = last;
- }
-
private String getNetworkPermission(NetworkCapabilities nc) {
// TODO: make these permission strings AIDL constants instead.
if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
@@ -4844,7 +4816,6 @@
notifyLockdownVpn(newNetwork);
handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
updateTcpBufferSizes(newNetwork);
- setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
}
private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 8092b4a..9f63e30 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -211,7 +211,10 @@
private long mMaintenanceStartTime;
private int mActiveIdleOpCount;
- private PowerManager.WakeLock mActiveIdleWakeLock;
+ private PowerManager.WakeLock mActiveIdleWakeLock; // held when there are operations in progress
+ private PowerManager.WakeLock mGoingIdleWakeLock; // held when we are going idle so hardware
+ // (especially NetworkPolicyManager) can shut
+ // down.
private boolean mJobsActive;
private boolean mAlarmsActive;
private boolean mReportedMaintenanceActivity;
@@ -998,14 +1001,14 @@
}
}
- static final int MSG_WRITE_CONFIG = 1;
- static final int MSG_REPORT_IDLE_ON = 2;
- static final int MSG_REPORT_IDLE_ON_LIGHT = 3;
- static final int MSG_REPORT_IDLE_OFF = 4;
- static final int MSG_REPORT_ACTIVE = 5;
- static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
- static final int MSG_REPORT_MAINTENANCE_ACTIVITY = 7;
- static final int MSG_FINISH_IDLE_OP = 8;
+ private static final int MSG_WRITE_CONFIG = 1;
+ private static final int MSG_REPORT_IDLE_ON = 2;
+ private static final int MSG_REPORT_IDLE_ON_LIGHT = 3;
+ private static final int MSG_REPORT_IDLE_OFF = 4;
+ private static final int MSG_REPORT_ACTIVE = 5;
+ private static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
+ private static final int MSG_REPORT_MAINTENANCE_ACTIVITY = 7;
+ private static final int MSG_FINISH_IDLE_OP = 8;
final class MyHandler extends Handler {
MyHandler(Looper looper) {
@@ -1016,10 +1019,12 @@
if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")");
switch (msg.what) {
case MSG_WRITE_CONFIG: {
+ // Does not hold a wakelock. Just let this happen whenever.
handleWriteConfigFile();
} break;
case MSG_REPORT_IDLE_ON:
case MSG_REPORT_IDLE_ON_LIGHT: {
+ // mGoingIdleWakeLock is held at this point
EventLogTags.writeDeviceIdleOnStart();
final boolean deepChanged;
final boolean lightChanged;
@@ -1044,8 +1049,10 @@
getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
}
EventLogTags.writeDeviceIdleOnComplete();
+ mGoingIdleWakeLock.release();
} break;
case MSG_REPORT_IDLE_OFF: {
+ // mActiveIdleWakeLock is held at this point
EventLogTags.writeDeviceIdleOffStart("unknown");
final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
@@ -1071,6 +1078,7 @@
EventLogTags.writeDeviceIdleOffComplete();
} break;
case MSG_REPORT_ACTIVE: {
+ // The device is awake at this point, so no wakelock necessary.
String activeReason = (String)msg.obj;
int activeUid = msg.arg1;
EventLogTags.writeDeviceIdleOffStart(
@@ -1092,10 +1100,12 @@
EventLogTags.writeDeviceIdleOffComplete();
} break;
case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
+ // TODO: What is keeping the device awake at this point? Does it need to be?
int uid = msg.arg1;
checkTempAppWhitelistTimeout(uid);
} break;
case MSG_REPORT_MAINTENANCE_ACTIVITY: {
+ // TODO: What is keeping the device awake at this point? Does it need to be?
boolean active = (msg.arg1 == 1);
final int size = mMaintenanceActivityListeners.beginBroadcast();
try {
@@ -1111,6 +1121,7 @@
}
} break;
case MSG_FINISH_IDLE_OP: {
+ // mActiveIdleWakeLock is held at this point
decActiveIdleOps();
} break;
}
@@ -1356,6 +1367,9 @@
mActiveIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"deviceidle_maint");
mActiveIdleWakeLock.setReferenceCounted(false);
+ mGoingIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ "deviceidle_going_idle");
+ mGoingIdleWakeLock.setReferenceCounted(true);
mConnectivityService = (ConnectivityService)ServiceManager.getService(
Context.CONNECTIVITY_SERVICE);
mLocalAlarmManager = getLocalService(AlarmManagerService.LocalService.class);
@@ -1898,6 +1912,7 @@
mLightState = LIGHT_STATE_IDLE;
EventLogTags.writeDeviceIdleLight(mLightState, reason);
addEvent(EVENT_LIGHT_IDLE);
+ mGoingIdleWakeLock.acquire();
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
break;
case LIGHT_STATE_IDLE:
@@ -2023,6 +2038,7 @@
}
EventLogTags.writeDeviceIdle(mState, reason);
addEvent(EVENT_DEEP_IDLE);
+ mGoingIdleWakeLock.acquire();
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
break;
case STATE_IDLE:
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 3dfbdc3..372e9a6 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1105,7 +1105,6 @@
mWindowManagerInternal.setOnHardKeyboardStatusChangeListener(
mHardKeyboardListener);
}
- buildInputMethodListLocked(!mImeSelectedOnBoot /* resetDefaultEnabledIme */);
if (!mImeSelectedOnBoot) {
Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here.");
resetStateIfCurrentLocaleChangedLocked();
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index 83d374c..14abb53 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -350,8 +350,8 @@
return Collections.unmodifiableSet(mFilters);
}
- public List<R> queryIntentFromList(Intent intent, String resolvedType,
- boolean defaultOnly, ArrayList<F[]> listCut, int userId) {
+ public List<R> queryIntentFromList(Intent intent, String resolvedType, boolean defaultOnly,
+ boolean visibleToEphemeral, boolean isEphemeral, ArrayList<F[]> listCut, int userId) {
ArrayList<R> resultList = new ArrayList<R>();
final boolean debug = localLOGV ||
@@ -361,8 +361,8 @@
final String scheme = intent.getScheme();
int N = listCut.size();
for (int i = 0; i < N; ++i) {
- buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, listCut.get(i), resultList, userId);
+ buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
+ isEphemeral, resolvedType, scheme, listCut.get(i), resultList, userId);
}
filterResults(resultList);
sortResults(resultList);
@@ -370,7 +370,7 @@
}
public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
- int userId) {
+ boolean visibleToEphemeral, boolean isEphemeral, int userId) {
String scheme = intent.getScheme();
ArrayList<R> finalList = new ArrayList<R>();
@@ -443,20 +443,20 @@
FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
if (firstTypeCut != null) {
- buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, firstTypeCut, finalList, userId);
+ buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
+ isEphemeral, resolvedType, scheme, firstTypeCut, finalList, userId);
}
if (secondTypeCut != null) {
- buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, secondTypeCut, finalList, userId);
+ buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
+ isEphemeral, resolvedType, scheme, secondTypeCut, finalList, userId);
}
if (thirdTypeCut != null) {
- buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, thirdTypeCut, finalList, userId);
+ buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
+ isEphemeral, resolvedType, scheme, thirdTypeCut, finalList, userId);
}
if (schemeCut != null) {
- buildResolveList(intent, categories, debug, defaultOnly,
- resolvedType, scheme, schemeCut, finalList, userId);
+ buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
+ isEphemeral, resolvedType, scheme, schemeCut, finalList, userId);
}
filterResults(finalList);
sortResults(finalList);
@@ -694,7 +694,7 @@
}
private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
- boolean debug, boolean defaultOnly,
+ boolean debug, boolean defaultOnly, boolean visibleToEphemeral, boolean isEphemeral,
String resolvedType, String scheme, F[] src, List<R> dest, int userId) {
final String action = intent.getAction();
final Uri data = intent.getData();
@@ -735,6 +735,15 @@
continue;
}
+ // throw out filters that aren't visible to ephemeral apps
+ if (visibleToEphemeral && !filter.isVisibleToEphemeral()) {
+ continue;
+ }
+ // throw out ephemeral filters if we're not explicitly requesting them
+ if (!isEphemeral && filter.isEphemeral()) {
+ continue;
+ }
+
// Are we verified ?
if (filter.getAutoVerify()) {
if (localVerificationLOGV || debug) {
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 72fa1e3..a1c3564 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -27,16 +27,22 @@
import android.content.pm.PackageManager;
import android.net.INetworkScoreCache;
import android.net.INetworkScoreService;
+import android.net.NetworkKey;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppManager;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
+import android.net.RecommendationRequest;
+import android.net.RecommendationResult;
import android.net.ScoredNetwork;
+import android.net.wifi.WifiConfiguration;
import android.os.Binder;
import android.os.IBinder;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import com.android.internal.R;
@@ -49,11 +55,11 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Set;
+import java.util.function.Consumer;
/**
* Backing service for {@link android.net.NetworkScoreManager}.
@@ -65,7 +71,8 @@
private final Context mContext;
private final NetworkScorerAppManager mNetworkScorerAppManager;
- private final Map<Integer, INetworkScoreCache> mScoreCaches;
+ @GuardedBy("mScoreCaches")
+ private final Map<Integer, RemoteCallbackList<INetworkScoreCache>> mScoreCaches;
/** Lock used to update mPackageMonitor when scorer package changes occur. */
private final Object mPackageMonitorLock = new Object[0];
@@ -163,7 +170,7 @@
NetworkScoreService(Context context, NetworkScorerAppManager networkScoreAppManager) {
mContext = context;
mNetworkScorerAppManager = networkScoreAppManager;
- mScoreCaches = new HashMap<>();
+ mScoreCaches = new ArrayMap<>();
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
// TODO: Need to update when we support per-user scorers. http://b/23422763
mContext.registerReceiverAsUser(
@@ -273,7 +280,7 @@
}
// Separate networks by type.
- Map<Integer, List<ScoredNetwork>> networksByType = new HashMap<>();
+ Map<Integer, List<ScoredNetwork>> networksByType = new ArrayMap<>();
for (ScoredNetwork network : networks) {
List<ScoredNetwork> networkList = networksByType.get(network.networkKey.type);
if (networkList == null) {
@@ -284,19 +291,32 @@
}
// Pass the scores of each type down to the appropriate network scorer.
- for (Map.Entry<Integer, List<ScoredNetwork>> entry : networksByType.entrySet()) {
- INetworkScoreCache scoreCache = mScoreCaches.get(entry.getKey());
- if (scoreCache != null) {
- try {
- scoreCache.updateScores(entry.getValue());
- } catch (RemoteException e) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Unable to update scores of type " + entry.getKey(), e);
+ for (final Map.Entry<Integer, List<ScoredNetwork>> entry : networksByType.entrySet()) {
+ final RemoteCallbackList<INetworkScoreCache> callbackList;
+ final boolean isEmpty;
+ synchronized (mScoreCaches) {
+ callbackList = mScoreCaches.get(entry.getKey());
+ isEmpty = callbackList == null || callbackList.getRegisteredCallbackCount() == 0;
+ }
+ if (isEmpty) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "No scorer registered for type " + entry.getKey() + ", discarding");
+ }
+ continue;
+ }
+
+ sendCallback(new Consumer<INetworkScoreCache>() {
+ @Override
+ public void accept(INetworkScoreCache networkScoreCache) {
+ try {
+ networkScoreCache.updateScores(entry.getValue());
+ } catch (RemoteException e) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Unable to update scores of type " + entry.getKey(), e);
+ }
}
}
- } else if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "No scorer registered for type " + entry.getKey() + ", discarding");
- }
+ }, Collections.singleton(callbackList));
}
return true;
@@ -391,33 +411,75 @@
/** Clear scores. Callers are responsible for checking permissions as appropriate. */
private void clearInternal() {
- Set<INetworkScoreCache> cachesToClear = getScoreCaches();
+ sendCallback(new Consumer<INetworkScoreCache>() {
+ @Override
+ public void accept(INetworkScoreCache networkScoreCache) {
+ try {
+ networkScoreCache.clearScores();
+ } catch (RemoteException e) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Unable to clear scores", e);
+ }
+ }
+ }
+ }, getScoreCacheLists());
+ }
- for (INetworkScoreCache scoreCache : cachesToClear) {
- try {
- scoreCache.clearScores();
- } catch (RemoteException e) {
+ @Override
+ public void registerNetworkScoreCache(int networkType,
+ INetworkScoreCache scoreCache,
+ int filterType) {
+ mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
+ synchronized (mScoreCaches) {
+ RemoteCallbackList<INetworkScoreCache> callbackList = mScoreCaches.get(networkType);
+ if (callbackList == null) {
+ callbackList = new RemoteCallbackList<>();
+ mScoreCaches.put(networkType, callbackList);
+ }
+ if (!callbackList.register(scoreCache, filterType)) {
+ if (callbackList.getRegisteredCallbackCount() == 0) {
+ mScoreCaches.remove(networkType);
+ }
if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Unable to clear scores", e);
+ Log.v(TAG, "Unable to register NetworkScoreCache for type " + networkType);
}
}
}
}
@Override
- public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
+ public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
synchronized (mScoreCaches) {
- if (mScoreCaches.containsKey(networkType)) {
- throw new IllegalArgumentException(
- "Score cache already registered for type " + networkType);
+ RemoteCallbackList<INetworkScoreCache> callbackList = mScoreCaches.get(networkType);
+ if (callbackList == null || !callbackList.unregister(scoreCache)) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Unable to unregister NetworkScoreCache for type " + networkType);
+ }
+ } else if (callbackList.getRegisteredCallbackCount() == 0) {
+ mScoreCaches.remove(networkType);
}
- mScoreCaches.put(networkType, scoreCache);
}
}
@Override
- protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ public RecommendationResult requestRecommendation(RecommendationRequest request) {
+ // TODO(jjoslin): 11/25/16 - Update with real impl.
+ WifiConfiguration selectedConfig = null;
+ if (request != null) {
+ selectedConfig = request.getCurrentSelectedConfig();
+ }
+ return new RecommendationResult(selectedConfig);
+ }
+
+ @Override
+ public boolean requestScores(NetworkKey[] networks) {
+ // TODO(jjoslin): 12/13/16 - Implement
+ return false;
+ }
+
+ @Override
+ protected void dump(final FileDescriptor fd, final PrintWriter writer, final String[] args) {
mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
NetworkScorerAppData currentScorer = mNetworkScorerAppManager.getActiveScorer();
if (currentScorer == null) {
@@ -426,13 +488,17 @@
}
writer.println("Current scorer: " + currentScorer.mPackageName);
- for (INetworkScoreCache scoreCache : getScoreCaches()) {
- try {
- TransferPipe.dumpAsync(scoreCache.asBinder(), fd, args);
- } catch (IOException | RemoteException e) {
- writer.println("Failed to dump score cache: " + e);
+ sendCallback(new Consumer<INetworkScoreCache>() {
+ @Override
+ public void accept(INetworkScoreCache networkScoreCache) {
+ try {
+ TransferPipe.dumpAsync(networkScoreCache.asBinder(), fd, args);
+ } catch (IOException | RemoteException e) {
+ writer.println("Failed to dump score cache: " + e);
+ }
}
- }
+ }, getScoreCacheLists());
+
if (mServiceConnection != null) {
mServiceConnection.dump(fd, writer, args);
} else {
@@ -442,14 +508,30 @@
}
/**
- * Returns a set of all score caches that are currently active.
+ * Returns a {@link Collection} of all {@link RemoteCallbackList}s that are currently active.
*
* <p>May be used to perform an action on all score caches without potentially strange behavior
* if a new scorer is registered during that action's execution.
*/
- private Set<INetworkScoreCache> getScoreCaches() {
+ private Collection<RemoteCallbackList<INetworkScoreCache>> getScoreCacheLists() {
synchronized (mScoreCaches) {
- return new HashSet<>(mScoreCaches.values());
+ return new ArrayList<>(mScoreCaches.values());
+ }
+ }
+
+ private void sendCallback(Consumer<INetworkScoreCache> consumer,
+ Collection<RemoteCallbackList<INetworkScoreCache>> remoteCallbackLists) {
+ for (RemoteCallbackList<INetworkScoreCache> callbackList : remoteCallbackLists) {
+ synchronized (callbackList) { // Ensure only one active broadcast per RemoteCallbackList
+ final int count = callbackList.beginBroadcast();
+ try {
+ for (int i = 0; i < count; i++) {
+ consumer.accept(callbackList.getBroadcastItem(i));
+ }
+ } finally {
+ callbackList.finishBroadcast();
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 698f1eb..8a0d4df 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -31,6 +31,7 @@
import android.util.Slog;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import libcore.io.IoUtils;
@@ -46,6 +47,8 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* Service for reading and writing blocks to a persistent partition.
@@ -79,9 +82,12 @@
private final Context mContext;
private final String mDataBlockFile;
private final Object mLock = new Object();
+ private final CountDownLatch mInitDoneSignal = new CountDownLatch(1);
private int mAllowedUid = -1;
private long mBlockDeviceSize;
+
+ @GuardedBy("mLock")
private boolean mIsWritable = true;
public PersistentDataBlockService(Context context) {
@@ -109,9 +115,29 @@
@Override
public void onStart() {
- enforceChecksumValidity();
- formatIfOemUnlockEnabled();
- publishBinderService(Context.PERSISTENT_DATA_BLOCK_SERVICE, mService);
+ // Do init on a separate thread, will join in PHASE_ACTIVITY_MANAGER_READY
+ FgThread.getHandler().post(() -> {
+ enforceChecksumValidity();
+ formatIfOemUnlockEnabled();
+ publishBinderService(Context.PERSISTENT_DATA_BLOCK_SERVICE, mService);
+ mInitDoneSignal.countDown();
+ });
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ // Wait for initialization in onStart to finish
+ if (phase == PHASE_SYSTEM_SERVICES_READY) {
+ try {
+ if (!mInitDoneSignal.await(10, TimeUnit.SECONDS)) {
+ throw new IllegalStateException("Service " + TAG + " init timeout");
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException("Service " + TAG + " init interrupted", e);
+ }
+ }
+ super.onBootPhase(phase);
}
private void formatIfOemUnlockEnabled() {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 8fd1d2f..c65aed7 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2136,14 +2136,17 @@
try {
accountId = accounts.accountsDb.findDeAccountId(account);
if (accountId >= 0) {
- accounts.accountsDb.deleteDeAccount(accountId);
- if (userUnlocked) {
- // Delete from CE table
- accounts.accountsDb.deleteCeAccount(accountId);
- }
- accounts.accountsDb.setTransactionSuccessful();
- isChanged = true;
+ isChanged = accounts.accountsDb.deleteDeAccount(accountId);
}
+ // always delete from CE table if CE storage is available
+ // DE account could be removed while CE was locked
+ if (userUnlocked) {
+ long ceAccountId = accounts.accountsDb.findCeAccountId(account);
+ if (ceAccountId >= 0) {
+ accounts.accountsDb.deleteCeAccount(ceAccountId);
+ }
+ }
+ accounts.accountsDb.setTransactionSuccessful();
} finally {
accounts.accountsDb.endTransaction();
}
diff --git a/services/core/java/com/android/server/accounts/AccountsDb.java b/services/core/java/com/android/server/accounts/AccountsDb.java
index a160b3a..5ca74711 100644
--- a/services/core/java/com/android/server/accounts/AccountsDb.java
+++ b/services/core/java/com/android/server/accounts/AccountsDb.java
@@ -1201,7 +1201,7 @@
}
boolean deleteCeAccount(long accountId) {
- SQLiteDatabase db = mDeDatabase.getReadableDatabaseUserIsUnlocked();
+ SQLiteDatabase db = mDeDatabase.getWritableDatabaseUserIsUnlocked();
return db.delete(
CE_TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null) > 0;
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 136e02c..7661127 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -75,6 +75,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
+import android.webkit.WebViewZygote;
public final class ActiveServices {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActiveServices" : TAG_AM;
@@ -1704,6 +1705,7 @@
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
+ String hostingType = "service";
ProcessRecord app;
if (!isolated) {
@@ -1732,13 +1734,17 @@
// in the service any current isolated process it is running in or
// waiting to have come up.
app = r.isolatedProc;
+ if (WebViewZygote.isMultiprocessEnabled()
+ && r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
+ hostingType = "webview_service";
+ }
}
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
- "service", r.name, false, isolated, false)) == null) {
+ hostingType, r.name, false, isolated, false)) == null) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 229a68b..4ea73e7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -43,7 +43,6 @@
import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.TransferPipe;
import com.android.internal.os.Zygote;
-import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
@@ -62,6 +61,7 @@
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.firewall.IntentFirewall;
import com.android.server.pm.Installer;
+import com.android.server.pm.Installer.InstallerException;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.vr.VrManagerInternal;
import com.android.server.wm.WindowManagerService;
@@ -202,6 +202,7 @@
import android.os.storage.StorageManager;
import android.provider.Downloads;
import android.provider.Settings;
+import android.service.autofill.AutoFillService;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.VoiceInteractionManagerInternal;
import android.service.voice.VoiceInteractionSession;
@@ -269,7 +270,6 @@
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
@@ -362,7 +362,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBLE_BEHIND;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStackSupervisor.ActivityContainer.FORCE_NEW_TASK_FLAGS;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
@@ -509,6 +508,9 @@
// on getting this result before starting to launch its UI).
static final int PENDING_ASSIST_EXTRAS_LONG_TIMEOUT = 2000;
+ // How long to wait in getAutoFillAssistStructure() for the activity to respond with the result.
+ static final int PENDING_AUTO_FILL_ASSIST_STRUCTURE_TIMEOUT = 2000;
+
// Maximum number of persisted Uri grants a package is allowed
static final int MAX_PERSISTED_URI_GRANTS = 128;
@@ -685,15 +687,18 @@
public AssistStructure structure = null;
public AssistContent content = null;
public Bundle receiverExtras;
+ public int flags;
public PendingAssistExtras(ActivityRecord _activity, Bundle _extras, Intent _intent,
- String _hint, IResultReceiver _receiver, Bundle _receiverExtras, int _userHandle) {
+ String _hint, IResultReceiver _receiver, Bundle _receiverExtras, int _flags,
+ int _userHandle) {
activity = _activity;
extras = _extras;
intent = _intent;
hint = _hint;
receiver = _receiver;
receiverExtras = _receiverExtras;
+ flags = _flags;
userHandle = _userHandle;
}
@Override
@@ -1215,6 +1220,15 @@
/**
* Set while we are wanting to sleep, to prevent any
* activities from being started/resumed.
+ *
+ * TODO(b/33594039): Clarify the actual state transitions represented by mSleeping.
+ *
+ * Currently mSleeping is set to true when transitioning into the sleep state, and remains true
+ * while in the sleep state until there is a pending transition out of sleep, in which case
+ * mSleeping is set to false, and remains false while awake.
+ *
+ * Whether mSleeping can quickly toggled between true/false without the device actually
+ * display changing states is undefined.
*/
private boolean mSleeping = false;
@@ -1364,6 +1378,7 @@
boolean mAlwaysFinishActivities = false;
boolean mForceResizableActivities;
boolean mSupportsMultiWindow;
+ boolean mSupportsSplitScreenMultiWindow;
boolean mSupportsFreeformWindowManagement;
boolean mSupportsPictureInPicture;
boolean mSupportsLeanbackOnly;
@@ -1386,6 +1401,8 @@
final long[] mTmpLong = new long[2];
+ private final ArraySet<BroadcastQueue> mTmpBroadcastQueue = new ArraySet();
+
static final class ProcessChangeItem {
static final int CHANGE_ACTIVITIES = 1<<0;
static final int CHANGE_PROCESS_STATE = 1<<1;
@@ -1544,10 +1561,9 @@
static final int SYSTEM_USER_UNLOCK_MSG = 59;
static final int LOG_STACK_STATE = 60;
static final int VR_MODE_CHANGE_MSG = 61;
- static final int VR_MODE_APPLY_IF_NEEDED_MSG = 62;
- static final int SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG = 63;
- static final int HANDLE_TRUST_STORAGE_UPDATE_MSG = 64;
- static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 65;
+ static final int SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG = 62;
+ static final int HANDLE_TRUST_STORAGE_UPDATE_MSG = 63;
+ static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 64;
static final int START_USER_SWITCH_FG_MSG = 712;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
@@ -2283,14 +2299,6 @@
}
vrService.setVrMode(vrMode, requestedPackage, userId, callingPackage);
} break;
- case VR_MODE_APPLY_IF_NEEDED_MSG: {
- final ActivityRecord r = (ActivityRecord) msg.obj;
- final boolean needsVrMode = r != null && r.requestedVrComponent != null;
- if (needsVrMode) {
- applyVrMode(msg.arg1 == 1, r.requestedVrComponent, r.userId,
- r.info.getComponentName(), false);
- }
- } break;
case HANDLE_TRUST_STORAGE_UPDATE_MSG: {
synchronized (ActivityManagerService.this) {
for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
@@ -3063,20 +3071,12 @@
mHandler.obtainMessage(VR_MODE_CHANGE_MSG, 0, 0, r));
}
- void applyVrModeIfNeededLocked(ActivityRecord r, boolean enable) {
- mHandler.sendMessage(
- mHandler.obtainMessage(VR_MODE_APPLY_IF_NEEDED_MSG, enable ? 1 : 0, 0, r));
- }
-
- private void applyVrMode(boolean enabled, ComponentName packageName, int userId,
- ComponentName callingPackage, boolean immediate) {
- VrManagerInternal vrService =
- LocalServices.getService(VrManagerInternal.class);
- if (immediate) {
- vrService.setVrModeImmediate(enabled, packageName, userId, callingPackage);
- } else {
- vrService.setVrMode(enabled, packageName, userId, callingPackage);
+ private void notifyVrManagerOfSleepState(boolean isSleeping) {
+ final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
+ if (vrService == null) {
+ return;
}
+ vrService.onSleepStateChanged(isSleeping);
}
final void showAskCompatModeDialogLocked(ActivityRecord r) {
@@ -3695,10 +3695,18 @@
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
- Process.ProcessStartResult startResult = Process.start(entryPoint,
- app.processName, uid, uid, gids, debugFlags, mountExternal,
- app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
- app.info.dataDir, entryPointArgs);
+ Process.ProcessStartResult startResult;
+ if (hostingType.equals("webview_service")) {
+ startResult = Process.startWebView(entryPoint,
+ app.processName, uid, uid, gids, debugFlags, mountExternal,
+ app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
+ app.info.dataDir, entryPointArgs);
+ } else {
+ startResult = Process.start(entryPoint,
+ app.processName, uid, uid, gids, debugFlags, mountExternal,
+ app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
+ app.info.dataDir, entryPointArgs);
+ }
checkTime(startTime, "startProcess: returned from zygote!");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
@@ -6195,8 +6203,19 @@
}
private final ProcessRecord removeProcessNameLocked(final String name, final int uid) {
- ProcessRecord old = mProcessNames.remove(name, uid);
- if (old != null) {
+ return removeProcessNameLocked(name, uid, null);
+ }
+
+ private final ProcessRecord removeProcessNameLocked(final String name, final int uid,
+ final ProcessRecord expecting) {
+ ProcessRecord old = mProcessNames.get(name, uid);
+ // Only actually remove when the currently recorded value matches the
+ // record that we expected; if it doesn't match then we raced with a
+ // newly created process and we don't want to destroy the new one.
+ if ((expecting == null) || (old == expecting)) {
+ mProcessNames.remove(name, uid);
+ }
+ if (old != null && old.uidRecord != null) {
old.uidRecord.numProcs--;
if (old.uidRecord.numProcs == 0) {
// No more processes using this uid, tell clients it is gone.
@@ -7486,45 +7505,51 @@
@Override
public void enterPictureInPictureMode(IBinder token) {
- enterPictureInPictureMode(token, DEFAULT_DISPLAY, null /* aspectRatio */);
+ enterPictureInPictureMode(token, DEFAULT_DISPLAY, -1f /* aspectRatio */,
+ false /* checkAspectRatio */);
}
@Override
public void enterPictureInPictureModeWithAspectRatio(IBinder token, float aspectRatio) {
- enterPictureInPictureMode(token, DEFAULT_DISPLAY, aspectRatio);
+ enterPictureInPictureMode(token, DEFAULT_DISPLAY, aspectRatio, true /* checkAspectRatio */);
}
- public void enterPictureInPictureMode(IBinder token, int displayId, Float aspectRatio) {
+ private void enterPictureInPictureMode(IBinder token, int displayId, float aspectRatio,
+ boolean checkAspectRatio) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized(this) {
- if (!mSupportsPictureInPicture) {
- throw new IllegalStateException("enterPictureInPictureMode: "
- + "Device doesn't support picture-in-picture mode.");
- }
+ final ActivityRecord r = ensureValidPictureInPictureActivityLocked(
+ "enterPictureInPictureMode", token, aspectRatio, checkAspectRatio,
+ true /* checkActivityVisibility */);
- final ActivityRecord r = ActivityRecord.forTokenLocked(token);
- if (r == null) {
- throw new IllegalStateException("enterPictureInPictureMode: "
- + "Can't find activity for token=" + token);
- }
+ enterPictureInPictureModeLocked(r, displayId, aspectRatio,
+ true /* moveHomeStackToFront */, "enterPictureInPictureMode");
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
- if (!r.supportsPictureInPicture()) {
- throw new IllegalArgumentException("enterPictureInPictureMode: "
- + "Picture-In-Picture not supported for r=" + r);
- }
+ void enterPictureInPictureModeLocked(ActivityRecord r, int displayId, float aspectRatio,
+ boolean moveHomeStackToFront, String reason) {
+ final Rect bounds = isValidPictureInPictureAspectRatio(aspectRatio)
+ ? mWindowManager.getPictureInPictureBounds(displayId, aspectRatio)
+ : mWindowManager.getPictureInPictureDefaultBounds(displayId);
+ mStackSupervisor.moveActivityToPinnedStackLocked(r, reason, bounds, moveHomeStackToFront);
+ }
- if (aspectRatio != null && !isValidPictureInPictureAspectRatio(aspectRatio)) {
- throw new IllegalArgumentException(String.format("enterPictureInPictureMode: "
- + "Aspect ratio is too extreme (must be between %f and %f).",
- mMinPipAspectRatio, mMaxPipAspectRatio));
- }
+ @Override
+ public void enterPictureInPictureModeOnMoveToBackground(IBinder token,
+ boolean enterPictureInPictureOnMoveToBg) {
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized(this) {
+ final ActivityRecord r = ensureValidPictureInPictureActivityLocked(
+ "requestAutoEnterPictureInPicture", token, -1f /* aspectRatio */,
+ false /* checkAspectRatio */, false /* checkActivityVisibility */);
- final Rect bounds = isValidPictureInPictureAspectRatio(aspectRatio)
- ? mWindowManager.getPictureInPictureBounds(displayId, aspectRatio)
- : mWindowManager.getPictureInPictureDefaultBounds(displayId);
- mStackSupervisor.moveActivityToPinnedStackLocked(r, "enterPictureInPictureMode",
- bounds);
+ r.supportsPipOnMoveToBackground = enterPictureInPictureOnMoveToBg;
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -7536,33 +7561,68 @@
final long origId = Binder.clearCallingIdentity();
try {
synchronized(this) {
- final ActivityRecord r = ActivityRecord.forTokenLocked(token);
- if (r == null || r.getStack().mStackId != PINNED_STACK_ID) {
- throw new IllegalStateException("setPictureInPictureAspectRatio: "
- + "Requesting activity must be in picture-in-picture mode.");
- }
+ final ActivityRecord r = ensureValidPictureInPictureActivityLocked(
+ "setPictureInPictureAspectRatio", token, aspectRatio,
+ true /* checkAspectRatio */, false /* checkActivityVisibility */);
- if (!isValidPictureInPictureAspectRatio(aspectRatio)) {
- throw new IllegalArgumentException(String.format(
- "setPictureInPictureAspectRatio: Aspect ratio is too extreme (must be "
- + "between %f and %f).", mMinPipAspectRatio,
- mMaxPipAspectRatio));
+ if (r.getStack().getStackId() == PINNED_STACK_ID) {
+ // If the activity is already in picture-in-picture, update the pinned stack now
+ mWindowManager.setPictureInPictureAspectRatio(aspectRatio);
}
-
- mWindowManager.setPictureInPictureAspectRatio(aspectRatio);
+ r.pictureInPictureAspectRatio = aspectRatio;
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
- private boolean isValidPictureInPictureAspectRatio(Float aspectRatio) {
- if (aspectRatio == null) {
- return false;
- }
+ private boolean isValidPictureInPictureAspectRatio(float aspectRatio) {
return mMinPipAspectRatio <= aspectRatio && aspectRatio <= mMaxPipAspectRatio;
}
+ /**
+ * Checks the state of the system and the activity associated with the given {@param token} to
+ * verify that picture-in-picture is supported for that activity.
+ *
+ * @param checkAspectRatio whether or not to check {@param aspectRatio} is within a valid range
+ * @param checkActivityVisibility whether or not to enforce that the activity is currently
+ * visible
+ *
+ * @return the activity record for the given {@param token} if all the checks pass.
+ */
+ private ActivityRecord ensureValidPictureInPictureActivityLocked(String caller, IBinder token,
+ float aspectRatio, boolean checkAspectRatio, boolean checkActivityVisibility) {
+ if (!mSupportsPictureInPicture) {
+ throw new IllegalStateException(caller
+ + ": Device doesn't support picture-in-picture mode.");
+ }
+
+ final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+ if (r == null) {
+ throw new IllegalStateException(caller
+ + ": Can't find activity for token=" + token);
+ }
+
+ if (!r.canEnterPictureInPicture(checkActivityVisibility)) {
+ throw new IllegalArgumentException(caller
+ + "Current activity does not support picture-in-picture or is not "
+ + "visible r=" + r);
+ }
+
+ if (r.getStack().isHomeStack()) {
+ throw new IllegalStateException(caller
+ + ": Activities on the home stack not supported");
+ }
+
+ if (checkAspectRatio && !isValidPictureInPictureAspectRatio(aspectRatio)) {
+ throw new IllegalArgumentException(String.format(caller
+ + ": Aspect ratio is too extreme (must be between %f and %f).",
+ mMinPipAspectRatio, mMaxPipAspectRatio));
+ }
+
+ return r;
+ }
+
// =========================================================
// PROCESS INFO
// =========================================================
@@ -9183,10 +9243,10 @@
}
}
final ActivityStack stack = tr.getStack();
- if ((flags & ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS) != 0) {
- if (stack != null && stack.isHomeStack()) {
+ if ((flags & ActivityManager.RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS) != 0) {
+ if (stack != null && stack.isHomeOrRecentsStack()) {
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, home stack task: " + tr);
+ "Skipping, home or recents stack task: " + tr);
continue;
}
}
@@ -9608,8 +9668,8 @@
@Override
public void removeStack(int stackId) {
enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS, "removeStack()");
- if (stackId == HOME_STACK_ID) {
- throw new IllegalArgumentException("Removing home stack is not allowed.");
+ if (StackId.isHomeOrRecentsStack(stackId)) {
+ throw new IllegalArgumentException("Removing home or recents stack is not allowed.");
}
synchronized (this) {
@@ -9837,9 +9897,9 @@
@Override
public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToStack()");
- if (stackId == HOME_STACK_ID) {
+ if (StackId.isHomeOrRecentsStack(stackId)) {
throw new IllegalArgumentException(
- "moveTaskToStack: Attempt to move task " + taskId + " to home stack");
+ "moveTaskToStack: Attempt to move task " + taskId + " to stack " + stackId);
}
synchronized (this) {
long ident = Binder.clearCallingIdentity();
@@ -9854,8 +9914,7 @@
!FORCE_FOCUS, "moveTaskToStack", ANIMATE);
if (result && stackId == DOCKED_STACK_ID) {
// If task moved to docked stack - show recents if needed.
- mStackSupervisor.moveHomeStackTaskToTop(RECENTS_ACTIVITY_TYPE,
- "moveTaskToDockedStack");
+ mWindowManager.showRecentApps(false /* fromHome */);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -10039,10 +10098,10 @@
@Override
public void positionTaskInStack(int taskId, int stackId, int position) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "positionTaskInStack()");
- if (stackId == HOME_STACK_ID) {
+ if (StackId.isHomeOrRecentsStack(stackId)) {
throw new IllegalArgumentException(
"positionTaskInStack: Attempt to change the position of task "
- + taskId + " in/to home stack");
+ + taskId + " in/to home/recents stack");
}
synchronized (this) {
long ident = Binder.clearCallingIdentity();
@@ -10084,22 +10143,6 @@
}
@Override
- public boolean isInHomeStack(int taskId) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
- long ident = Binder.clearCallingIdentity();
- try {
- synchronized (this) {
- final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(
- taskId, !RESTORE_FROM_RECENTS, INVALID_STACK_ID);
- final ActivityStack stack = tr != null ? tr.getStack() : null;
- return stack != null && stack.isHomeStack();
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- @Override
public int getTaskForActivity(IBinder token, boolean onlyRoot) {
synchronized(this) {
return ActivityRecord.getTaskForActivityLocked(token, onlyRoot);
@@ -11642,6 +11685,7 @@
startTimeTrackingFocusedActivityLocked();
mTopProcessState = ActivityManager.PROCESS_STATE_TOP;
mStackSupervisor.comeOutOfSleepIfNeededLocked();
+ notifyVrManagerOfSleepState(false);
updateOomAdjLocked();
} else if (!mSleeping && shouldSleepLocked()) {
mSleeping = true;
@@ -11650,6 +11694,7 @@
}
mTopProcessState = ActivityManager.PROCESS_STATE_TOP_SLEEPING;
mStackSupervisor.goingToSleepLocked();
+ notifyVrManagerOfSleepState(true);
updateOomAdjLocked();
// Initialize the wake times of all processes.
@@ -12135,7 +12180,7 @@
public Bundle getAssistContextExtras(int requestType) {
PendingAssistExtras pae = enqueueAssistContext(requestType, null, null, null,
null, null, true /* focused */, true /* newSessionId */,
- UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT);
+ UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT, 0);
if (pae == null) {
return null;
}
@@ -12203,22 +12248,23 @@
IBinder activityToken, boolean focused, boolean newSessionId) {
return enqueueAssistContext(requestType, null, null, receiver, receiverExtras,
activityToken, focused, newSessionId,
- UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_LONG_TIMEOUT)
+ UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_LONG_TIMEOUT, 0)
!= null;
}
@Override
public boolean requestAutoFillData(IResultReceiver receiver, Bundle receiverExtras,
- IBinder activityToken) {
- return enqueueAssistContext(ActivityManager.ASSIST_CONTEXT_AUTOFILL, null, null, receiver,
+ IBinder activityToken, int flags) {
+ return enqueueAssistContext(ActivityManager.ASSIST_CONTEXT_FULL, null, null, receiver,
receiverExtras, activityToken, true, true,
- UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_LONG_TIMEOUT)
- != null;
+ UserHandle.getCallingUserId(), null, PENDING_AUTO_FILL_ASSIST_STRUCTURE_TIMEOUT,
+ flags) != null;
}
private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint,
IResultReceiver receiver, Bundle receiverExtras, IBinder activityToken,
- boolean focused, boolean newSessionId, int userHandle, Bundle args, long timeout) {
+ boolean focused, boolean newSessionId, int userHandle, Bundle args, long timeout,
+ int flags) {
enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
"enqueueAssistContext()");
synchronized (this) {
@@ -12257,14 +12303,14 @@
extras.putString(Intent.EXTRA_ASSIST_PACKAGE, activity.packageName);
extras.putInt(Intent.EXTRA_ASSIST_UID, activity.app.uid);
pae = new PendingAssistExtras(activity, extras, intent, hint, receiver, receiverExtras,
- userHandle);
+ flags, userHandle);
// Increment the sessionId if necessary
if (newSessionId) {
mViSessionId++;
}
try {
activity.app.thread.requestAssistContextExtras(activity.appToken, pae,
- requestType, mViSessionId);
+ requestType, mViSessionId, flags);
mPendingAssistExtras.add(pae);
mUiHandler.postDelayed(pae, timeout);
} catch (RemoteException e) {
@@ -12340,10 +12386,13 @@
sendBundle.putParcelable(VoiceInteractionSession.KEY_CONTENT, pae.content);
sendBundle.putBundle(VoiceInteractionSession.KEY_RECEIVER_EXTRAS,
pae.receiverExtras);
+ if (pae.flags > 0) {
+ sendBundle.putInt(VoiceInteractionSession.KEY_FLAGS, pae.flags);
+ }
IBinder autoFillCallback =
- extras.getBinder(VoiceInteractionSession.KEY_AUTO_FILL_CALLBACK);
+ extras.getBinder(AutoFillService.KEY_CALLBACK);
if (autoFillCallback != null) {
- sendBundle.putBinder(VoiceInteractionSession.KEY_AUTO_FILL_CALLBACK,
+ sendBundle.putBinder(AutoFillService.KEY_CALLBACK,
autoFillCallback);
}
}
@@ -12377,7 +12426,7 @@
Bundle args) {
return enqueueAssistContext(requestType, intent, hint, null, null, null,
true /* focused */, true /* newSessionId */,
- userHandle, args, PENDING_ASSIST_EXTRAS_TIMEOUT) != null;
+ userHandle, args, PENDING_ASSIST_EXTRAS_TIMEOUT, 0) != null;
}
public void registerProcessObserver(IProcessObserver observer) {
@@ -13093,6 +13142,8 @@
mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
final boolean supportsMultiWindow = ActivityManager.supportsMultiWindow();
+ final boolean supportsSplitScreenMultiWindow =
+ ActivityManager.supportsSplitScreenMultiWindow();
final String debugApp = Settings.Global.getString(resolver, DEBUG_APP);
final boolean waitForDebugger = Settings.Global.getInt(resolver, WAIT_FOR_DEBUGGER, 0) != 0;
final boolean alwaysFinishActivities =
@@ -13128,6 +13179,7 @@
mSupportsFreeformWindowManagement = false;
mSupportsPictureInPicture = false;
}
+ mSupportsSplitScreenMultiWindow = supportsSplitScreenMultiWindow;
mWindowManager.setForceResizableTasks(mForceResizableActivities);
mWindowManager.setSupportsPictureInPicture(mSupportsPictureInPicture);
// This happens before any activities are started, so we can change global configuration
@@ -17009,7 +17061,7 @@
if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
"Removing non-persistent process during cleanup: " + app);
if (!replacingPid) {
- removeProcessNameLocked(app.processName, app.uid);
+ removeProcessNameLocked(app.processName, app.uid, app);
}
if (mHeavyWeightProcess == app) {
mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
@@ -18331,7 +18383,8 @@
}
List<BroadcastFilter> registeredReceiversForUser =
mReceiverResolver.queryIntent(intent,
- resolvedType, false, users[i]);
+ resolvedType, false, false /*visibleToEphemeral*/,
+ false /*isEphemeral*/, users[i]);
if (registeredReceivers == null) {
registeredReceivers = registeredReceiversForUser;
} else if (registeredReceiversForUser != null) {
@@ -18340,7 +18393,8 @@
}
} else {
registeredReceivers = mReceiverResolver.queryIntent(intent,
- resolvedType, false, userId);
+ resolvedType, false, false /*visibleToEphemeral*/,
+ false /*isEphemeral*/, userId);
}
}
@@ -18845,8 +18899,8 @@
@Override
public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTasksToFullscreenStack()");
- if (fromStackId == HOME_STACK_ID) {
- throw new IllegalArgumentException("You can't move tasks from the home stack.");
+ if (StackId.isHomeOrRecentsStack(fromStackId)) {
+ throw new IllegalArgumentException("You can't move tasks from the home/recents stack.");
}
synchronized (this) {
final long origId = Binder.clearCallingIdentity();
@@ -19530,7 +19584,7 @@
int schedGroup;
int procState;
boolean foregroundActivities = false;
- final ArraySet<BroadcastQueue> queues = new ArraySet<BroadcastQueue>();
+ mTmpBroadcastQueue.clear();
if (app == TOP_APP) {
// The last app on the list is the foreground app.
adj = ProcessList.FOREGROUND_APP_ADJ;
@@ -19544,13 +19598,13 @@
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.adjType = "instrumentation";
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
- } else if (isReceivingBroadcastLocked(app, queues)) {
+ } else if (isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) {
// An app that is currently receiving a broadcast also
// counts as being in the foreground for OOM killer purposes.
// It's placed in a sched group based on the nature of the
// broadcast as reflected by which queue it's active in.
adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = (queues.contains(mFgBroadcastQueue))
+ schedGroup = (mTmpBroadcastQueue.contains(mFgBroadcastQueue))
? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
app.adjType = "broadcast";
procState = ActivityManager.PROCESS_STATE_RECEIVER;
@@ -22177,22 +22231,6 @@
public SleepToken acquireSleepToken(String tag) {
Preconditions.checkNotNull(tag);
- ComponentName requestedVrService = null;
- ComponentName callingVrActivity = null;
- int userId = -1;
- synchronized (ActivityManagerService.this) {
- final ActivityRecord resumedActivity = mStackSupervisor.getResumedActivityLocked();
- if (resumedActivity != null) {
- requestedVrService = resumedActivity.requestedVrComponent;
- callingVrActivity = resumedActivity.info.getComponentName();
- userId = resumedActivity.userId;
- }
- }
-
- if (requestedVrService != null) {
- applyVrMode(false, requestedVrService, userId, callingVrActivity, true);
- }
-
synchronized (ActivityManagerService.this) {
SleepTokenImpl token = new SleepTokenImpl(tag);
mSleepTokens.add(token);
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 14b843a..814b05a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -233,6 +233,8 @@
return runAttachAgent(pw);
case "supports-multiwindow":
return runSupportsMultiwindow(pw);
+ case "supports-split-screen-multi-window":
+ return runSupportsSplitScreenMultiwindow(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -2300,20 +2302,36 @@
}
int runSupportsMultiwindow(PrintWriter pw) throws RemoteException {
+ final Resources res = getResources(pw);
+ if (res == null) {
+ return -1;
+ }
+ pw.println(res.getBoolean(com.android.internal.R.bool.config_supportsMultiWindow));
+ return 0;
+ }
+
+ int runSupportsSplitScreenMultiwindow(PrintWriter pw) throws RemoteException {
+ final Resources res = getResources(pw);
+ if (res == null) {
+ return -1;
+ }
+ pw.println(
+ res.getBoolean(com.android.internal.R.bool.config_supportsSplitScreenMultiWindow));
+ return 0;
+ }
+
+ private Resources getResources(PrintWriter pw) throws RemoteException {
// system resources does not contain all the device configuration, construct it manually.
Configuration config = mInterface.getConfiguration();
if (config == null) {
pw.println("Error: Activity manager has no configuration");
- return -1;
+ return null;
}
final DisplayMetrics metrics = new DisplayMetrics();
metrics.setToDefaults();
- Resources res = new Resources(AssetManager.getSystem(), metrics, config);
-
- pw.println(res.getBoolean(com.android.internal.R.bool.config_supportsMultiWindow));
- return 0;
+ return new Resources(AssetManager.getSystem(), metrics, config);
}
@Override
@@ -2495,6 +2513,8 @@
pw.println(" Rtrieve the configuration and any recent configurations of the device.");
pw.println(" supports-multiwindow");
pw.println(" Returns true if the device supports multiwindow.");
+ pw.println(" supports-split-screen-multi-window");
+ pw.println(" Returns true if the device supports split screen multiwindow.");
pw.println(" suppress-resize-config-changes <true|false>");
pw.println(" Suppresses configuration changes due to user resizing an activity/task.");
pw.println(" set-inactive [--user <USER_ID>] <PACKAGE> true|false");
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index facfeb6..32dec96 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -5,6 +5,8 @@
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
+
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
@@ -78,7 +80,7 @@
if (stack.mStackId == PINNED_STACK_ID) {
stack = mSupervisor.findStackBehind(stack);
}
- if (stack.mStackId == HOME_STACK_ID
+ if (StackId.isHomeOrRecentsStack(stack.mStackId)
|| stack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
mWindowState = WINDOW_STATE_STANDARD;
} else if (stack.mStackId == DOCKED_STACK_ID) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 214a357..7dd2e84 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -19,6 +19,7 @@
import static android.app.ActivityManager.StackId;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
@@ -82,7 +83,6 @@
import android.util.TimeUtils;
import android.view.AppTransitionAnimationSpec;
import android.view.IApplicationToken;
-import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import com.android.internal.app.ResolverActivity;
@@ -216,6 +216,14 @@
boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
boolean immersive; // immersive mode (don't interrupt if possible)
boolean forceNewConfig; // force re-create with new config next time
+ boolean supportsPipOnMoveToBackground; // Supports automatically entering picture-in-picture
+ // when this activity is hidden. This flag is requested by the activity.
+ private boolean enterPipOnMoveToBackground; // Flag to enter picture in picture when this
+ // activity is made invisible. This flag is set specifically when another task is being
+ // launched or moved to the front which may cause this activity to try and enter PiP
+ // when it is next made invisible.
+ float pictureInPictureAspectRatio; // The aspect ratio to use when auto-entering
+ // picture-in-picture
int launchCount; // count of launches since last state
long lastLaunchTime; // time of last launch of this activity
ComponentName requestedVrComponent; // the requested component for handling VR mode.
@@ -432,6 +440,11 @@
if (info != null) {
pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
}
+ if (supportsPipOnMoveToBackground) {
+ pw.println(prefix + "supportsPipOnMoveToBackground=1 "
+ + "enterPipOnMoveToBackground="
+ + (enterPipOnMoveToBackground ? 1 : 0));
+ }
}
private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
@@ -840,6 +853,23 @@
}
/**
+ * If this activity has requested that it auto-enter picture-in-picture and we can actually do
+ * this, then mark it to enter picture in picture at that point.
+ */
+ void setEnterPipOnMoveToBackground(boolean enterPipOnInvisible) {
+ if (supportsPipOnMoveToBackground) {
+ enterPipOnMoveToBackground = enterPipOnInvisible;
+ }
+ }
+
+ /**
+ * @return whether to enter PiP when this activity is made invisible.
+ */
+ public boolean shouldEnterPictureInPictureOnInvisible() {
+ return enterPipOnMoveToBackground;
+ }
+
+ /**
* @return Stack value from current task, null if there is no task.
*/
ActivityStack getStack() {
@@ -920,10 +950,34 @@
&& info.resizeMode != RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
}
+ /**
+ * @return whether this activity's resize mode supports PIP.
+ */
boolean supportsPictureInPicture() {
return !isHomeActivity() && info.resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
}
+ /**
+ * @return whether this activity is currently allowed to enter PIP, if
+ * {@param checkActivityVisibility} is set, then the current activity visibility is taken into
+ * account.
+ */
+ boolean canEnterPictureInPicture(boolean checkActivityVisibility) {
+ if (!checkActivityVisibility) {
+ return supportsPictureInPicture();
+ }
+
+ if (supportsPictureInPicture()) {
+ switch (state) {
+ case RESUMED:
+ case PAUSING:
+ case PAUSED:
+ return true;
+ }
+ }
+ return false;
+ }
+
boolean canGoInDockedStack() {
return !isHomeActivity() && isResizeableOrForced();
}
@@ -1197,10 +1251,11 @@
}
final ActivityStack stack = getStack();
- if (stack.isHomeStack()) {
+ if (stack.isHomeOrRecentsStack()) {
// This is an optimization -- since we never show Home or Recents within Recents itself,
// we can just go ahead and skip taking the screenshot if this is the home stack.
- if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tHome stack");
+ if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, stack.getStackId() == HOME_STACK_ID ?
+ "\tHome stack" : "\tRecents stack");
return null;
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 005b8aa..671c84e 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -690,6 +690,10 @@
return mStackId == HOME_STACK_ID;
}
+ final boolean isHomeOrRecentsStack() {
+ return StackId.isHomeOrRecentsStack(mStackId);
+ }
+
final boolean isDockedStack() {
return mStackId == DOCKED_STACK_ID;
}
@@ -718,7 +722,6 @@
mStacks.remove(this);
int addIndex = mStacks.size();
-
if (addIndex > 0) {
final ActivityStack topStack = mStacks.get(addIndex - 1);
if (StackId.isAlwaysOnTop(topStack.mStackId) && topStack != this) {
@@ -1450,10 +1453,10 @@
return false;
}
- if (!isHomeStack() && r.frontOfTask
- && task.isOverHomeStack() && stackBehindId != HOME_STACK_ID) {
+ if (!isHomeOrRecentsStack() && r.frontOfTask
+ && task.isOverHomeStack() && !StackId.isHomeOrRecentsStack(stackBehindId)) {
// Stack isn't translucent if it's top activity should have the home stack
- // behind it and the stack currently behind it isn't the home stack.
+ // behind it and the stack currently behind it isn't the home or recents stack.
return false;
}
}
@@ -1519,10 +1522,10 @@
}
if (mStackId == FULLSCREEN_WORKSPACE_STACK_ID
- && hasVisibleBehindActivity() && focusedStackId == HOME_STACK_ID
+ && hasVisibleBehindActivity() && StackId.isHomeOrRecentsStack(focusedStackId)
&& !focusedStack.topActivity().fullscreen) {
// The fullscreen stack should be visible if it has a visible behind activity behind
- // the home stack that is translucent.
+ // the home or recents stack that is translucent.
return STACK_VISIBLE_ACTIVITY_BEHIND;
}
@@ -1713,7 +1716,9 @@
+ stackInvisible + " behindFullscreenActivity="
+ behindFullscreenActivity + " mLaunchTaskBehind="
+ r.mLaunchTaskBehind);
- makeInvisible(r, visibleBehind);
+ if (!enterPictureInPictureOnActivityInvisible(r)) {
+ makeInvisible(r, visibleBehind);
+ }
}
}
if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
@@ -1825,11 +1830,10 @@
// If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard
// right away.
return shouldBeVisible && mStackSupervisor.mKeyguardController
- .canShowActivityWhileKeyguardShowing(dismissKeyguard);
+ .canShowActivityWhileKeyguardShowing(r, dismissKeyguard);
} else if (keyguardLocked) {
-
- // Show when locked windows above keyguard.
- return shouldBeVisible && showWhenLocked;
+ return shouldBeVisible && mStackSupervisor.mKeyguardController.canShowWhileOccluded(
+ dismissKeyguard, showWhenLocked);
} else {
return shouldBeVisible;
}
@@ -1872,6 +1876,32 @@
return false;
}
+ /**
+ * Attempts to enter picture-in-picture if the activity that is being made invisible supports
+ * it. If not, then
+ *
+ * @return whether or not picture-in-picture mode was entered.
+ */
+ private boolean enterPictureInPictureOnActivityInvisible(ActivityRecord r) {
+ final boolean hasPinnedStack =
+ mStackSupervisor.getStack(PINNED_STACK_ID) != null;
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, " enterPictureInPictureOnInvisible="
+ + r.shouldEnterPictureInPictureOnInvisible()
+ + " hasPinnedStack=" + hasPinnedStack);
+ if (!hasPinnedStack && r.visible && r.shouldEnterPictureInPictureOnInvisible()) {
+ r.setEnterPipOnMoveToBackground(false);
+
+ // Enter picture in picture, but don't move the home stack to the front
+ // since it will affect the focused stack's visibility and occlude
+ // starting activities
+ mService.enterPictureInPictureModeLocked(r, r.getDisplayId(),
+ r.pictureInPictureAspectRatio, false /* moveHomeStackToFront */,
+ "ensureActivitiesVisibleLocked");
+ return true;
+ }
+ return false;
+ }
+
private void makeInvisible(ActivityRecord r, ActivityRecord visibleBehind) {
if (!r.visible) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + r);
@@ -1922,7 +1952,7 @@
+ " behindFullscreenActivity=" + behindFullscreenActivity);
// At this point, nothing else needs to be shown in this task.
behindFullscreenActivity = true;
- } else if (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()) {
+ } else if (!isHomeOrRecentsStack() && r.frontOfTask && task.isOverHomeStack()) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Showing home: at " + r
+ " stackInvisible=" + stackInvisible
+ " behindFullscreenActivity=" + behindFullscreenActivity);
@@ -2096,9 +2126,7 @@
if (next == null) {
// There are no more activities!
final String reason = "noMoreActivities";
- final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack()
- ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
- if (!mFullscreen && adjustFocusToNextFocusableStackLocked(returnTaskType, reason)) {
+ if (!mFullscreen && adjustFocusToNextFocusableStackLocked(reason)) {
// Try to move focus to the next visible stack with a running activity if this
// stack is not covering the entire screen.
return mStackSupervisor.resumeFocusedStackTopActivityLocked(
@@ -2112,7 +2140,7 @@
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
// Only resume home if on home display
return isOnHomeDisplay() &&
- mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);
+ mStackSupervisor.resumeHomeStackTask(prev, reason);
}
next.delayedResume = false;
@@ -2122,9 +2150,7 @@
mStackSupervisor.allResumedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
- mWindowManager.executeAppTransition();
- mNoAnimActivities.clear();
- ActivityOptions.abort(options);
+ executeAppTransition(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Top activity resumed " + next);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -2147,10 +2173,8 @@
} else if (!isHomeStack()){
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Launching home next");
- final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
- HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
return isOnHomeDisplay() &&
- mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished");
+ mStackSupervisor.resumeHomeStackTask(prev, "prevFinished");
}
}
@@ -2161,9 +2185,7 @@
&& mStackSupervisor.allPausedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
- mWindowManager.executeAppTransition();
- mNoAnimActivities.clear();
- ActivityOptions.abort(options);
+ executeAppTransition(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Going to sleep and all paused");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -2226,9 +2248,7 @@
// So, nothing else to-do except:
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
- mWindowManager.executeAppTransition();
- mNoAnimActivities.clear();
- ActivityOptions.abort(options);
+ executeAppTransition(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -2567,7 +2587,7 @@
// activity, set mTaskToReturnTo accordingly.
if (isOnHomeDisplay()) {
ActivityStack lastStack = mStackSupervisor.getLastStack();
- final boolean fromHome = lastStack.isHomeStack();
+ final boolean fromHomeOrRecents = lastStack.isHomeOrRecentsStack();
final boolean fromOnTopLauncher = lastStack.topTask() != null &&
lastStack.topTask().isOnTopLauncher();
if (fromOnTopLauncher) {
@@ -2576,12 +2596,12 @@
// This also makes sure that non-home activities are visible under a transparent
// non-home activity.
task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
- } else if (!isHomeStack() && (fromHome || topTask() != task)) {
+ } else if (!isHomeOrRecentsStack() && (fromHomeOrRecents || topTask() != task)) {
// If it's a last task over home - we default to keep its return to type not to
// make underlying task focused when this one will be finished.
int returnToType = isLastTaskOverHome
? task.getTaskToReturnTo() : APPLICATION_ACTIVITY_TYPE;
- if (fromHome && StackId.allowTopTaskToReturnHome(mStackId)) {
+ if (fromHomeOrRecents && StackId.allowTopTaskToReturnHome(mStackId)) {
returnToType = lastStack.topTask() == null
? HOME_ACTIVITY_TYPE : lastStack.topTask().taskType;
}
@@ -2613,8 +2633,8 @@
mWindowManager.moveTaskToTop(task.taskId);
}
- final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
- ActivityOptions options) {
+ final void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
+ boolean newTask, boolean keepCurTransition, ActivityOptions options) {
TaskRecord rTask = r.task;
final int taskId = rTask.taskId;
// mLaunchTaskBehind tasks get placed at the back of the task stack.
@@ -2675,7 +2695,7 @@
task.setFrontOfTask();
r.putInHistory();
- if (!isHomeStack() || numActivities() > 0) {
+ if (!isHomeOrRecentsStack() || numActivities() > 0) {
// We want to show the starting preview window if we are
// switching to a new task, or the next activity's process is
// not currently running.
@@ -2693,11 +2713,20 @@
mWindowManager.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
mNoAnimActivities.add(r);
} else {
- mWindowManager.prepareAppTransition(newTask
- ? r.mLaunchTaskBehind
- ? TRANSIT_TASK_OPEN_BEHIND
- : TRANSIT_TASK_OPEN
- : TRANSIT_ACTIVITY_OPEN, keepCurTransition);
+ int transit = TRANSIT_ACTIVITY_OPEN;
+ if (newTask) {
+ if (r.mLaunchTaskBehind) {
+ transit = TRANSIT_TASK_OPEN_BEHIND;
+ } else {
+ // If a new task is being launched, then mark the existing top activity to
+ // enter picture-in-picture if it supports auto-entering PiP
+ if (focusedTopActivity != null) {
+ focusedTopActivity.setEnterPipOnMoveToBackground(true);
+ }
+ transit = TRANSIT_TASK_OPEN;
+ }
+ }
+ mWindowManager.prepareAppTransition(transit, keepCurTransition);
mNoAnimActivities.remove(r);
}
addConfigOverride(r, task);
@@ -2822,7 +2851,7 @@
} else {
targetTask = createTaskRecord(
mStackSupervisor.getNextTaskIdForUserLocked(target.userId),
- target.info, null, null, null, false);
+ target.info, null, null, null, false, target.mActivityType);
targetTask.affinityIntent = target.intent;
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
+ " out to new task " + target.task);
@@ -3114,18 +3143,16 @@
} else {
final TaskRecord task = r.task;
if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
- final int taskToReturnTo = task.getTaskToReturnTo();
-
// For non-fullscreen stack, we want to move the focus to the next visible
// stack to prevent the home screen from moving to the top and obscuring
// other visible stacks.
if (!mFullscreen
- && adjustFocusToNextFocusableStackLocked(taskToReturnTo, myReason)) {
+ && adjustFocusToNextFocusableStackLocked(myReason)) {
return;
}
// Move the home stack to the top if this stack is fullscreen or there is no
// other visible stack.
- if (mStackSupervisor.moveHomeStackTaskToTop(taskToReturnTo, myReason)) {
+ if (mStackSupervisor.moveHomeStackTaskToTop(myReason)) {
// Activity focus was already adjusted. Nothing else to do...
return;
}
@@ -3137,7 +3164,7 @@
mStackSupervisor.topRunningActivityLocked(), myReason);
}
- private boolean adjustFocusToNextFocusableStackLocked(int taskToReturnTo, String reason) {
+ private boolean adjustFocusToNextFocusableStackLocked(String reason) {
final ActivityStack stack = getNextFocusableStackLocked();
final String myReason = reason + " adjustFocusToNextFocusableStack";
if (stack == null) {
@@ -3146,10 +3173,10 @@
final ActivityRecord top = stack.topRunningActivityLocked();
- if (stack.isHomeStack() && (top == null || !top.visible)) {
+ if (stack.isHomeOrRecentsStack() && (top == null || !top.visible)) {
// If we will be focusing on the home stack next and its current top activity isn't
// visible, then use the task return to value to determine the home task to display next.
- return mStackSupervisor.moveHomeStackTaskToTop(taskToReturnTo, reason);
+ return mStackSupervisor.moveHomeStackTaskToTop(reason);
}
stack.moveToFront(myReason);
@@ -3754,7 +3781,7 @@
"removeActivityFromHistoryLocked: last activity removed from " + this);
if (mStackSupervisor.isFocusedStack(this) && task == topTask() &&
task.isOverHomeStack()) {
- mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(), reason);
+ mStackSupervisor.moveHomeStackTaskToTop(reason);
}
removeTask(task, reason);
}
@@ -4176,11 +4203,11 @@
mStackSupervisor.invalidateTaskLayers();
}
- void moveHomeStackTaskToTop(int homeStackTaskType) {
+ void moveHomeStackTaskToTop() {
final int top = mTaskHistory.size() - 1;
for (int taskNdx = top; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
- if (task.taskType == homeStackTaskType) {
+ if (task.taskType == HOME_ACTIVITY_TYPE) {
if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG_STACK,
"moveHomeStackTaskToTop: moving " + task);
mTaskHistory.remove(taskNdx);
@@ -4195,6 +4222,8 @@
AppTimeTracker timeTracker, String reason) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
+ final ActivityRecord focusedTopActivity = mStackSupervisor.getFocusedStack() != null
+ ? mStackSupervisor.getFocusedStack().topActivity() : null;
final int numTasks = mTaskHistory.size();
final int index = mTaskHistory.indexOf(tr);
if (numTasks == 0 || index < 0) {
@@ -4240,6 +4269,11 @@
} else {
updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
}
+ // If a new task is moved to the front, then mark the existing top activity to enter
+ // picture-in-picture if it supports auto-entering PiP
+ if (focusedTopActivity != null) {
+ focusedTopActivity.setEnterPipOnMoveToBackground(true);
+ }
mStackSupervisor.resumeFocusedStackTopActivityLocked();
EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
@@ -4306,7 +4340,7 @@
moveToBack(topTask());
// Resume an activity in the next focusable stack.
- adjustFocusToNextFocusableStackLocked(APPLICATION_ACTIVITY_TYPE, "moveTaskToBack");
+ adjustFocusToNextFocusableStackLocked("moveTaskToBack");
mStackSupervisor.resumeFocusedStackTopActivityLocked();
return true;
}
@@ -4365,9 +4399,8 @@
// Not ready yet!
return false;
}
- final int taskToReturnTo = tr.getTaskToReturnTo();
tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
- return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null, "moveTaskToBack");
+ return mStackSupervisor.resumeHomeStackTask(null, "moveTaskToBack");
}
mStackSupervisor.resumeFocusedStackTopActivityLocked();
@@ -4840,9 +4873,7 @@
if (isOnHomeDisplay() && mode != REMOVE_TASK_MODE_MOVING_TO_TOP
&& mStackSupervisor.isFocusedStack(this)) {
String myReason = reason + " leftTaskHistoryEmpty";
- if (mFullscreen
- || !adjustFocusToNextFocusableStackLocked(
- task.getTaskToReturnTo(), myReason)) {
+ if (mFullscreen || !adjustFocusToNextFocusableStackLocked(myReason)) {
mStackSupervisor.moveHomeStackToFront(myReason);
}
}
@@ -4850,7 +4881,7 @@
mStacks.remove(this);
mStacks.add(0, this);
}
- if (!isHomeStack()) {
+ if (!isHomeOrRecentsStack()) {
mActivityContainer.onTaskListEmptyLocked();
}
}
@@ -4860,9 +4891,9 @@
TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
- boolean toTop) {
+ boolean toTop, int type) {
TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession,
- voiceInteractor);
+ voiceInteractor, type);
// add the task to stack first, mTaskPositioner might need the stack association
addTask(task, toTop, "createTaskRecord");
final boolean isLockscreenShown =
@@ -4871,6 +4902,11 @@
&& !isLockscreenShown) {
task.updateOverrideConfiguration(mBounds);
}
+ final Rect bounds = task.updateOverrideConfigurationFromLaunchBounds();
+ final boolean showForAllUsers = (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
+ mWindowManager.addTask(taskId, mStackId, task.userId, bounds,
+ task.getOverrideConfiguration(), task.mResizeMode, task.isHomeTask(),
+ task.isOnTopLauncher(), toTop, showForAllUsers);
return task;
}
@@ -4937,15 +4973,13 @@
}
void addConfigOverride(ActivityRecord r, TaskRecord task) {
- final Rect bounds = task.updateOverrideConfigurationFromLaunchBounds();
+ task.updateOverrideConfigurationFromLaunchBounds();
// TODO: VI deal with activity
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
- r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
- (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId, r.info.configChanges,
- task.voiceSession != null, r.mLaunchTaskBehind, bounds,
- task.getOverrideConfiguration(), task.mResizeMode, r.isAlwaysFocusable(),
- task.isHomeTask(), r.appInfo.targetSdkVersion, r.mRotationAnimationHint,
- task.isOnTopLauncher());
+ r.task.taskId, r.info.screenOrientation, r.fullscreen,
+ (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, r.info.configChanges,
+ task.voiceSession != null, r.mLaunchTaskBehind, r.isAlwaysFocusable(),
+ r.appInfo.targetSdkVersion, r.mRotationAnimationHint);
r.onOverrideConfigurationSent();
}
@@ -4984,7 +5018,7 @@
final TaskRecord task = createTaskRecord(
mStackSupervisor.getNextTaskIdForUserLocked(r.userId),
- r.info, r.intent, null, null, true);
+ r.info, r.intent, null, null, true, r.mActivityType);
r.setTask(task, null);
task.addActivityToTop(r);
setAppTask(r, task);
@@ -4996,10 +5030,8 @@
}
private void setAppTask(ActivityRecord r, TaskRecord task) {
- final Rect bounds = task.updateOverrideConfigurationFromLaunchBounds();
- mWindowManager.setAppTask(r.appToken, task.taskId, mStackId, bounds,
- task.getOverrideConfiguration(), task.mResizeMode, task.isHomeTask(),
- task.isOnTopLauncher());
+ task.updateOverrideConfigurationFromLaunchBounds();
+ mWindowManager.addAppToTask(r.appToken, task.taskId);
r.onOverrideConfigurationSent();
}
@@ -5018,4 +5050,10 @@
mTaskHistory.get(taskNdx).setLockTaskAuth();
}
}
+
+ void executeAppTransition(ActivityOptions options) {
+ mWindowManager.executeAppTransition();
+ mNoAnimActivities.clear();
+ ActivityOptions.abort(options);
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 48108fe..fe261f1 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -33,6 +33,7 @@
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -72,7 +73,6 @@
import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
-import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
@@ -661,13 +661,8 @@
}
/** Returns true if the focus activity was adjusted to the home stack top activity. */
- boolean moveHomeStackTaskToTop(int homeStackTaskType, String reason) {
- if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
- mWindowManager.showRecentApps(false /* fromHome */);
- return false;
- }
-
- mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
+ boolean moveHomeStackTaskToTop(String reason) {
+ mHomeStack.moveHomeStackTaskToTop();
final ActivityRecord top = getHomeActivity();
if (top == null) {
@@ -677,22 +672,17 @@
return true;
}
- boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev, String reason) {
+ boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
- if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
- mWindowManager.showRecentApps(false /* fromHome */);
- return false;
- }
-
if (prev != null) {
prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
}
- mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
+ mHomeStack.moveHomeStackTaskToTop();
ActivityRecord r = getHomeActivity();
final String myReason = reason + " resumeHomeStackTask";
@@ -1854,6 +1844,9 @@
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || r.state != RESUMED) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
+ } else if (r.state == RESUMED) {
+ // Kick off any lingering app transitions form the MoveTaskToFront operation.
+ mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
@@ -2332,6 +2325,11 @@
return true;
}
+ if (!task.canResizeToBounds(bounds)) {
+ throw new IllegalArgumentException("resizeTaskLocked: Can not resize task=" + task
+ + " to bounds=" + bounds + " resizeMode=" + task.mResizeMode);
+ }
+
// Do not move the task to another stack here.
// This method assumes that the task is already placed in the right stack.
// we do not mess with that decision and we only do the resize!
@@ -2429,7 +2427,11 @@
return false;
}
- stack.addTask(task, false, "restoreRecentTask");
+ stack.addTask(task, false /* toTop */, "restoreRecentTask");
+ final Rect bounds = task.updateOverrideConfigurationFromLaunchBounds();
+ mWindowManager.addTask(task.taskId, stack.mStackId, task.userId, bounds,
+ task.getOverrideConfiguration(), task.mResizeMode, task.isHomeTask(),
+ task.isOnTopLauncher(), false /* toTop */, true /* showForAllUsers */);
if (DEBUG_RECENTS) Slog.v(TAG_RECENTS,
"Added restored task=" + task + " to stack=" + stack);
final ArrayList<ActivityRecord> activities = task.mActivities;
@@ -2648,11 +2650,13 @@
return false;
}
- moveActivityToPinnedStackLocked(r, "moveTopActivityToPinnedStack", bounds);
+ moveActivityToPinnedStackLocked(r, "moveTopActivityToPinnedStack", bounds,
+ true /* moveHomeStackToFront */);
return true;
}
- void moveActivityToPinnedStackLocked(ActivityRecord r, String reason, Rect bounds) {
+ void moveActivityToPinnedStackLocked(ActivityRecord r, String reason, Rect bounds,
+ boolean moveHomeStackToFront) {
mWindowManager.deferSurfaceLayout();
try {
final TaskRecord task = r.task;
@@ -2676,7 +2680,7 @@
if (task.mActivities.size() == 1) {
// There is only one activity in the task. So, we can just move the task over to
// the stack without re-parenting the activity in a different task.
- if (task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE) {
+ if (moveHomeStackToFront && task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE) {
// Move the home stack forward if the task we just moved to the pinned stack
// was launched from home so home should be visible behind it.
moveHomeStackToFront(reason);
@@ -2684,6 +2688,8 @@
moveTaskToStackLocked(
task.taskId, PINNED_STACK_ID, ON_TOP, FORCE_FOCUS, reason, !ANIMATE);
} else {
+ // There are multiple activities in the task and moving the top activity should
+ // reveal/leave the other activities in their original task
stack.moveActivityToStack(r);
}
} finally {
@@ -2754,7 +2760,7 @@
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
- if (!r.isApplicationActivity() && !stack.isHomeStack()) {
+ if (!r.isApplicationActivity() && !stack.isHomeOrRecentsStack()) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping stack: (home activity) " + stack);
continue;
}
@@ -3178,7 +3184,7 @@
stack.moveToFront("switchUserOnHomeDisplay");
} else {
// Stack was moved to another display while user was swapped out.
- resumeHomeStackTask(HOME_ACTIVITY_TYPE, null, "switchUserOnOtherDisplay");
+ resumeHomeStackTask(null, "switchUserOnOtherDisplay");
}
return homeInFront;
}
@@ -4597,9 +4603,9 @@
? new ActivityOptions(bOptions) : null;
final int launchStackId = (activityOptions != null)
? activityOptions.getLaunchStackId() : INVALID_STACK_ID;
- if (launchStackId == HOME_STACK_ID) {
+ if (StackId.isHomeOrRecentsStack(launchStackId)) {
throw new IllegalArgumentException("startActivityFromRecentsInner: Task "
- + taskId + " can't be launch in the home stack.");
+ + taskId + " can't be launch in the home/recents stack.");
}
if (launchStackId == DOCKED_STACK_ID) {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index dff7cef..3bb9ccc 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -32,6 +32,7 @@
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.isStaticStack;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
@@ -589,7 +590,7 @@
}
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
- mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
+ mSupervisor.moveHomeStackTaskToTop(reason);
startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
@@ -1067,6 +1068,7 @@
// If the activity being launched is the same as the one currently at the top, then
// we need to check if it should only be launched once.
final ActivityStack topStack = mSupervisor.mFocusedStack;
+ final ActivityRecord topFocused = topStack.topActivity();
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
final boolean dontStart = top != null && mStartActivity.resultTo == null
&& top.realActivity.equals(mStartActivity.realActivity)
@@ -1138,7 +1140,8 @@
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
- mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
+ mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
+ mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
if (!mTargetStack.isFocusable()
@@ -1524,8 +1527,8 @@
private void updateTaskReturnToType(
TaskRecord task, int launchFlags, ActivityStack focusedStack) {
- if (focusedStack != null && focusedStack.isHomeStack() && focusedStack.topTask() != null
- && focusedStack.topTask().isOnTopLauncher()) {
+ if (focusedStack != null && focusedStack.isHomeOrRecentsStack()
+ && focusedStack.topTask() != null && focusedStack.topTask().isOnTopLauncher()) {
// Since an on-top launcher will is moved to back when tasks are launched from it,
// those tasks should first try to return to a non-home activity.
// This also makes sure that non-home activities are visible under a transparent
@@ -1639,8 +1642,8 @@
final TaskRecord task = mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
- mNewTaskIntent != null ? mNewTaskIntent : mIntent,
- mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
+ mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
+ mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
mStartActivity.setTask(task, taskToAffiliate);
if (mLaunchBounds != null) {
final int stackId = mTargetStack.mStackId;
@@ -1814,8 +1817,8 @@
}
final ActivityRecord prev = mTargetStack.topActivity();
final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
- mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
- mStartActivity.info, mIntent, null, null, true);
+ mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
+ mIntent, null, null, true, mStartActivity.mActivityType);
mStartActivity.setTask(task, null);
mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
if (DEBUG_TASKS) Slog.v(TAG_TASKS,
@@ -1869,7 +1872,10 @@
private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
int launchFlags, ActivityOptions aOptions) {
final TaskRecord task = r.task;
- if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
+ if (r.isRecentsActivity()) {
+ return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
+ }
+ if (r.isHomeActivity()) {
return mSupervisor.mHomeStack;
}
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index 5e02597..cfe2eb0 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -57,6 +57,7 @@
private boolean mKeyguardShowing;
private boolean mKeyguardGoingAway;
private boolean mOccluded;
+ private boolean mDismissalRequested;
private ActivityRecord mDismissingKeyguardActivity;
private int mBeforeUnoccludeTransit;
private int mVisibilityTransactionDepth;
@@ -95,9 +96,7 @@
mKeyguardShowing = showing;
if (showing) {
mKeyguardGoingAway = false;
-
- // Allow an activity to redismiss Keyguard.
- mDismissingKeyguardActivity = null;
+ mDismissalRequested = false;
}
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mService.updateSleepIfNeededLocked();
@@ -122,8 +121,6 @@
// Some stack visibility might change (e.g. docked stack)
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
- mService.applyVrModeIfNeededLocked(mStackSupervisor.getResumedActivityLocked(),
- true /* enable */);
} finally {
mWindowManager.continueSurfaceLayout();
}
@@ -183,8 +180,20 @@
* @return True if we may show an activity while Keyguard is showing because we are in the
* process of dismissing it anyways, false otherwise.
*/
- boolean canShowActivityWhileKeyguardShowing(boolean dismissKeyguard) {
- return dismissKeyguard && canDismissKeyguard();
+ boolean canShowActivityWhileKeyguardShowing(ActivityRecord r, boolean dismissKeyguard) {
+
+ // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is
+ // already the dismissing activity, in which case we don't allow it to repeatedly dismiss
+ // Keyguard.
+ return dismissKeyguard && canDismissKeyguard() &&
+ (mDismissalRequested || r != mDismissingKeyguardActivity);
+ }
+
+ /**
+ * @return True if we may show an activity while Keyguard is occluded, false otherwise.
+ */
+ boolean canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked) {
+ return showWhenLocked || dismissKeyguard && !mWindowManager.isKeyguardSecure();
}
private void visibilitiesUpdated() {
@@ -199,7 +208,14 @@
// Only the very top activity may control occluded state
if (stackNdx == topStackNdx) {
- mOccluded = stack.topActivityOccludesKeyguard();
+
+ // A dismissing activity occludes Keyguard in the insecure case for legacy reasons.
+ final ActivityRecord topDismissing = stack.getTopDismissingKeyguardActivity();
+ mOccluded = stack.topActivityOccludesKeyguard()
+ || (topDismissing != null
+ && stack.topRunningActivityLocked() == topDismissing
+ && canShowWhileOccluded(true /* dismissKeyguard */,
+ false /* showWhenLocked */));
}
if (mDismissingKeyguardActivity == null
&& stack.getTopDismissingKeyguardActivity() != null) {
@@ -239,8 +255,13 @@
* Called when somebody might want to dismiss the Keyguard.
*/
private void handleDismissKeyguard() {
- if (mDismissingKeyguardActivity != null) {
+ // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy
+ // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the
+ // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
+ if (!mOccluded && mDismissingKeyguardActivity != null
+ && mWindowManager.isKeyguardSecure()) {
mWindowManager.dismissKeyguard(null /* callback */);
+ mDismissalRequested = true;
// If we are about to unocclude the Keyguard, but we can dismiss it without security,
// we immediately dismiss the Keyguard so the activity gets shown without a flicker.
@@ -296,6 +317,7 @@
pw.println(prefix + " mKeyguardGoingAway=" + mKeyguardGoingAway);
pw.println(prefix + " mOccluded=" + mOccluded);
pw.println(prefix + " mDismissingKeyguardActivity=" + mDismissingKeyguardActivity);
+ pw.println(prefix + " mDismissalRequested=" + mDismissalRequested);
pw.println(prefix + " mVisibilityTransactionDepth=" + mVisibilityTransactionDepth);
}
}
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index bc9bda2f..6a13d36 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -130,8 +130,8 @@
void notifyTaskPersisterLocked(TaskRecord task, boolean flush) {
final ActivityStack stack = task != null ? task.getStack() : null;
- if (stack != null && stack.isHomeStack()) {
- // Never persist the home stack.
+ if (stack != null && stack.isHomeOrRecentsStack()) {
+ // Never persist the home or recents stack.
return;
}
syncPersistentTaskIdsLocked();
@@ -150,7 +150,7 @@
for (int i = size() - 1; i >= 0; i--) {
final TaskRecord task = get(i);
final ActivityStack stack = task.getStack();
- if (task.isPersistable && (stack == null || !stack.isHomeStack())) {
+ if (task.isPersistable && (stack == null || !stack.isHomeOrRecentsStack())) {
// Set of persisted taskIds for task.userId should not be null here
// TODO Investigate why it can happen. For now initialize with an empty set
if (mPersistedTaskIds.get(task.userId) == null) {
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 1ecb2e9..7a62f2c 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -643,7 +643,7 @@
" persistable=" + task.isPersistable);
final ActivityStack stack = task.getStack();
if ((task.isPersistable || task.inRecents)
- && (stack == null || !stack.isHomeStack())) {
+ && (stack == null || !stack.isHomeOrRecentsStack())) {
if (DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
persistentTaskIds.add(task.taskId);
} else {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 0bc12ee..9e28068 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -64,6 +64,7 @@
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.pm.ActivityInfo.FLAG_ON_TOP_LAUNCHER;
@@ -72,6 +73,9 @@
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
@@ -277,7 +281,7 @@
private Configuration mTmpConfig = new Configuration();
TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
- IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
+ IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, int type) {
mService = service;
mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
TaskPersister.IMAGE_EXTENSION;
@@ -292,6 +296,7 @@
mActivities = new ArrayList<>();
mCallingUid = info.applicationInfo.uid;
mCallingPackage = info.packageName;
+ taskType = type;
setIntent(_intent, info);
setMinDimensions(info);
touchActiveTime();
@@ -317,7 +322,6 @@
setIntent(_intent, info);
setMinDimensions(info);
- taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
isPersistable = true;
// Clamp to [1, max].
maxRecents = Math.min(Math.max(info.maxRecents, 1),
@@ -1068,7 +1072,7 @@
}
boolean isOverHomeStack() {
- return mTaskToReturnTo == HOME_ACTIVITY_TYPE || mTaskToReturnTo == RECENTS_ACTIVITY_TYPE;
+ return mTaskToReturnTo == HOME_ACTIVITY_TYPE;
}
boolean isResizeable() {
@@ -1076,12 +1080,32 @@
&& !mTemporarilyUnresizable;
}
+ /**
+ * Check that a given bounds matches the application requested orientation.
+ *
+ * @param bounds The bounds to be tested.
+ * @return True if the requested bounds are okay for a resizing request.
+ */
+ boolean canResizeToBounds(Rect bounds) {
+ if (bounds == null || getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
+ // Note: If not on the freeform workspace, we ignore the bounds.
+ return true;
+ }
+ final boolean landscape = bounds.width() > bounds.height();
+ if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
+ return mBounds == null || landscape == (mBounds.width() > mBounds.height());
+ }
+ return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
+ && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
+ }
+
boolean isOnTopLauncher() {
return isHomeTask() && mIsOnTopLauncher;
}
boolean canGoInDockedStack() {
- return isResizeable();
+ return isResizeable() && mService.mSupportsSplitScreenMultiWindow &&
+ !ActivityInfo.isPreserveOrientationMode(mResizeMode);
}
/**
@@ -1685,7 +1709,10 @@
* The task will be moved (and stack focus changed) later if necessary.
*/
int getLaunchStackId() {
- if (!isApplicationTask()) {
+ if (isRecentsTask()) {
+ return RECENTS_STACK_ID;
+ }
+ if (isHomeTask()) {
return HOME_STACK_ID;
}
if (mBounds != null) {
@@ -1707,6 +1734,7 @@
final int stackId = mStack.mStackId;
if (stackId == HOME_STACK_ID
+ || stackId == RECENTS_STACK_ID
|| stackId == FULLSCREEN_WORKSPACE_STACK_ID
|| (stackId == DOCKED_STACK_ID && !isResizeable())) {
return isResizeable() ? mStack.mBounds : null;
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index aa66917..5e98859 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -97,6 +97,24 @@
private static final int SOCKET_TIMEOUT_MS = 10000;
private static final int PROBE_TIMEOUT_MS = 3000;
+ static enum EvaluationResult {
+ VALIDATED(true),
+ CAPTIVE_PORTAL(false);
+ final boolean isValidated;
+ EvaluationResult(boolean isValidated) {
+ this.isValidated = isValidated;
+ }
+ }
+
+ static enum ValidationStage {
+ FIRST_VALIDATION(true),
+ REVALIDATION(false);
+ final boolean isFirstValidation;
+ ValidationStage(boolean isFirstValidation) {
+ this.isFirstValidation = isFirstValidation;
+ }
+ }
+
public static final String ACTION_NETWORK_CONDITIONS_MEASURED =
"android.net.conn.NETWORK_CONDITIONS_MEASURED";
public static final String EXTRA_CONNECTIVITY_TYPE = "extra_connectivity_type";
@@ -216,6 +234,8 @@
protected boolean mIsCaptivePortalCheckEnabled;
private boolean mUseHttps;
+ // The total number of captive portal detection attempts for this NetworkMonitor instance.
+ private int mValidations = 0;
// Set if the user explicitly selected "Do not use this network" in captive portal sign-in app.
private boolean mUserDoesNotWant = false;
@@ -290,6 +310,10 @@
return validationLogs.readOnlyLocalLog();
}
+ private ValidationStage validationStage() {
+ return 0 == mValidations ? ValidationStage.FIRST_VALIDATION : ValidationStage.REVALIDATION;
+ }
+
// DefaultState is the parent of all States. It exists only to handle CMD_* messages but
// does not entail any real state (hence no enter() or exit() routines).
private class DefaultState extends State {
@@ -366,9 +390,11 @@
private class ValidatedState extends State {
@Override
public void enter() {
- maybeLogEvaluationResult(NetworkEvent.NETWORK_VALIDATED);
+ maybeLogEvaluationResult(
+ networkEventType(validationStage(), EvaluationResult.VALIDATED));
mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
NETWORK_TEST_RESULT_VALID, mNetworkAgentInfo.network.netId, null));
+ mValidations++;
}
@Override
@@ -584,7 +610,8 @@
@Override
public void enter() {
- maybeLogEvaluationResult(NetworkEvent.NETWORK_CAPTIVE_PORTAL_FOUND);
+ maybeLogEvaluationResult(
+ networkEventType(validationStage(), EvaluationResult.CAPTIVE_PORTAL));
// Don't annoy user with sign-in notifications.
if (mDontDisplaySigninNotification) return;
// Create a CustomIntentReceiver that sends us a
@@ -604,6 +631,7 @@
// Retest for captive portal occasionally.
sendMessageDelayed(CMD_CAPTIVE_PORTAL_RECHECK, 0 /* no UID */,
CAPTIVE_PORTAL_REEVALUATE_DELAY_MS);
+ mValidations++;
}
@Override
@@ -679,48 +707,13 @@
long startTime = SystemClock.elapsedRealtime();
- // Pre-resolve the captive portal server host so we can log it.
- // Only do this if HttpURLConnection is about to, to avoid any potentially
- // unnecessary resolution.
- String hostToResolve = null;
+ final CaptivePortalProbeResult result;
if (pacUrl != null) {
- hostToResolve = pacUrl.getHost();
- } else if (proxyInfo != null) {
- hostToResolve = proxyInfo.getHost();
- } else {
- hostToResolve = httpUrl.getHost();
- }
-
- if (!TextUtils.isEmpty(hostToResolve)) {
- String probeName = ValidationProbeEvent.getProbeName(ValidationProbeEvent.PROBE_DNS);
- final Stopwatch dnsTimer = new Stopwatch().start();
- int dnsResult;
- long dnsLatency;
- try {
- InetAddress[] addresses = mNetworkAgentInfo.network.getAllByName(hostToResolve);
- dnsResult = ValidationProbeEvent.DNS_SUCCESS;
- dnsLatency = dnsTimer.stop();
- final StringBuffer connectInfo = new StringBuffer(", " + hostToResolve + "=");
- for (InetAddress address : addresses) {
- connectInfo.append(address.getHostAddress());
- if (address != addresses[addresses.length-1]) connectInfo.append(",");
- }
- validationLog(probeName + " OK " + dnsLatency + "ms" + connectInfo);
- } catch (UnknownHostException e) {
- dnsResult = ValidationProbeEvent.DNS_FAILURE;
- dnsLatency = dnsTimer.stop();
- validationLog(probeName + " FAIL " + dnsLatency + "ms, " + hostToResolve);
- }
- logValidationProbe(dnsLatency, ValidationProbeEvent.PROBE_DNS, dnsResult);
- }
-
- CaptivePortalProbeResult result;
- if (pacUrl != null) {
- result = sendHttpProbe(pacUrl, ValidationProbeEvent.PROBE_PAC);
+ result = sendDnsAndHttpProbes(null, pacUrl, ValidationProbeEvent.PROBE_PAC);
} else if (mUseHttps) {
- result = sendParallelHttpProbes(httpsUrl, httpUrl, fallbackUrl);
+ result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl, fallbackUrl);
} else {
- result = sendHttpProbe(httpUrl, ValidationProbeEvent.PROBE_HTTP);
+ result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP);
}
long endTime = SystemClock.elapsedRealtime();
@@ -733,8 +726,50 @@
}
/**
- * Do a URL fetch on a known server to see if we get the data we expect.
- * Returns HTTP response code.
+ * Do a DNS resolution and URL fetch on a known web server to see if we get the data we expect.
+ * @return a CaptivePortalProbeResult inferred from the HTTP response.
+ */
+ private CaptivePortalProbeResult sendDnsAndHttpProbes(ProxyInfo proxy, URL url, int probeType) {
+ // Pre-resolve the captive portal server host so we can log it.
+ // Only do this if HttpURLConnection is about to, to avoid any potentially
+ // unnecessary resolution.
+ final String host = (proxy != null) ? proxy.getHost() : url.getHost();
+ sendDnsProbe(host);
+ return sendHttpProbe(url, probeType);
+ }
+
+ /** Do a DNS resolution of the given server. */
+ private void sendDnsProbe(String host) {
+ if (TextUtils.isEmpty(host)) {
+ return;
+ }
+
+ final String name = ValidationProbeEvent.getProbeName(ValidationProbeEvent.PROBE_DNS);
+ final Stopwatch watch = new Stopwatch().start();
+ int result;
+ String connectInfo;
+ try {
+ InetAddress[] addresses = mNetworkAgentInfo.network.getAllByName(host);
+ result = ValidationProbeEvent.DNS_SUCCESS;
+ StringBuffer buffer = new StringBuffer(host).append("=");
+ for (InetAddress address : addresses) {
+ buffer.append(address.getHostAddress());
+ if (address != addresses[addresses.length-1]) buffer.append(",");
+ }
+ connectInfo = buffer.toString();
+ } catch (UnknownHostException e) {
+ result = ValidationProbeEvent.DNS_FAILURE;
+ connectInfo = host;
+ }
+ final long latency = watch.stop();
+ String resultString = (ValidationProbeEvent.DNS_SUCCESS == result) ? "OK" : "FAIL";
+ validationLog(String.format("%s %s %dms, %s", name, resultString, latency, connectInfo));
+ logValidationProbe(latency, ValidationProbeEvent.PROBE_DNS, result);
+ }
+
+ /**
+ * Do a URL fetch on a known web server to see if we get the data we expect.
+ * @return a CaptivePortalProbeResult inferred from the HTTP response.
*/
@VisibleForTesting
protected CaptivePortalProbeResult sendHttpProbe(URL url, int probeType) {
@@ -801,7 +836,7 @@
}
private CaptivePortalProbeResult sendParallelHttpProbes(
- URL httpsUrl, URL httpUrl, URL fallbackUrl) {
+ ProxyInfo proxy, URL httpsUrl, URL httpUrl, URL fallbackUrl) {
// Number of probes to wait for. If a probe completes with a conclusive answer
// it shortcuts the latch immediately by forcing the count to 0.
final CountDownLatch latch = new CountDownLatch(2);
@@ -821,9 +856,10 @@
@Override
public void run() {
if (mIsHttps) {
- mResult = sendHttpProbe(httpsUrl, ValidationProbeEvent.PROBE_HTTPS);
+ mResult =
+ sendDnsAndHttpProbes(proxy, httpsUrl, ValidationProbeEvent.PROBE_HTTPS);
} else {
- mResult = sendHttpProbe(httpUrl, ValidationProbeEvent.PROBE_HTTP);
+ mResult = sendDnsAndHttpProbes(proxy, httpUrl, ValidationProbeEvent.PROBE_HTTP);
}
if ((mIsHttps && mResult.isSuccessful()) || (!mIsHttps && mResult.isPortal())) {
// Stop waiting immediately if https succeeds or if http finds a portal.
@@ -974,6 +1010,22 @@
mMetricsLog.log(new NetworkEvent(mNetId, evtype));
}
+ private int networkEventType(ValidationStage s, EvaluationResult r) {
+ if (s.isFirstValidation) {
+ if (r.isValidated) {
+ return NetworkEvent.NETWORK_FIRST_VALIDATION_SUCCESS;
+ } else {
+ return NetworkEvent.NETWORK_FIRST_VALIDATION_PORTAL_FOUND;
+ }
+ } else {
+ if (r.isValidated) {
+ return NetworkEvent.NETWORK_REVALIDATION_SUCCESS;
+ } else {
+ return NetworkEvent.NETWORK_REVALIDATION_PORTAL_FOUND;
+ }
+ }
+ }
+
private void maybeLogEvaluationResult(int evtype) {
if (mEvaluationTimer.isRunning()) {
mMetricsLog.log(new NetworkEvent(mNetId, evtype, mEvaluationTimer.stop()));
@@ -982,6 +1034,8 @@
}
private void logValidationProbe(long durationMs, int probeType, int probeResult) {
+ probeType =
+ ValidationProbeEvent.makeProbeType(probeType, validationStage().isFirstValidation);
mMetricsLog.log(new ValidationProbeEvent(mNetId, durationMs, probeType, probeResult));
}
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index c6bf4c5..9ffa40b 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -27,7 +27,7 @@
import android.os.UserHandle;
import android.telephony.TelephonyManager;
import android.util.Slog;
-
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.R;
import static android.net.NetworkCapabilities.*;
@@ -37,7 +37,8 @@
public static enum NotificationType { SIGN_IN, NO_INTERNET, LOST_INTERNET, NETWORK_SWITCH };
- private static final String NOTIFICATION_ID = "Connectivity.Notification";
+ @VisibleForTesting
+ static final String NOTIFICATION_ID = "Connectivity.Notification";
private static final String TAG = NetworkNotificationManager.class.getSimpleName();
private static final boolean DBG = true;
diff --git a/services/core/java/com/android/server/firewall/IntentFirewall.java b/services/core/java/com/android/server/firewall/IntentFirewall.java
index 7e19c66..19eed35 100644
--- a/services/core/java/com/android/server/firewall/IntentFirewall.java
+++ b/services/core/java/com/android/server/firewall/IntentFirewall.java
@@ -151,7 +151,8 @@
// For the first pass, find all the rules that have at least one intent-filter or
// component-filter that matches this intent
List<Rule> candidateRules;
- candidateRules = resolver.queryIntent(intent, resolvedType, false, 0);
+ candidateRules = resolver.queryIntent(intent, resolvedType, false /*defaultOnly*/,
+ false /*visibleToEphemeral*/, false /*isEphemeral*/, 0);
if (candidateRules == null) {
candidateRules = new ArrayList<Rule>();
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 44aafa8..e5f4282 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -888,13 +888,42 @@
}
/**
- * Send a key event to other device.
+ * Send a key event to other CEC device. The logical address of target device will be given by
+ * {@link #findKeyReceiverAddress}.
*
* @param keyCode key code defined in {@link android.view.KeyEvent}
* @param isPressed {@code true} for key down event
+ * @see #findKeyReceiverAddress()
*/
+ @ServiceThreadOnly
protected void sendKeyEvent(int keyCode, boolean isPressed) {
- Slog.w(TAG, "sendKeyEvent not implemented");
+ assertRunOnServiceThread();
+ if (!HdmiCecKeycode.isSupportedKeycode(keyCode)) {
+ Slog.w(TAG, "Unsupported key: " + keyCode);
+ return;
+ }
+ List<SendKeyAction> action = getActions(SendKeyAction.class);
+ int logicalAddress = findKeyReceiverAddress();
+ if (logicalAddress == Constants.ADDR_INVALID || logicalAddress == mAddress) {
+ // Don't send key event to invalid device or itself.
+ Slog.w(TAG, "Discard key event: " + keyCode + ", pressed:" + isPressed
+ + ", receiverAddr=" + logicalAddress);
+ } else if (!action.isEmpty()) {
+ action.get(0).processKeyEvent(keyCode, isPressed);
+ } else if (isPressed) {
+ addAndStartAction(new SendKeyAction(this, logicalAddress, keyCode));
+ }
+ }
+
+ /**
+ * Returns the logical address of the device which will receive key events via
+ * {@link #sendKeyEvent}.
+ *
+ * @see #sendKeyEvent(int, boolean)
+ */
+ protected int findKeyReceiverAddress() {
+ Slog.w(TAG, "findKeyReceiverAddress is not implemented");
+ return Constants.ADDR_INVALID;
}
void sendUserControlPressedAndReleased(int targetAddress, int cecKeycode) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 69c012e..d45b00b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -355,6 +355,11 @@
}
@Override
+ protected int findKeyReceiverAddress() {
+ return Constants.ADDR_TV;
+ }
+
+ @Override
@ServiceThreadOnly
protected void sendStandby(int deviceId) {
assertRunOnServiceThread();
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index c85d979..4526ab74 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -432,40 +432,8 @@
return mService.getPowerStatus();
}
- /**
- * Sends key to a target CEC device.
- *
- * @param keyCode key code to send. Defined in {@link android.view.KeyEvent}.
- * @param isPressed true if this is key press event
- */
@Override
- @ServiceThreadOnly
- protected void sendKeyEvent(int keyCode, boolean isPressed) {
- assertRunOnServiceThread();
- if (!HdmiCecKeycode.isSupportedKeycode(keyCode)) {
- Slog.w(TAG, "Unsupported key: " + keyCode);
- return;
- }
- List<SendKeyAction> action = getActions(SendKeyAction.class);
- int logicalAddress = findKeyReceiverAddress();
- if (logicalAddress == mAddress) {
- Slog.w(TAG, "Discard key event to itself :" + keyCode + " pressed:" + isPressed);
- return;
- }
- if (!action.isEmpty()) {
- action.get(0).processKeyEvent(keyCode, isPressed);
- } else {
- if (isPressed) {
- if (logicalAddress != Constants.ADDR_INVALID) {
- addAndStartAction(new SendKeyAction(this, logicalAddress, keyCode));
- return;
- }
- }
- Slog.w(TAG, "Discard key event: " + keyCode + " pressed:" + isPressed);
- }
- }
-
- private int findKeyReceiverAddress() {
+ protected int findKeyReceiverAddress() {
if (getActiveSource().isValid()) {
return getActiveSource().logicalAddress;
}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 45f54a9..fb2b961 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -95,7 +95,8 @@
import java.util.Date;
import java.util.Map.Entry;
import java.util.Properties;
-
+import java.util.Map;
+import java.util.HashMap;
import libcore.io.IoUtils;
/**
@@ -211,24 +212,18 @@
private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
- // Request ref location
- private static final int AGPS_RIL_REQUEST_REFLOC_CELLID = 1;
- private static final int AGPS_RIL_REQUEST_REFLOC_MAC = 2;
+ //TODO(b/33112647): Create gps_debug.conf with commented career parameters.
+ private static final String DEBUG_PROPERTIES_FILE = "/etc/gps_debug.conf";
// ref. location info
private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
- private static final int AGPS_REG_LOCATION_TYPE_MAC = 3;
// set id info
private static final int AGPS_SETID_TYPE_NONE = 0;
private static final int AGPS_SETID_TYPE_IMSI = 1;
private static final int AGPS_SETID_TYPE_MSISDN = 2;
- private static final String PROPERTIES_FILE_PREFIX = "/etc/gps";
- private static final String PROPERTIES_FILE_SUFFIX = ".conf";
- private static final String DEFAULT_PROPERTIES_FILE = PROPERTIES_FILE_PREFIX + PROPERTIES_FILE_SUFFIX;
-
private static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L;
private static final int GPS_GEOFENCE_AVAILABLE = 1<<1L;
@@ -462,6 +457,8 @@
if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
xtraDownloadRequest();
}
+ // Always on, notify HAL so it can get data it needs
+ sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
}
};
@@ -474,6 +471,7 @@
new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
+ // Specific to a change to a SUPL enabled network becoming ready
sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
}
@@ -501,10 +499,6 @@
startNavigating(false);
} else if (action.equals(ALARM_TIMEOUT)) {
hibernate();
- } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
- checkSmsSuplInit(intent);
- } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
- checkWapSuplInit(intent);
} else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
|| PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)
|| Intent.ACTION_SCREEN_OFF.equals(action)
@@ -557,31 +551,6 @@
}
}
- private void checkSmsSuplInit(Intent intent) {
- SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
- if (messages == null) {
- Log.e(TAG, "Message does not exist in the intent.");
- return;
- }
-
- for (SmsMessage message : messages) {
- if (message != null && message.mWrappedSmsMessage != null) {
- byte[] suplInit = message.getUserData();
- if (suplInit != null) {
- native_agps_ni_message(suplInit, suplInit.length);
- }
- }
- }
- }
-
- private void checkWapSuplInit(Intent intent) {
- byte[] suplInit = intent.getByteArrayExtra("data");
- if (suplInit == null) {
- return;
- }
- native_agps_ni_message(suplInit,suplInit.length);
- }
-
private void updateLowPowerMode() {
// Disable GPS if we are in device idle mode.
boolean disableGps = mPowerManager.isDeviceIdleMode();
@@ -602,23 +571,14 @@
return native_is_supported();
}
+ interface SetCarrierProperty {
+ public boolean set(int value);
+ }
+
private void reloadGpsProperties(Context context, Properties properties) {
if (DEBUG) Log.d(TAG, "Reset GPS properties, previous size = " + properties.size());
loadPropertiesFromResource(context, properties);
- boolean isPropertiesLoadedFromFile = false;
- final String gpsHardware = SystemProperties.get("ro.hardware.gps");
-
- if (!TextUtils.isEmpty(gpsHardware)) {
- final String propFilename =
- PROPERTIES_FILE_PREFIX + "." + gpsHardware + PROPERTIES_FILE_SUFFIX;
- isPropertiesLoadedFromFile =
- loadPropertiesFromFile(propFilename, properties);
- }
- if (!isPropertiesLoadedFromFile) {
- loadPropertiesFromFile(DEFAULT_PROPERTIES_FILE, properties);
- }
- if (DEBUG) Log.d(TAG, "GPS properties reloaded, size = " + properties.size());
String lpp_prof = SystemProperties.get(LPP_PROFILE);
if (!TextUtils.isEmpty(lpp_prof)) {
// override default value of this if lpp_prof is not empty
@@ -636,16 +596,37 @@
Log.e(TAG, "unable to parse C2K_PORT: " + portString);
}
}
-
+ /*
+ * Allow carrier properties to be loaded from a debug configuration file.
+ */
+ loadPropertiesFromFile(DEBUG_PROPERTIES_FILE, properties);
if (native_is_gnss_configuration_supported()) {
- try {
- // Convert properties to string contents and send it to HAL.
- ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
- properties.store(baos, null);
- native_configuration_update(baos.toString());
- if (DEBUG) Log.d(TAG, "final config = " + baos.toString());
- } catch (IOException ex) {
- Log.e(TAG, "failed to dump properties contents");
+ Map<String, SetCarrierProperty> map = new HashMap<String, SetCarrierProperty>() {
+ {
+ put("SUPL_VER", (val) -> native_set_supl_version(val));
+ put("SUPL_MODE", (val) -> native_set_supl_mode(val));
+ put("SUPL_ES", (val) -> native_set_supl_es(val));
+ put("LPP_PROFILE", (val) -> native_set_lpp_profile(val));
+ put("A_GLONASS_POS_PROTOCOL_SELECT", (val) -> native_set_gnss_pos_protocol_select(val));
+ put("USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL", (val) -> native_set_emergency_supl_pdn(val));
+ put("GPS_LOCK", (val) -> native_set_gps_lock(val));
+ }
+ };
+
+ for(Entry<String, SetCarrierProperty> entry : map.entrySet()) {
+ String propertyName = entry.getKey();
+ String propertyValueString = properties.getProperty(propertyName);
+ if (propertyValueString != null) {
+ try {
+ int propertyValueInt = Integer.decode(propertyValueString);
+ boolean result = entry.getValue().set(propertyValueInt);
+ if (result == false) {
+ Log.e(TAG, "Unable to set " + propertyName);
+ }
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "unable to parse propertyName: " + propertyValueString);
+ }
+ }
}
} else if (DEBUG) {
Log.d(TAG, "Skipped configuration update because GNSS configuration in GPS HAL is not"
@@ -692,7 +673,7 @@
}
} catch (IOException e) {
- Log.w(TAG, "Could not open GPS configuration file " + filename);
+ Log.v(TAG, "Could not open GPS configuration file " + filename);
return false;
}
return true;
@@ -1973,8 +1954,7 @@
String requestorId,
String text,
int requestorIdEncoding,
- int textEncoding,
- String extras // Encoded extra data
+ int textEncoding
)
{
Log.i(TAG, "reportNiNotification: entered");
@@ -2003,28 +1983,6 @@
notification.requestorIdEncoding = requestorIdEncoding;
notification.textEncoding = textEncoding;
- // Process extras, assuming the format is
- // one of more lines of "key = value"
- Bundle bundle = new Bundle();
-
- if (extras == null) extras = "";
- Properties extraProp = new Properties();
-
- try {
- extraProp.load(new StringReader(extras));
- }
- catch (IOException e)
- {
- Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
- }
-
- for (Entry<Object, Object> ent : extraProp.entrySet())
- {
- bundle.putString((String) ent.getKey(), (String) ent.getValue());
- }
-
- notification.extras = bundle;
-
mNIHandler.handleNiNotification(notification);
}
@@ -2075,7 +2033,7 @@
* Called from native code to request reference location info
*/
- private void requestRefLocation(int flags) {
+ private void requestRefLocation() {
TelephonyManager phone = (TelephonyManager)
mContext.getSystemService(Context.TELEPHONY_SERVICE);
final int phoneType = phone.getPhoneType();
@@ -2547,5 +2505,12 @@
private native boolean native_stop_navigation_message_collection();
// GNSS Configuration
- private static native void native_configuration_update(String configData);
+ private static native boolean native_set_supl_version(int version);
+ private static native boolean native_set_supl_mode(int mode);
+ private static native boolean native_set_supl_es(int es);
+ private static native boolean native_set_lpp_profile(int lppProfile);
+ private static native boolean native_set_gnss_pos_protocol_select(int gnssPosProtocolSelect);
+ private static native boolean native_set_gps_lock(int gpsLock);
+ private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn);
+
}
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index 9740935..d8fd6e2 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -74,7 +74,7 @@
try {
List<ActivityManager.RecentTaskInfo> tasks =
ActivityManager.getService().getRecentTasks(1,
- ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS |
+ ActivityManager.RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS |
ActivityManager.RECENT_IGNORE_UNAVAILABLE |
ActivityManager.RECENT_INCLUDE_PROFILES |
ActivityManager.RECENT_WITH_EXCLUDED, record.getUserId()).getList();
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 533307e..ac3a025 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -139,6 +139,7 @@
import android.os.MessageQueue.IdleHandler;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
+import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -197,6 +198,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* Service that maintains low-level network policy rules, using
@@ -565,9 +568,12 @@
}
}
- public void systemReady() {
+ private void initService(CountDownLatch initCompleteSignal) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "systemReady");
+ final int oldPriority = Process.getThreadPriority(Process.myTid());
try {
+ // Boost thread's priority during system server init
+ Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
if (!isBandwidthControlEnabled()) {
Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy");
return;
@@ -672,11 +678,33 @@
mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler);
mUsageStats.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
+ // tell systemReady() that the service has been initialized
+ initCompleteSignal.countDown();
} finally {
+ // Restore the default priority after init is done
+ Process.setThreadPriority(oldPriority);
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
}
}
+ public CountDownLatch networkScoreAndNetworkManagementServiceReady() {
+ final CountDownLatch initCompleteSignal = new CountDownLatch(1);
+ mHandler.post(() -> initService(initCompleteSignal));
+ return initCompleteSignal;
+ }
+
+ public void systemReady(CountDownLatch initCompleteSignal) {
+ // wait for initService to complete
+ try {
+ if (!initCompleteSignal.await(30, TimeUnit.SECONDS)) {
+ throw new IllegalStateException("Service " + TAG +" init timeout");
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException("Service " + TAG + " init interrupted", e);
+ }
+ }
+
final private IUidObserver mUidObserver = new IUidObserver.Stub() {
@Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "onUidStateChanged");
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 8ca6086..386e78b 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -553,15 +553,21 @@
@Override
public NetworkStats getSummaryForAllUid(
NetworkTemplate template, long start, long end, boolean includeTags) {
- @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage);
- final NetworkStats stats =
- getUidComplete().getSummary(template, start, end, accessLevel);
- if (includeTags) {
- final NetworkStats tagStats = getUidTagComplete()
- .getSummary(template, start, end, accessLevel);
- stats.combineAllValues(tagStats);
+ try {
+ @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage);
+ final NetworkStats stats =
+ getUidComplete().getSummary(template, start, end, accessLevel);
+ if (includeTags) {
+ final NetworkStats tagStats = getUidTagComplete()
+ .getSummary(template, start, end, accessLevel);
+ stats.combineAllValues(tagStats);
+ }
+ return stats;
+ } catch (NullPointerException e) {
+ // TODO: Track down and fix the cause of this crash and remove this catch block.
+ Slog.wtf(TAG, "NullPointerException in getSummaryForAllUid", e);
+ throw e;
}
- return stats;
}
@Override
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index c78a0f5..a6fb458 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -110,6 +110,7 @@
import android.service.notification.NotificationAssistantService;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationRankingUpdate;
+import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenModeConfig;
import android.telephony.PhoneStateListener;
@@ -1020,7 +1021,7 @@
synchronized (mNotificationList) {
addAutogroupKeyLocked(key);
}
- mRankingHandler.requestSort();
+ mRankingHandler.requestSort(false);
}
@Override
@@ -1028,7 +1029,7 @@
synchronized (mNotificationList) {
removeAutogroupKeyLocked(key);
}
- mRankingHandler.requestSort();
+ mRankingHandler.requestSort(false);
}
@Override
@@ -1551,9 +1552,6 @@
@Override
public void createNotificationChannel(String pkg, NotificationChannel channel,
IOnNotificationChannelCreatedListener listener) throws RemoteException {
- Preconditions.checkNotNull(channel);
- Preconditions.checkNotNull(channel.getId());
- Preconditions.checkNotNull(channel.getName());
checkCallerIsSystemOrSameApp(pkg);
mRankingHelper.createNotificationChannel(pkg, Binder.getCallingUid(), channel);
savePolicyFile();
@@ -1562,7 +1560,6 @@
@Override
public NotificationChannel getNotificationChannel(String pkg, String channelId) {
- Preconditions.checkNotNull(channelId);
checkCallerIsSystemOrSameApp(pkg);
return mRankingHelper.getNotificationChannel(pkg, Binder.getCallingUid(), channelId);
}
@@ -1570,14 +1567,12 @@
@Override
public NotificationChannel getNotificationChannelForPackage(String pkg, int uid,
String channelId) {
- Preconditions.checkNotNull(channelId);
checkCallerIsSystem();
return mRankingHelper.getNotificationChannel(pkg, uid, channelId);
}
@Override
public void deleteNotificationChannel(String pkg, String channelId) {
- Preconditions.checkNotNull(channelId);
checkCallerIsSystemOrSameApp(pkg);
if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
throw new IllegalArgumentException("Cannot delete default channel");
@@ -1591,8 +1586,6 @@
@Override
public void updateNotificationChannelForPackage(String pkg, int uid,
NotificationChannel channel) {
- Preconditions.checkNotNull(channel);
- Preconditions.checkNotNull(channel.getId());
checkCallerIsSystem();
if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
// cancel
@@ -2382,7 +2375,7 @@
}
@Override
- public void applyAdjustmentFromAssistantService(INotificationListener token,
+ public void applyAdjustmentFromAssistant(INotificationListener token,
Adjustment adjustment) throws RemoteException {
final long identity = Binder.clearCallingIdentity();
try {
@@ -2390,14 +2383,14 @@
mNotificationAssistants.checkServiceTokenLocked(token);
applyAdjustmentLocked(adjustment);
}
- mRankingHandler.requestSort();
+ mRankingHandler.requestSort(true);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
- public void applyAdjustmentsFromAssistantService(INotificationListener token,
+ public void applyAdjustmentsFromAssistant(INotificationListener token,
List<Adjustment> adjustments) throws RemoteException {
final long identity = Binder.clearCallingIdentity();
@@ -2408,11 +2401,57 @@
applyAdjustmentLocked(adjustment);
}
}
- mRankingHandler.requestSort();
+ mRankingHandler.requestSort(true);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
+
+ @Override
+ public void createNotificationChannelFromAssistant(INotificationListener token, String pkg,
+ NotificationChannel channel) throws RemoteException {
+ ManagedServiceInfo info = mNotificationAssistants.checkServiceTokenLocked(token);
+ int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
+ mRankingHelper.createNotificationChannel(pkg, uid, channel);
+ savePolicyFile();
+ }
+
+ @Override
+ public void deleteNotificationChannelFromAssistant(INotificationListener token, String pkg,
+ String channelId) throws RemoteException {
+ ManagedServiceInfo info = mNotificationAssistants.checkServiceTokenLocked(token);
+ if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
+ throw new IllegalArgumentException("Cannot delete default channel");
+ }
+
+ int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
+ cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channelId, 0, 0, true,
+ info.userid, REASON_CHANNEL_BANNED, null);
+ mRankingHelper.deleteNotificationChannel(pkg, uid, channelId);
+ savePolicyFile();
+ }
+
+ @Override
+ public void updateNotificationChannelFromAssistant(INotificationListener token, String pkg,
+ NotificationChannel channel) throws RemoteException {
+ ManagedServiceInfo info = mNotificationAssistants.checkServiceTokenLocked(token);
+ if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
+ // cancel
+ cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channel.getId(), 0, 0, true,
+ info.userid, REASON_CHANNEL_BANNED, null);
+ }
+ int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
+ mRankingHelper.updateNotificationChannelFromAssistant(pkg, uid, channel);
+ savePolicyFile();
+ }
+
+ @Override
+ public ParceledListSlice<NotificationChannel> getNotificationChannelsFromAssistant(
+ INotificationListener token, String pkg) throws RemoteException {
+ ManagedServiceInfo info = mNotificationAssistants.checkServiceTokenLocked(token);
+ int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
+ return mRankingHelper.getNotificationChannels(pkg, uid);
+ }
};
private void applyAdjustmentLocked(Adjustment adjustment) {
@@ -2420,12 +2459,20 @@
if (n == null) {
return;
}
- if (adjustment.getImportance() != IMPORTANCE_NONE) {
- n.setImportance(adjustment.getImportance(), adjustment.getExplanation());
- }
if (adjustment.getSignals() != null) {
Bundle.setDefusable(adjustment.getSignals(), true);
- // TODO: apply signals
+ final String overrideChannelId =
+ adjustment.getSignals().getString(Adjustment.KEY_CHANNEL_ID, null);
+ final ArrayList<String> people =
+ adjustment.getSignals().getStringArrayList(Adjustment.KEY_PEOPLE);
+ final ArrayList<SnoozeCriterion> snoozeCriterionList =
+ adjustment.getSignals().getParcelableArrayList(Adjustment.KEY_SNOOZE_CRITERIA);
+ if (!TextUtils.isEmpty(overrideChannelId)) {
+ n.setNotificationChannelOverride(mRankingHelper.getNotificationChannel(
+ n.sbn.getPackageName(), n.sbn.getUid(), overrideChannelId));
+ }
+ n.setPeopleOverride(people);
+ n.setSnoozeCriteria(snoozeCriterionList);
}
}
@@ -3309,27 +3356,27 @@
}
}
- private void handleRankingSort() {
+ private void handleRankingSort(Message msg) {
+ if (!(msg.obj instanceof Boolean)) return;
+ boolean forceUpdate = ((Boolean) msg.obj == null) ? false : (boolean) msg.obj;
synchronized (mNotificationList) {
final int N = mNotificationList.size();
ArrayList<String> orderBefore = new ArrayList<String>(N);
ArrayList<String> groupOverrideBefore = new ArrayList<>(N);
int[] visibilities = new int[N];
- int[] importances = new int[N];
for (int i = 0; i < N; i++) {
final NotificationRecord r = mNotificationList.get(i);
orderBefore.add(r.getKey());
groupOverrideBefore.add(r.sbn.getGroupKey());
visibilities[i] = r.getPackageVisibilityOverride();
- importances[i] = r.getImportance();
mRankingHelper.extractSignals(r);
}
mRankingHelper.sort(mNotificationList);
for (int i = 0; i < N; i++) {
final NotificationRecord r = mNotificationList.get(i);
- if (!orderBefore.get(i).equals(r.getKey())
+ if (forceUpdate
+ || !orderBefore.get(i).equals(r.getKey())
|| visibilities[i] != r.getPackageVisibilityOverride()
- || importances[i] != r.getImportance()
|| !groupOverrideBefore.get(i).equals(r.sbn.getGroupKey())) {
scheduleSendRankingUpdate();
return;
@@ -3439,14 +3486,17 @@
handleRankingReconsideration(msg);
break;
case MESSAGE_RANKING_SORT:
- handleRankingSort();
+ handleRankingSort(msg);
break;
}
}
- public void requestSort() {
+ public void requestSort(boolean forceUpdate) {
removeMessages(MESSAGE_RANKING_SORT);
- sendEmptyMessage(MESSAGE_RANKING_SORT);
+ Message msg = Message.obtain();
+ msg.what = MESSAGE_RANKING_SORT;
+ msg.obj = forceUpdate;
+ sendMessage(msg);
}
public void requestReconsideration(RankingReconsideration recon) {
@@ -3912,7 +3962,7 @@
}
}
- private static boolean isUidSystem(int uid) {
+ protected static boolean isUidSystem(int uid) {
final int appid = UserHandle.getAppId(uid);
return (appid == Process.SYSTEM_UID || appid == Process.PHONE_UID || uid == 0);
}
@@ -3987,6 +4037,9 @@
Bundle visibilityOverrides = new Bundle();
Bundle suppressedVisualEffects = new Bundle();
Bundle explanation = new Bundle();
+ Bundle overrideChannels = new Bundle();
+ Bundle overridePeople = new Bundle();
+ Bundle snoozeCriteria = new Bundle();
for (int i = 0; i < N; i++) {
NotificationRecord record = mNotificationList.get(i);
if (!isVisibleToListener(record.sbn, info)) {
@@ -4008,6 +4061,9 @@
visibilityOverrides.putInt(key, record.getPackageVisibilityOverride());
}
overrideGroupKeys.putString(key, record.sbn.getOverrideGroupKey());
+ overrideChannels.putParcelable(key, record.getChannel());
+ overridePeople.putStringArrayList(key, record.getPeopleOverride());
+ snoozeCriteria.putParcelableArrayList(key, record.getSnoozeCriteria());
}
final int M = keys.size();
String[] keysAr = keys.toArray(new String[M]);
@@ -4017,7 +4073,8 @@
importanceAr[i] = importance.get(i);
}
return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
- suppressedVisualEffects, importanceAr, explanation, overrideGroupKeys);
+ suppressedVisualEffects, importanceAr, explanation, overrideGroupKeys,
+ overrideChannels, overridePeople, snoozeCriteria);
}
private boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 0213258..a03c4aa 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -36,6 +36,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
+import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.util.Slog;
@@ -45,6 +46,7 @@
import java.io.PrintWriter;
import java.lang.reflect.Array;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
@@ -110,6 +112,9 @@
private Uri mSound;
private long[] mVibration;
private AudioAttributes mAttributes;
+ private NotificationChannel mOverrideChannel;
+ private ArrayList<String> mPeopleOverride;
+ private ArrayList<SnoozeCriterion> mSnoozeCriteria;
@VisibleForTesting
public NotificationRecord(Context context, StatusBarNotification sbn)
@@ -131,6 +136,12 @@
private boolean isPreChannelsNotification() {
try {
if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(getChannel().getId())) {
+ final boolean isSystemNotification =
+ NotificationManagerService.isUidSystem(sbn.getUid())
+ || ("android".equals(sbn.getPackageName()));
+ if (isSystemNotification) {
+ return false;
+ }
final ApplicationInfo applicationInfo =
mContext.getPackageManager().getApplicationInfoAsUser(sbn.getPackageName(),
0, sbn.getUserId());
@@ -626,7 +637,14 @@
}
public NotificationChannel getChannel() {
- return sbn.getNotificationChannel();
+ return mOverrideChannel == null ? sbn.getNotificationChannel() : mOverrideChannel;
+ }
+
+ protected void setNotificationChannelOverride(NotificationChannel channel) {
+ mOverrideChannel = channel;
+ if (mOverrideChannel != null) {
+ calculateImportance();
+ }
}
public Uri getSound() {
@@ -640,4 +658,20 @@
public AudioAttributes getAudioAttributes() {
return mAttributes;
}
+
+ public ArrayList<String> getPeopleOverride() {
+ return mPeopleOverride;
+ }
+
+ protected void setPeopleOverride(ArrayList<String> people) {
+ mPeopleOverride = people;
+ }
+
+ public ArrayList<SnoozeCriterion> getSnoozeCriteria() {
+ return mSnoozeCriteria;
+ }
+
+ protected void setSnoozeCriteria(ArrayList<SnoozeCriterion> snoozeCriteria) {
+ mSnoozeCriteria = snoozeCriteria;
+ }
}
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index cb5fb0d..882e84c 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -34,7 +34,7 @@
void createNotificationChannel(String pkg, int uid, NotificationChannel channel);
void updateNotificationChannel(String pkg, int uid, NotificationChannel channel);
- void updateNotificationChannelFromRanker(String pkg, int uid, NotificationChannel channel);
+ void updateNotificationChannelFromAssistant(String pkg, int uid, NotificationChannel channel);
NotificationChannel getNotificationChannel(String pkg, int uid, String channelId);
NotificationChannel getNotificationChannelWithFallback(String pkg, int uid, String channelId);
void deleteNotificationChannel(String pkg, int uid, String channelId);
diff --git a/services/core/java/com/android/server/notification/RankingHandler.java b/services/core/java/com/android/server/notification/RankingHandler.java
index 80bb4f0..656d727 100644
--- a/services/core/java/com/android/server/notification/RankingHandler.java
+++ b/services/core/java/com/android/server/notification/RankingHandler.java
@@ -16,6 +16,6 @@
package com.android.server.notification;
public interface RankingHandler {
- public void requestSort();
+ public void requestSort(boolean forceUpdate);
public void requestReconsideration(RankingReconsideration recon);
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index a41231d..89101a8 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -18,6 +18,7 @@
import static android.app.NotificationManager.IMPORTANCE_NONE;
import com.android.internal.R;
+import com.android.internal.util.Preconditions;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -328,7 +329,7 @@
for (int i = 0; i < N; i++) {
mSignalExtractors[i].setConfig(this);
}
- mRankingHandler.requestSort();
+ mRankingHandler.requestSort(false);
}
public void sort(ArrayList<NotificationRecord> notificationList) {
@@ -451,7 +452,14 @@
@Override
public void createNotificationChannel(String pkg, int uid, NotificationChannel channel) {
+ Preconditions.checkNotNull(pkg);
+ Preconditions.checkNotNull(channel);
+ Preconditions.checkNotNull(channel.getId());
+ Preconditions.checkNotNull(channel.getName());
Record r = getOrCreateRecord(pkg, uid);
+ if (r == null) {
+ throw new IllegalArgumentException("Invalid package");
+ }
if (IMPORTANCE_NONE == r.importance) {
throw new IllegalArgumentException("Package blocked");
}
@@ -472,7 +480,12 @@
@Override
public void updateNotificationChannel(String pkg, int uid, NotificationChannel updatedChannel) {
+ Preconditions.checkNotNull(updatedChannel);
+ Preconditions.checkNotNull(updatedChannel.getId());
Record r = getOrCreateRecord(pkg, uid);
+ if (r == null) {
+ throw new IllegalArgumentException("Invalid package");
+ }
NotificationChannel channel = r.channels.get(updatedChannel.getId());
if (channel == null) {
throw new IllegalArgumentException("Channel does not exist");
@@ -485,9 +498,12 @@
}
@Override
- public void updateNotificationChannelFromRanker(String pkg, int uid,
+ public void updateNotificationChannelFromAssistant(String pkg, int uid,
NotificationChannel updatedChannel) {
Record r = getOrCreateRecord(pkg, uid);
+ if (r == null) {
+ throw new IllegalArgumentException("Invalid package");
+ }
NotificationChannel channel = r.channels.get(updatedChannel.getId());
if (channel == null) {
throw new IllegalArgumentException("Channel does not exist");
@@ -538,7 +554,11 @@
@Override
public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId) {
+ Preconditions.checkNotNull(pkg);
Record r = getOrCreateRecord(pkg, uid);
+ if (r == null) {
+ throw new IllegalArgumentException("Invalid package");
+ }
if (channelId == null) {
channelId = NotificationChannel.DEFAULT_CHANNEL_ID;
}
@@ -547,7 +567,12 @@
@Override
public void deleteNotificationChannel(String pkg, int uid, String channelId) {
+ Preconditions.checkNotNull(pkg);
+ Preconditions.checkNotNull(channelId);
Record r = getRecord(pkg, uid);
+ if (r == null) {
+ throw new IllegalArgumentException("Invalid package");
+ }
if (r != null) {
r.channels.remove(channelId);
}
@@ -555,8 +580,12 @@
@Override
public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid) {
+ Preconditions.checkNotNull(pkg);
List<NotificationChannel> channels = new ArrayList<>();
- Record r = getOrCreateRecord(pkg, uid);
+ Record r = getRecord(pkg, uid);
+ if (r == null) {
+ throw new IllegalArgumentException("Invalid package");
+ }
int N = r.channels.size();
for (int i = 0; i < N; i++) {
channels.add(r.channels.valueAt(i));
diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
index c9e1315..5dd651f 100644
--- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
+++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
@@ -31,13 +31,17 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import android.util.LruCache;
import android.util.Slog;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -157,7 +161,8 @@
if (context == null) {
return NONE;
}
- final PeopleRankingReconsideration prr = validatePeople(context, key, extras, affinityOut);
+ final PeopleRankingReconsideration prr =
+ validatePeople(context, key, extras, null, affinityOut);
float affinity = affinityOut[0];
if (prr != null) {
@@ -207,7 +212,8 @@
final String key = record.getKey();
final Bundle extras = record.getNotification().extras;
final float[] affinityOut = new float[1];
- final PeopleRankingReconsideration rr = validatePeople(context, key, extras, affinityOut);
+ final PeopleRankingReconsideration rr =
+ validatePeople(context, key, extras, record.getPeopleOverride(), affinityOut);
final float affinity = affinityOut[0];
record.setContactAffinity(affinity);
if (rr == null) {
@@ -220,22 +226,22 @@
}
private PeopleRankingReconsideration validatePeople(Context context, String key, Bundle extras,
- float[] affinityOut) {
+ List<String> peopleOverride, float[] affinityOut) {
long start = SystemClock.elapsedRealtime();
float affinity = NONE;
if (extras == null) {
return null;
}
-
- final String[] people = getExtraPeople(extras);
- if (people == null || people.length == 0) {
- return null;
+ final Set<String> people = new ArraySet<>(peopleOverride);
+ final String[] notificationPeople = getExtraPeople(extras);
+ if (notificationPeople != null ) {
+ people.addAll(Arrays.asList(getExtraPeople(extras)));
}
if (VERBOSE) Slog.i(TAG, "Validating: " + key + " for " + context.getUserId());
final LinkedList<String> pendingLookups = new LinkedList<String>();
- for (int personIdx = 0; personIdx < people.length && personIdx < MAX_PEOPLE; personIdx++) {
- final String handle = people[personIdx];
+ int personIdx = 0;
+ for (String handle : people) {
if (TextUtils.isEmpty(handle)) continue;
synchronized (mPeopleCache) {
@@ -250,6 +256,9 @@
affinity = Math.max(affinity, lookupResult.getAffinity());
}
}
+ if (++personIdx == MAX_PEOPLE) {
+ break;
+ }
}
// record the best available data, so far:
diff --git a/services/core/java/com/android/server/pm/EphemeralResolver.java b/services/core/java/com/android/server/pm/EphemeralResolver.java
index 3ce5007..d735e72 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolver.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolver.java
@@ -227,8 +227,9 @@
ephemeralResolver.addFilter(intentInfo);
}
}
- List<EphemeralResponse> matchedResolveInfoList = ephemeralResolver
- .queryIntent(intent, resolvedType, false /*defaultOnly*/, userId);
+ List<EphemeralResponse> matchedResolveInfoList = ephemeralResolver.queryIntent(
+ intent, resolvedType, false /*defaultOnly*/, false /*visibleToEphemeral*/,
+ false /*isEphemeral*/, userId);
if (!matchedResolveInfoList.isEmpty()) {
return matchedResolveInfoList.get(0);
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 2e18b1c..3193974 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -20,17 +20,15 @@
import android.content.Context;
import android.content.pm.PackageStats;
import android.os.Build;
+import android.os.IInstalld;
+import android.os.ServiceManager;
import android.util.Slog;
-import com.android.internal.os.InstallerConnection;
-import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.server.SystemService;
import dalvik.system.VMRuntime;
-import java.util.Arrays;
-
-public final class Installer extends SystemService {
+public class Installer extends SystemService {
private static final String TAG = "Installer";
/* ***************************************************************************
@@ -47,25 +45,29 @@
public static final int DEXOPT_BOOTCOMPLETE = 1 << 4;
/** Hint that the dexopt type is profile-guided. */
public static final int DEXOPT_PROFILE_GUIDED = 1 << 5;
- /** This is an OTA update dexopt */
- public static final int DEXOPT_OTA = 1 << 6;
// NOTE: keep in sync with installd
public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9;
- private final InstallerConnection mInstaller;
+ private final boolean mIsolated;
+
+ // TODO: reconnect if installd restarts
+ private volatile IInstalld mInstalld;
+ private volatile Object mWarnIfHeld;
public Installer(Context context) {
- super(context);
- mInstaller = new InstallerConnection();
+ this(context, false);
}
- // Package-private installer that accepts a custom InstallerConnection. Used for
- // OtaDexoptService.
- Installer(Context context, InstallerConnection connection) {
+ /**
+ * @param isolated indicates if this object should <em>not</em> connect to
+ * the real {@code installd}. All remote calls will be ignored
+ * unless you extend this class and intercept them.
+ */
+ public Installer(Context context, boolean isolated) {
super(context);
- mInstaller = connection;
+ mIsolated = isolated;
}
/**
@@ -73,136 +75,239 @@
* the given object.
*/
public void setWarnIfHeld(Object warnIfHeld) {
- mInstaller.setWarnIfHeld(warnIfHeld);
+ mWarnIfHeld = warnIfHeld;
}
@Override
public void onStart() {
- Slog.i(TAG, "Waiting for installd to be ready.");
- mInstaller.waitForConnection();
+ if (mIsolated) {
+ mInstalld = null;
+ } else {
+ mInstalld = IInstalld.Stub.asInterface(ServiceManager.getService("installd"));
+ }
}
- public void createAppData(String uuid, String pkgname, int userid, int flags, int appid,
- String seinfo, int targetSdkVersion) throws InstallerException {
- mInstaller.execute("create_app_data", uuid, pkgname, userid, flags, appid, seinfo,
- targetSdkVersion);
+ /**
+ * Do several pre-flight checks before making a remote call.
+ *
+ * @return if the remote call should continue.
+ */
+ private boolean checkBeforeRemote() {
+ if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
+ Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
+ + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
+ }
+ if (mIsolated) {
+ Slog.i(TAG, "Ignoring request because this installer is isolated");
+ return false;
+ } else {
+ return true;
+ }
}
- public void restoreconAppData(String uuid, String pkgname, int userid, int flags, int appid,
- String seinfo) throws InstallerException {
- mInstaller.execute("restorecon_app_data", uuid, pkgname, userid, flags, appid,
- seinfo);
+ public void createAppData(String uuid, String packageName, int userId, int flags, int appId,
+ String seInfo, int targetSdkVersion) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo,
+ targetSdkVersion);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
- public void migrateAppData(String uuid, String pkgname, int userid, int flags)
+ public void restoreconAppData(String uuid, String packageName, int userId, int flags, int appId,
+ String seInfo) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.restoreconAppData(uuid, packageName, userId, flags, appId, seInfo);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
+ public void migrateAppData(String uuid, String packageName, int userId, int flags)
throws InstallerException {
- mInstaller.execute("migrate_app_data", uuid, pkgname, userid, flags);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.migrateAppData(uuid, packageName, userId, flags);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
- public void clearAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode)
+ public void clearAppData(String uuid, String packageName, int userId, int flags,
+ long ceDataInode) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.clearAppData(uuid, packageName, userId, flags, ceDataInode);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
+ public void destroyAppData(String uuid, String packageName, int userId, int flags,
+ long ceDataInode) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.destroyAppData(uuid, packageName, userId, flags, ceDataInode);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
+ public void moveCompleteApp(String fromUuid, String toUuid, String packageName,
+ String dataAppName, int appId, String seInfo, int targetSdkVersion)
throws InstallerException {
- mInstaller.execute("clear_app_data", uuid, pkgname, userid, flags, ceDataInode);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.moveCompleteApp(fromUuid, toUuid, packageName, dataAppName, appId, seInfo,
+ targetSdkVersion);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
- public void destroyAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode)
- throws InstallerException {
- mInstaller.execute("destroy_app_data", uuid, pkgname, userid, flags, ceDataInode);
- }
-
- public void moveCompleteApp(String from_uuid, String to_uuid, String package_name,
- String data_app_name, int appid, String seinfo, int targetSdkVersion)
- throws InstallerException {
- mInstaller.execute("move_complete_app", from_uuid, to_uuid, package_name,
- data_app_name, appid, seinfo, targetSdkVersion);
- }
-
- public void getAppSize(String uuid, String pkgname, int userid, int flags, long ceDataInode,
+ public void getAppSize(String uuid, String packageName, int userId, int flags, long ceDataInode,
String codePath, PackageStats stats) throws InstallerException {
- final String[] res = mInstaller.execute("get_app_size", uuid, pkgname, userid, flags,
- ceDataInode, codePath);
+ if (!checkBeforeRemote()) return;
try {
- stats.codeSize += Long.parseLong(res[1]);
- stats.dataSize += Long.parseLong(res[2]);
- stats.cacheSize += Long.parseLong(res[3]);
- } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
- throw new InstallerException("Invalid size result: " + Arrays.toString(res));
+ final long[] res = mInstalld.getAppSize(uuid, packageName, userId, flags, ceDataInode,
+ codePath);
+ stats.codeSize += res[0];
+ stats.dataSize += res[1];
+ stats.cacheSize += res[2];
+ } catch (Exception e) {
+ throw InstallerException.from(e);
}
}
- public long getAppDataInode(String uuid, String pkgname, int userid, int flags)
+ public long getAppDataInode(String uuid, String packageName, int userId, int flags)
throws InstallerException {
- final String[] res = mInstaller.execute("get_app_data_inode", uuid, pkgname, userid, flags);
+ if (!checkBeforeRemote()) return -1;
try {
- return Long.parseLong(res[1]);
- } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
- throw new InstallerException("Invalid inode result: " + Arrays.toString(res));
+ return mInstalld.getAppDataInode(uuid, packageName, userId, flags);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
}
}
- public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
- int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries)
- throws InstallerException {
- assertValidInstructionSet(instructionSet);
- mInstaller.dexopt(apkPath, uid, instructionSet, dexoptNeeded, dexFlags,
- compilerFilter, volumeUuid, sharedLibraries);
- }
-
- public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
+ public void dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet,
int dexoptNeeded, @Nullable String outputPath, int dexFlags,
- String compilerFilter, String volumeUuid, String sharedLibraries)
+ String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries)
throws InstallerException {
assertValidInstructionSet(instructionSet);
- mInstaller.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded,
- outputPath, dexFlags, compilerFilter, volumeUuid, sharedLibraries);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath,
+ dexFlags, compilerFilter, volumeUuid, sharedLibraries);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
- public boolean mergeProfiles(int uid, String pkgName) throws InstallerException {
- return mInstaller.mergeProfiles(uid, pkgName);
+ public boolean mergeProfiles(int uid, String packageName) throws InstallerException {
+ if (!checkBeforeRemote()) return false;
+ try {
+ return mInstalld.mergeProfiles(uid, packageName);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
- public boolean dumpProfiles(String gid, String packageName, String codePaths)
+ public boolean dumpProfiles(int uid, String packageName, String codePaths)
throws InstallerException {
- return mInstaller.dumpProfiles(gid, packageName, codePaths);
+ if (!checkBeforeRemote()) return false;
+ try {
+ return mInstalld.dumpProfiles(uid, packageName, codePaths);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
public void idmap(String targetApkPath, String overlayApkPath, int uid)
throws InstallerException {
- mInstaller.execute("idmap", targetApkPath, overlayApkPath, uid);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.idmap(targetApkPath, overlayApkPath, uid);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
public void rmdex(String codePath, String instructionSet) throws InstallerException {
assertValidInstructionSet(instructionSet);
- mInstaller.execute("rmdex", codePath, instructionSet);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.rmdex(codePath, instructionSet);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
public void rmPackageDir(String packageDir) throws InstallerException {
- mInstaller.execute("rmpackagedir", packageDir);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.rmPackageDir(packageDir);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
- public void clearAppProfiles(String pkgName) throws InstallerException {
- mInstaller.execute("clear_app_profiles", pkgName);
+ public void clearAppProfiles(String packageName) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.clearAppProfiles(packageName);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
- public void destroyAppProfiles(String pkgName) throws InstallerException {
- mInstaller.execute("destroy_app_profiles", pkgName);
+ public void destroyAppProfiles(String packageName) throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.destroyAppProfiles(packageName);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
public void createUserData(String uuid, int userId, int userSerial, int flags)
throws InstallerException {
- mInstaller.execute("create_user_data", uuid, userId, userSerial, flags);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.createUserData(uuid, userId, userSerial, flags);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
public void destroyUserData(String uuid, int userId, int flags) throws InstallerException {
- mInstaller.execute("destroy_user_data", uuid, userId, flags);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.destroyUserData(uuid, userId, flags);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
public void markBootComplete(String instructionSet) throws InstallerException {
assertValidInstructionSet(instructionSet);
- mInstaller.execute("markbootcomplete", instructionSet);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.markBootComplete(instructionSet);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
public void freeCache(String uuid, long freeStorageSize) throws InstallerException {
- mInstaller.execute("freecache", uuid, freeStorageSize);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.freeCache(uuid, freeStorageSize);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
/**
@@ -210,29 +315,54 @@
* directory to the real location for backward compatibility. Note that no
* such symlink is created for 64 bit shared libraries.
*/
- public void linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32,
+ public void linkNativeLibraryDirectory(String uuid, String packageName, String nativeLibPath32,
int userId) throws InstallerException {
- mInstaller.execute("linklib", uuid, dataPath, nativeLibPath32, userId);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.linkNativeLibraryDirectory(uuid, packageName, nativeLibPath32, userId);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
public void createOatDir(String oatDir, String dexInstructionSet)
throws InstallerException {
- mInstaller.execute("createoatdir", oatDir, dexInstructionSet);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.createOatDir(oatDir, dexInstructionSet);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
public void linkFile(String relativePath, String fromBase, String toBase)
throws InstallerException {
- mInstaller.execute("linkfile", relativePath, fromBase, toBase);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.linkFile(relativePath, fromBase, toBase);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
public void moveAb(String apkPath, String instructionSet, String outputPath)
throws InstallerException {
- mInstaller.execute("move_ab", apkPath, instructionSet, outputPath);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.moveAb(apkPath, instructionSet, outputPath);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
public void deleteOdex(String apkPath, String instructionSet, String outputPath)
throws InstallerException {
- mInstaller.execute("delete_odex", apkPath, instructionSet, outputPath);
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.deleteOdex(apkPath, instructionSet, outputPath);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
}
private static void assertValidInstructionSet(String instructionSet)
@@ -244,4 +374,14 @@
}
throw new InstallerException("Invalid instruction set: " + instructionSet);
}
+
+ public static class InstallerException extends Exception {
+ public InstallerException(String detailMessage) {
+ super(detailMessage);
+ }
+
+ public static InstallerException from(Exception e) throws InstallerException {
+ throw new InstallerException(e.toString());
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index f777aae..bbd227e 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -16,11 +16,11 @@
package com.android.server.pm;
-import static com.android.server.pm.Installer.DEXOPT_OTA;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.IOtaDexopt;
import android.content.pm.PackageParser;
@@ -30,15 +30,17 @@
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.storage.StorageManager;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
+
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.os.InstallerConnection;
-import com.android.internal.os.InstallerConnection.InstallerException;
+import com.android.server.pm.Installer.InstallerException;
import java.io.File;
import java.io.FileDescriptor;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -277,9 +279,27 @@
*/
private synchronized List<String> generatePackageDexopts(PackageParser.Package pkg,
int compilationReason) {
- // Use our custom connection that just collects the commands.
- RecordingInstallerConnection collectingConnection = new RecordingInstallerConnection();
- Installer collectingInstaller = new Installer(mContext, collectingConnection);
+ // Intercept and collect dexopt requests
+ final List<String> commands = new ArrayList<String>();
+ final Installer collectingInstaller = new Installer(mContext, true) {
+ @Override
+ public void dexopt(String apkPath, int uid, @Nullable String pkgName,
+ String instructionSet, int dexoptNeeded, @Nullable String outputPath,
+ int dexFlags, String compilerFilter, @Nullable String volumeUuid,
+ @Nullable String sharedLibraries) throws InstallerException {
+ commands.add(buildCommand("dexopt",
+ apkPath,
+ uid,
+ pkgName,
+ instructionSet,
+ dexoptNeeded,
+ outputPath,
+ dexFlags,
+ compilerFilter,
+ volumeUuid,
+ sharedLibraries));
+ }
+ };
// Use the package manager install and install lock here for the OTA dex optimizer.
PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer(
@@ -296,7 +316,7 @@
getCompilerFilterForReason(compilationReason),
null /* CompilerStats.PackageStats */);
- return collectingConnection.commands;
+ return commands;
}
@Override
@@ -401,53 +421,33 @@
private static class OTADexoptPackageDexOptimizer extends
PackageDexOptimizer.ForcedUpdatePackageDexOptimizer {
-
public OTADexoptPackageDexOptimizer(Installer installer, Object installLock,
Context context) {
super(installer, installLock, context, "*otadexopt*");
}
-
- @Override
- protected int adjustDexoptFlags(int dexoptFlags) {
- // Add the OTA flag.
- return dexoptFlags | DEXOPT_OTA;
- }
-
}
- private static class RecordingInstallerConnection extends InstallerConnection {
- public List<String> commands = new ArrayList<String>(1);
-
- @Override
- public void setWarnIfHeld(Object warnIfHeld) {
- throw new IllegalStateException("Should not reach here");
+ /**
+ * Cook up argument list in the format that {@code installd} expects.
+ */
+ private static String buildCommand(Object... args) {
+ final StringBuilder builder = new StringBuilder();
+ for (Object arg : args) {
+ String escaped;
+ if (arg == null) {
+ escaped = "";
+ } else {
+ escaped = String.valueOf(arg);
+ }
+ if (escaped.indexOf('\0') != -1 || escaped.indexOf(' ') != -1 || "!".equals(escaped)) {
+ throw new IllegalArgumentException(
+ "Invalid argument while executing " + Arrays.toString(args));
+ }
+ if (TextUtils.isEmpty(escaped)) {
+ escaped = "!";
+ }
+ builder.append(' ').append(escaped);
}
-
- @Override
- public synchronized String transact(String cmd) {
- commands.add(cmd);
- return "0";
- }
-
- @Override
- public boolean mergeProfiles(int uid, String pkgName) throws InstallerException {
- throw new IllegalStateException("Should not reach here");
- }
-
- @Override
- public boolean dumpProfiles(String gid, String packageName, String codePaths)
- throws InstallerException {
- throw new IllegalStateException("Should not reach here");
- }
-
- @Override
- public void disconnect() {
- throw new IllegalStateException("Should not reach here");
- }
-
- @Override
- public void waitForConnection() {
- throw new IllegalStateException("Should not reach here");
- }
+ return builder.toString();
}
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index acdcc72..2e0199b 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -27,8 +27,8 @@
import android.util.Log;
import android.util.Slog;
-import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.pm.Installer.InstallerException;
import java.io.File;
import java.io.IOException;
@@ -251,7 +251,7 @@
Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg="
+ pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
+ " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
- + " target-filter=" + targetCompilerFilter + " oatDir = " + oatDir
+ + " target-filter=" + targetCompilerFilter + " oatDir=" + oatDir
+ " sharedLibraries=" + sharedLibrariesPath);
// Profile guide compiled oat files should not be public.
final boolean isPublic = !pkg.isForwardLocked() && !isProfileGuidedFilter;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 2ece99f..c85e1d8 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -72,10 +72,10 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
-import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
+import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter;
import java.io.File;
diff --git a/services/core/java/com/android/server/pm/PackageManagerException.java b/services/core/java/com/android/server/pm/PackageManagerException.java
index f243e63..0e3f173 100644
--- a/services/core/java/com/android/server/pm/PackageManagerException.java
+++ b/services/core/java/com/android/server/pm/PackageManagerException.java
@@ -19,7 +19,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageParser.PackageParserException;
-import com.android.internal.os.InstallerConnection.InstallerException;
+import com.android.server.pm.Installer.InstallerException;
/** {@hide} */
public class PackageManagerException extends Exception {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index dc25ce4..f7cccc8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -237,7 +237,6 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.IParcelFileDescriptorFactory;
-import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.os.RoSystemProperties;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
@@ -257,6 +256,7 @@
import com.android.server.SystemConfig;
import com.android.server.Watchdog;
import com.android.server.net.NetworkPolicyManagerInternal;
+import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.PermissionsState.PermissionState;
import com.android.server.pm.Settings.DatabaseVersion;
import com.android.server.pm.Settings.VersionInfo;
@@ -558,7 +558,8 @@
Manifest.permission.RECEIVE_WAP_PUSH,
Manifest.permission.RECEIVE_MMS,
Manifest.permission.READ_EXTERNAL_STORAGE,
- Manifest.permission.WRITE_EXTERNAL_STORAGE);
+ Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ Manifest.permission.READ_PHONE_NUMBER);
final ServiceThread mHandlerThread;
@@ -2228,6 +2229,18 @@
mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ // Clean up orphaned packages for which the code path doesn't exist
+ // and they are an update to a system app - caused by bug/32321269
+ final int packageSettingCount = mSettings.mPackages.size();
+ for (int i = packageSettingCount - 1; i >= 0; i--) {
+ PackageSetting ps = mSettings.mPackages.valueAt(i);
+ if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
+ && mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
+ mSettings.mPackages.removeAt(i);
+ mSettings.enableSystemPackageLPw(ps.name);
+ }
+ }
+
if (mFirstBoot) {
requestCopyPreoptedFiles();
}
@@ -2286,8 +2299,9 @@
getCompilerFilterForReason(REASON_SHARED_APK),
false /* newProfile */);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
- dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
+ mInstaller.dexopt(lib, Process.SYSTEM_UID, "*",
+ dexCodeInstructionSet, dexoptNeeded, null,
+ DEXOPT_PUBLIC,
getCompilerFilterForReason(REASON_SHARED_APK),
StorageManager.UUID_PRIVATE_INTERNAL,
SKIP_SHARED_LIBRARY_CHECK);
@@ -3208,8 +3222,12 @@
flags = updateFlagsForPackage(flags, userId, packageName);
enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /* requireFullPermission */, false /* checkShell */, "get package info");
+
// reader
synchronized (mPackages) {
+ // Normalize package name to hanlde renamed packages
+ packageName = normalizePackageNameLPr(packageName);
+
final boolean matchFactoryOnly = (flags & MATCH_FACTORY_ONLY) != 0;
PackageParser.Package p = null;
if (matchFactoryOnly) {
@@ -3412,8 +3430,12 @@
flags = updateFlagsForApplication(flags, userId, packageName);
enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /* requireFullPermission */, false /* checkShell */, "get application info");
+
// writer
synchronized (mPackages) {
+ // Normalize package name to hanlde renamed packages
+ packageName = normalizePackageNameLPr(packageName);
+
PackageParser.Package p = mPackages.get(packageName);
if (DEBUG_PACKAGE_INFO) Log.v(
TAG, "getApplicationInfo " + packageName
@@ -3435,6 +3457,11 @@
return null;
}
+ private String normalizePackageNameLPr(String packageName) {
+ String normalizedPackageName = mSettings.getRenamedPackageLPr(packageName);
+ return normalizedPackageName != null ? normalizedPackageName : packageName;
+ }
+
@Override
public void freeStorageAndNotify(final String volumeUuid, final long freeStorageSize,
final IPackageDataObserver observer) {
@@ -3614,6 +3641,11 @@
if (mSafeMode) {
flags |= PackageManager.MATCH_SYSTEM_ONLY;
}
+ final String ephemeralPkgName = getEphemeralPackageName(Binder.getCallingUid());
+ if (ephemeralPkgName != null) {
+ flags |= PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY;
+ flags |= PackageManager.MATCH_EPHEMERAL;
+ }
return updateFlagsForComponent(flags, userId, cookie);
}
@@ -5187,7 +5219,9 @@
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for presistent preferred activities...");
List<PersistentPreferredActivity> pprefs = ppir != null
? ppir.queryIntent(intent, resolvedType,
- (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId)
+ (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
+ (flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
+ (flags & PackageManager.MATCH_EPHEMERAL) != 0, userId)
: null;
if (pprefs != null && pprefs.size() > 0) {
final int M = pprefs.size();
@@ -5262,7 +5296,9 @@
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for preferred activities...");
List<PreferredActivity> prefs = pir != null
? pir.queryIntent(intent, resolvedType,
- (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId)
+ (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
+ (flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
+ (flags & PackageManager.MATCH_EPHEMERAL) != 0, userId)
: null;
if (prefs != null && prefs.size() > 0) {
boolean changed = false;
@@ -5433,7 +5469,8 @@
String resolvedType, int userId) {
CrossProfileIntentResolver resolver = mSettings.mCrossProfileIntentResolvers.get(userId);
if (resolver != null) {
- return resolver.queryIntent(intent, resolvedType, false, userId);
+ return resolver.queryIntent(intent, resolvedType, false /*defaultOnly*/,
+ false /*visibleToEphemeral*/, false /*isEphemeral*/, userId);
}
return null;
}
@@ -5451,9 +5488,26 @@
}
}
+ /**
+ * Returns the package name of the calling Uid if it's an ephemeral app. If it isn't
+ * ephemeral, returns {@code null}.
+ */
+ private String getEphemeralPackageName(int callingUid) {
+ final int appId = UserHandle.getAppId(callingUid);
+ synchronized (mPackages) {
+ final Object obj = mSettings.getUserIdLPr(appId);
+ if (obj instanceof PackageSetting) {
+ final PackageSetting ps = (PackageSetting) obj;
+ return ps.pkg.applicationInfo.isEphemeralApp() ? ps.pkg.packageName : null;
+ }
+ }
+ return null;
+ }
+
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
+ final String ephemeralPkgName = getEphemeralPackageName(Binder.getCallingUid());
flags = updateFlagsForResolve(flags, userId, intent);
enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /* requireFullPermission */, false /* checkShell */,
@@ -5480,7 +5534,6 @@
// reader
boolean sortResult = false;
boolean addEphemeral = false;
- boolean matchEphemeralPackage = false;
List<ResolveInfo> result;
final String pkgName = intent.getPackage();
synchronized (mPackages) {
@@ -5493,7 +5546,8 @@
if (xpResolveInfo != null) {
List<ResolveInfo> xpResult = new ArrayList<ResolveInfo>(1);
xpResult.add(xpResolveInfo);
- return filterIfNotSystemUser(xpResult, userId);
+ return filterForEphemeral(
+ filterIfNotSystemUser(xpResult, userId), ephemeralPkgName);
}
// Check for results in the current profile.
@@ -5533,13 +5587,13 @@
// And we are not going to add emphemeral app, so we can return the
// result straight away.
result.add(xpDomainInfo.resolveInfo);
- return result;
+ return filterForEphemeral(result, ephemeralPkgName);
}
} else if (result.size() <= 1 && !addEphemeral) {
// No result in parent user and <= 1 result in current profile, and we
// are not going to add emphemeral app, so we can return the result without
// further processing.
- return result;
+ return filterForEphemeral(result, ephemeralPkgName);
}
// We have more than one candidate (combining results from current and parent
// profile), so we need filtering and sorting.
@@ -5559,7 +5613,6 @@
// were no installed results, so, try to find an ephemeral result
addEphemeral = isEphemeralAllowed(
intent, null /*result*/, userId, true /*skipPackageCheck*/);
- matchEphemeralPackage = true;
result = new ArrayList<ResolveInfo>();
}
}
@@ -5592,7 +5645,7 @@
if (sortResult) {
Collections.sort(result, mResolvePrioritySorter);
}
- return result;
+ return filterForEphemeral(result, ephemeralPkgName);
}
private static class CrossProfileDomainInfo {
@@ -5691,6 +5744,38 @@
}
/**
+ * Filters out ephemeral activities.
+ * <p>When resolving for an ephemeral app, only activities that 1) are defined in the
+ * ephemeral app or 2) marked with {@code visibleToEphemeral} are returned.
+ *
+ * @param resolveInfos The pre-filtered list of resolved activities
+ * @param ephemeralPkgName The ephemeral package name. If {@code null}, no filtering
+ * is performed.
+ * @return A filtered list of resolved activities.
+ */
+ private List<ResolveInfo> filterForEphemeral(List<ResolveInfo> resolveInfos,
+ String ephemeralPkgName) {
+ if (ephemeralPkgName == null) {
+ return resolveInfos;
+ }
+ for (int i = resolveInfos.size() - 1; i >= 0; i--) {
+ ResolveInfo info = resolveInfos.get(i);
+ final boolean isEphemeralApp = info.activityInfo.applicationInfo.isEphemeralApp();
+ // allow activities that are defined in the provided package
+ if (isEphemeralApp && ephemeralPkgName.equals(info.activityInfo.packageName)) {
+ continue;
+ }
+ // allow activities that have been explicitly exposed to ephemeral apps
+ if (!isEphemeralApp
+ && ((info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0)) {
+ continue;
+ }
+ resolveInfos.remove(i);
+ }
+ return resolveInfos;
+ }
+
+ /**
* @param resolveInfos list of resolve infos in descending priority order
* @return if the list contains a resolve info with non-negative priority
*/
@@ -7732,9 +7817,8 @@
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
try {
List<String> allCodePaths = pkg.getAllCodePathsExcludingResourceOnly();
- String gid = Integer.toString(sharedGid);
String codePaths = TextUtils.join(";", allCodePaths);
- mInstaller.dumpProfiles(gid, packageName, codePaths);
+ mInstaller.dumpProfiles(sharedGid, packageName, codePaths);
} catch (InstallerException e) {
Slog.w(TAG, "Failed to dump profiles", e);
}
@@ -9086,6 +9170,13 @@
PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
final String curPackageName = cur == null ? null : cur.info.packageName;
+ // Dont allow ephemeral apps to define new permission groups.
+ if (pkg.applicationInfo.isEphemeralApp()) {
+ Slog.w(TAG, "Permission group " + pg.info.name + " from package "
+ + pg.info.packageName
+ + " ignored: ephemeral apps cannot define new permission groups.");
+ continue;
+ }
final boolean isPackageUpdate = pg.info.packageName.equals(curPackageName);
if (cur == null || isPackageUpdate) {
mPermissionGroups.put(pg.info.name, pg);
@@ -9124,6 +9215,14 @@
for (i=0; i<N; i++) {
PackageParser.Permission p = pkg.permissions.get(i);
+ // Dont allow ephemeral apps to define new permissions.
+ if (pkg.applicationInfo.isEphemeralApp()) {
+ Slog.w(TAG, "Permission " + p.info.name + " from package "
+ + p.info.packageName
+ + " ignored: ephemeral apps cannot define new permissions.");
+ continue;
+ }
+
// Assume by default that we did not install this permission into the system.
p.info.flags &= ~PermissionInfo.FLAG_INSTALLED;
@@ -10701,10 +10800,13 @@
final class ActivityIntentResolver
extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
- boolean defaultOnly, int userId) {
+ boolean defaultOnly, boolean visibleToEphemeral, boolean isEphemeral, int userId) {
if (!sUserManager.exists(userId)) return null;
- mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
- return super.queryIntent(intent, resolvedType, defaultOnly, userId);
+ mFlags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0)
+ | (visibleToEphemeral ? PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY : 0)
+ | (isEphemeral ? PackageManager.MATCH_EPHEMERAL : 0);
+ return super.queryIntent(intent, resolvedType, defaultOnly, visibleToEphemeral,
+ isEphemeral, userId);
}
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
@@ -10712,7 +10814,9 @@
if (!sUserManager.exists(userId)) return null;
mFlags = flags;
return super.queryIntent(intent, resolvedType,
- (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
+ (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
+ (flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
+ (flags & PackageManager.MATCH_EPHEMERAL) != 0, userId);
}
public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
@@ -10722,7 +10826,10 @@
return null;
}
mFlags = flags;
- final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
+ final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+ final boolean vislbleToEphemeral =
+ (flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0;
+ final boolean isEphemeral = (flags & PackageManager.MATCH_EPHEMERAL) != 0;
final int N = packageActivities.size();
ArrayList<PackageParser.ActivityIntentInfo[]> listCut =
new ArrayList<PackageParser.ActivityIntentInfo[]>(N);
@@ -10737,7 +10844,8 @@
listCut.add(array);
}
}
- return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
+ return super.queryIntentFromList(intent, resolvedType, defaultOnly,
+ vislbleToEphemeral, isEphemeral, listCut, userId);
}
/**
@@ -11222,9 +11330,10 @@
private final class ServiceIntentResolver
extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
- boolean defaultOnly, int userId) {
+ boolean defaultOnly, boolean visibleToEphemeral, boolean isEphemeral, int userId) {
mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
- return super.queryIntent(intent, resolvedType, defaultOnly, userId);
+ return super.queryIntent(intent, resolvedType, defaultOnly, visibleToEphemeral,
+ isEphemeral, userId);
}
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
@@ -11232,7 +11341,9 @@
if (!sUserManager.exists(userId)) return null;
mFlags = flags;
return super.queryIntent(intent, resolvedType,
- (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
+ (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
+ (flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
+ (flags & PackageManager.MATCH_EPHEMERAL) != 0, userId);
}
public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
@@ -11243,6 +11354,9 @@
}
mFlags = flags;
final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
+ final boolean vislbleToEphemeral =
+ (flags&PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0;
+ final boolean isEphemeral = (flags&PackageManager.MATCH_EPHEMERAL) != 0;
final int N = packageServices.size();
ArrayList<PackageParser.ServiceIntentInfo[]> listCut =
new ArrayList<PackageParser.ServiceIntentInfo[]>(N);
@@ -11257,7 +11371,8 @@
listCut.add(array);
}
}
- return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
+ return super.queryIntentFromList(intent, resolvedType, defaultOnly,
+ vislbleToEphemeral, isEphemeral, listCut, userId);
}
public final void addService(PackageParser.Service s) {
@@ -11427,14 +11542,15 @@
private final ArrayMap<ComponentName, PackageParser.Service> mServices
= new ArrayMap<ComponentName, PackageParser.Service>();
private int mFlags;
- };
+ }
private final class ProviderIntentResolver
extends IntentResolver<PackageParser.ProviderIntentInfo, ResolveInfo> {
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
- boolean defaultOnly, int userId) {
+ boolean defaultOnly, boolean visibleToEphemeral, boolean isEphemeral, int userId) {
mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
- return super.queryIntent(intent, resolvedType, defaultOnly, userId);
+ return super.queryIntent(intent, resolvedType, defaultOnly, visibleToEphemeral,
+ isEphemeral, userId);
}
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
@@ -11443,7 +11559,9 @@
return null;
mFlags = flags;
return super.queryIntent(intent, resolvedType,
- (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
+ (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
+ (flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
+ (flags & PackageManager.MATCH_EPHEMERAL) != 0, userId);
}
public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
@@ -11455,6 +11573,9 @@
}
mFlags = flags;
final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+ final boolean isEphemeral = (flags&PackageManager.MATCH_EPHEMERAL) != 0;
+ final boolean vislbleToEphemeral =
+ (flags&PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0;
final int N = packageProviders.size();
ArrayList<PackageParser.ProviderIntentInfo[]> listCut =
new ArrayList<PackageParser.ProviderIntentInfo[]>(N);
@@ -11469,7 +11590,8 @@
listCut.add(array);
}
}
- return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
+ return super.queryIntentFromList(intent, resolvedType, defaultOnly,
+ vislbleToEphemeral, isEphemeral, listCut, userId);
}
public final void addProvider(PackageParser.Provider p) {
@@ -20089,6 +20211,9 @@
private void assertPackageKnown(String volumeUuid, String packageName)
throws PackageManagerException {
synchronized (mPackages) {
+ // Normalize package name to handle renamed packages
+ packageName = normalizePackageNameLPr(packageName);
+
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps == null) {
throw new PackageManagerException("Package " + packageName + " is unknown");
@@ -20103,6 +20228,9 @@
private void assertPackageKnownAndInstalled(String volumeUuid, String packageName, int userId)
throws PackageManagerException {
synchronized (mPackages) {
+ // Normalize package name to handle renamed packages
+ packageName = normalizePackageNameLPr(packageName);
+
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps == null) {
throw new PackageManagerException("Package " + packageName + " is unknown");
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index fd2b504..2751742 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -51,9 +51,11 @@
import android.os.SystemProperties;
import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.PrintWriterPrinter;
import com.android.internal.content.PackageHelper;
import com.android.internal.util.SizedInputStream;
+import com.android.server.SystemConfig;
import dalvik.system.DexFile;
@@ -135,6 +137,8 @@
return runSuspend(false);
case "set-home-activity":
return runSetHomeActivity();
+ case "get-privapp-permissions":
+ return runGetPrivappPermissions();
default:
return handleDefaultCommands(cmd);
}
@@ -1105,7 +1109,7 @@
sessionParams.abiOverride = checkAbiArgument(getNextArg());
break;
case "--ephemeral":
- sessionParams.installFlags |= PackageManager.INSTALL_EPHEMERAL;
+ sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
break;
case "--user":
params.userId = UserHandle.parseUserArg(getNextArgRequired());
@@ -1164,6 +1168,18 @@
}
}
+ private int runGetPrivappPermissions() {
+ final String pkg = getNextArg();
+ if (pkg == null) {
+ System.err.println("Error: no package specified.");
+ return 1;
+ }
+ ArraySet<String> privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
+ getOutPrintWriter().println(privAppPermissions == null
+ ? "{}" : privAppPermissions.toString());
+ return 0;
+ }
+
private static String checkAbiArgument(String abi) {
if (TextUtils.isEmpty(abi)) {
throw new IllegalArgumentException("Missing ABI argument");
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index e330585..7187fc2 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -80,13 +80,13 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
-import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.XmlUtils;
import com.android.server.backup.PreferredActivityBackupHelper;
+import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.PackageManagerService.DumpState;
import com.android.server.pm.PermissionsState.PermissionState;
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index d558b07..2eb0778 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -259,6 +259,11 @@
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
+ if (si.isFloating()) {
+ si.setRank(0);
+ si.setActivity(null);
+ }
+
if (si.isAlive()) continue;
if (removeList == null) {
@@ -288,6 +293,7 @@
si.setTimestamp(now);
si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
si.setRank(0); // It may still be pinned, so clear the rank.
+ si.setActivity(null);
}
}
if (changed) {
@@ -355,6 +361,7 @@
if (oldShortcut.isPinned()) {
oldShortcut.setRank(0);
+ oldShortcut.setActivity(null);
oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
if (disable) {
oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
@@ -595,6 +602,10 @@
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
+
+ if (si.isFloating()) {
+ continue; // Ignore floating shortcuts, which are not tied to any activities.
+ }
final ComponentName activity = si.getActivity();
if (checked.contains(activity)) {
@@ -1356,6 +1367,10 @@
case TAG_SHORTCUT:
final ShortcutInfo si = parseShortcut(parser, packageName,
shortcutUser.getUserId());
+ // Floating shortcut used to have target activities, but not anymore.
+ if (si.isFloating()) { // Not really needed by just in case.
+ si.setActivity(null);
+ }
// Don't use addShortcut(), we don't need to save the icon.
ret.mShortcuts.put(si.getId(), si);
@@ -1462,7 +1477,6 @@
intents.clear();
intents.add(intentLegacy);
}
-
return new ShortcutInfo(
userId, id, packageName, activityComponent, /* icon =*/ null,
title, titleResId, titleResName, text, textResId, textResName,
@@ -1553,12 +1567,17 @@
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " is both dynamic and manifest at the same time.");
}
- if (si.getActivity() == null) {
+ if (!si.isFloating() && si.getActivity() == null) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
- + " has null activity.");
+ + " is not floating, but has null activity.");
}
- if ((si.isDynamic() || si.isManifestShortcut()) && !si.isEnabled()) {
+ if (si.isFloating() && si.getActivity() != null) {
+ failed = true;
+ Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ + " is floating, but has non-null activity.");
+ }
+ if (!si.isFloating() && !si.isEnabled()) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " is not floating, but is disabled.");
@@ -1581,7 +1600,7 @@
}
if (failed) {
- throw new IllegalStateException("See logcat for errors");
+ mShortcutUser.mService.verifyError();
}
}
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
index 4de15de..e5a2f5a 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
@@ -23,7 +23,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.backup.BackupUtils;
-import libcore.io.Base64;
import libcore.util.HexEncoding;
import org.xmlpull.v1.XmlPullParser;
@@ -33,6 +32,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Base64;
/**
* Package information used by {@link android.content.pm.ShortcutManager} for backup / restore.
@@ -161,7 +161,8 @@
for (int i = 0; i < mSigHashes.size(); i++) {
out.startTag(null, TAG_SIGNATURE);
- ShortcutService.writeAttr(out, ATTR_SIGNATURE_HASH, Base64.encode(mSigHashes.get(i)));
+ final String encoded = Base64.getEncoder().encodeToString(mSigHashes.get(i));
+ ShortcutService.writeAttr(out, ATTR_SIGNATURE_HASH, encoded);
out.endTag(null, TAG_SIGNATURE);
}
out.endTag(null, TAG_ROOT);
@@ -196,7 +197,9 @@
case TAG_SIGNATURE: {
final String hash = ShortcutService.parseStringAttribute(
parser, ATTR_SIGNATURE_HASH);
- hashes.add(Base64.decode(hash.getBytes()));
+ // Throws IllegalArgumentException if hash is invalid base64 data
+ final byte[] decoded = Base64.getDecoder().decode(hash);
+ hashes.add(decoded);
continue;
}
}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 16f209b..c5c1c0c 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -124,6 +124,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -401,6 +402,9 @@
@VisibleForTesting
ShortcutService(Context context, Looper looper, boolean onlyForPackageManagerApis) {
+ if (DEBUG) {
+ Binder.LOG_RUNTIME_EXCEPTION = true;
+ }
mContext = Preconditions.checkNotNull(context);
LocalServices.addService(ShortcutServiceInternal.class, new LocalService());
mHandler = new Handler(looper);
@@ -1604,7 +1608,7 @@
}
if (!forUpdate) {
- shortcut.enforceMandatoryFields();
+ shortcut.enforceMandatoryFields(/* forPinned= */ false);
Preconditions.checkArgument(
injectIsMainActivity(shortcut.getActivity(), shortcut.getUserId()),
"Cannot publish shortcut: " + shortcut.getActivity() + " is not main activity");
@@ -1752,6 +1756,9 @@
// Note copyNonNullFieldsFrom() does the "updatable with?" check too.
target.copyNonNullFieldsFrom(source);
+ if (target.isFloating()) {
+ target.setActivity(null);
+ }
target.setTimestamp(injectCurrentTimeMillis());
if (replacingIcon) {
@@ -2320,8 +2327,7 @@
return false;
}
if (componentName != null) {
- if (si.getActivity() != null
- && !si.getActivity().equals(componentName)) {
+ if (!Objects.equals(componentName, si.getActivity())) {
return false;
}
}
@@ -3771,4 +3777,8 @@
forEachLoadedUserLocked(u -> u.forAllPackageItems(ShortcutPackageItem::verifyStates));
}
}
+
+ void verifyError() {
+ Slog.e(TAG, "See logcat for errors");
+ }
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index c4241e7..05228ec 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -913,17 +913,36 @@
@Override
public boolean isUserUnlockingOrUnlocked(int userId) {
- int callingUserId = UserHandle.getCallingUserId();
- if (callingUserId != userId && !hasManageUsersPermission()) {
- if (!isSameProfileGroupNoChecks(callingUserId, userId)) {
- throw new SecurityException(
- "You need MANAGE_USERS permission to: check isUserUnlockingOrUnlocked");
- }
- }
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isUserUnlockingOrUnlocked");
return mLocalService.isUserUnlockingOrUnlocked(userId);
}
@Override
+ public boolean isUserUnlocked(int userId) {
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isUserUnlocked");
+ return mLocalService.isUserUnlockingOrUnlocked(userId);
+ }
+
+ @Override
+ public boolean isUserRunning(int userId) {
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isUserRunning");
+ return mLocalService.isUserRunning(userId);
+ }
+
+ private void checkManageOrInteractPermIfCallerInOtherProfileGroup(int userId, String name) {
+ int callingUserId = UserHandle.getCallingUserId();
+ if (callingUserId == userId || isSameProfileGroupNoChecks(callingUserId, userId) ||
+ hasManageUsersPermission()) {
+ return;
+ }
+ if (ActivityManager.checkComponentPermission(Manifest.permission.INTERACT_ACROSS_USERS,
+ Binder.getCallingUid(), -1, true) != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("You need INTERACT_ACROSS_USERS or MANAGE_USERS permission "
+ + "to: check " + name);
+ }
+ }
+
+ @Override
public boolean isDemoUser(int userId) {
int callingUserId = UserHandle.getCallingUserId();
if (callingUserId != userId && !hasManageUsersPermission()) {
@@ -2250,8 +2269,11 @@
private UserInfo createUserInternal(String name, int flags, int parentId,
String[] disallowedPackages) {
- if (hasUserRestriction(UserManager.DISALLOW_ADD_USER, UserHandle.getCallingUserId())) {
- Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled.");
+ String restriction = ((flags & UserInfo.FLAG_MANAGED_PROFILE) != 0)
+ ? UserManager.DISALLOW_ADD_MANAGED_PROFILE
+ : UserManager.DISALLOW_ADD_USER;
+ if (hasUserRestriction(restriction, UserHandle.getCallingUserId())) {
+ Log.w(LOG_TAG, "Cannot add user. " + restriction + " is enabled.");
return null;
}
return createUserInternalUnchecked(name, flags, parentId, disallowedPackages);
@@ -2522,9 +2544,16 @@
public boolean removeUser(int userHandle) {
Slog.i(LOG_TAG, "removeUser u" + userHandle);
checkManageOrCreateUsersPermission("Only the system can remove users");
- if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
- UserManager.DISALLOW_REMOVE_USER, false)) {
- Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled.");
+
+ final boolean isManagedProfile;
+ synchronized (mUsersLock) {
+ UserInfo userInfo = getUserInfoLU(userHandle);
+ isManagedProfile = userInfo != null && userInfo.isManagedProfile();
+ }
+ String restriction = isManagedProfile
+ ? UserManager.DISALLOW_REMOVE_MANAGED_PROFILE : UserManager.DISALLOW_REMOVE_USER;
+ if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(restriction, false)) {
+ Log.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled.");
return false;
}
return removeUserUnchecked(userHandle);
@@ -3641,6 +3670,14 @@
|| (state == UserState.STATE_RUNNING_UNLOCKED);
}
}
+
+ @Override
+ public boolean isUserUnlocked(int userId) {
+ synchronized (mUserStates) {
+ int state = mUserStates.get(userId, -1);
+ return state == UserState.STATE_RUNNING_UNLOCKED;
+ }
+ }
}
/* Remove all the users except of the system one. */
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 9fe0922..e91cce1 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -71,15 +71,18 @@
UserManager.DISALLOW_SHARE_LOCATION,
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
UserManager.DISALLOW_CONFIG_BLUETOOTH,
+ UserManager.DISALLOW_BLUETOOTH,
UserManager.DISALLOW_USB_FILE_TRANSFER,
UserManager.DISALLOW_CONFIG_CREDENTIALS,
UserManager.DISALLOW_REMOVE_USER,
+ UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
UserManager.DISALLOW_DEBUGGING_FEATURES,
UserManager.DISALLOW_CONFIG_VPN,
UserManager.DISALLOW_CONFIG_TETHERING,
UserManager.DISALLOW_NETWORK_RESET,
UserManager.DISALLOW_FACTORY_RESET,
UserManager.DISALLOW_ADD_USER,
+ UserManager.DISALLOW_ADD_MANAGED_PROFILE,
UserManager.ENSURE_VERIFY_APPS,
UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
@@ -117,11 +120,14 @@
* User restrictions that can not be set by profile owners.
*/
private static final Set<String> DEVICE_OWNER_ONLY_RESTRICTIONS = Sets.newArraySet(
+ UserManager.DISALLOW_BLUETOOTH,
UserManager.DISALLOW_USB_FILE_TRANSFER,
UserManager.DISALLOW_CONFIG_TETHERING,
UserManager.DISALLOW_NETWORK_RESET,
UserManager.DISALLOW_FACTORY_RESET,
UserManager.DISALLOW_ADD_USER,
+ UserManager.DISALLOW_ADD_MANAGED_PROFILE,
+ UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
@@ -153,6 +159,13 @@
);
/**
+ * User restrictions that default to {@code true} for device owners.
+ */
+ private static final Set<String> DEFAULT_ENABLED_FOR_DEVICE_OWNERS = Sets.newArraySet(
+ UserManager.DISALLOW_ADD_MANAGED_PROFILE
+ );
+
+ /**
* Throws {@link IllegalArgumentException} if the given restriction name is invalid.
*/
public static boolean isValidRestriction(@NonNull String restriction) {
@@ -247,6 +260,13 @@
}
/**
+ * Returns the user restrictions that default to {@code true} for device owners.
+ */
+ public static @NonNull Set<String> getDefaultEnabledForDeviceOwner() {
+ return DEFAULT_ENABLED_FOR_DEVICE_OWNERS;
+ }
+
+ /**
* Takes restrictions that can be set by device owner, and sort them into what should be applied
* globally and what should be applied only on the current user.
*/
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index a1cce2b..b058f95 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -229,6 +229,7 @@
import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.AppTransition;
+import com.android.server.vr.VrManagerInternal;
import java.io.File;
import java.io.FileReader;
@@ -265,7 +266,6 @@
static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
static final int SHORT_PRESS_POWER_GO_HOME = 4;
- static final int SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME = 5;
static final int LONG_PRESS_POWER_NOTHING = 0;
static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
@@ -1346,14 +1346,6 @@
case SHORT_PRESS_POWER_GO_HOME:
launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
break;
- case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME:
- if (mWindowManagerFuncs.isInputMethodWindowVisible()) {
- mWindowManagerFuncs.hideCurrentInputMethod();
- } else {
- launchHomeFromHotKey(true /* awakenFromDreams */,
- false /*respectKeyguard*/);
- }
- break;
}
}
}
@@ -6464,6 +6456,7 @@
mKeyguardDelegate.onScreenTurnedOff();
}
}
+ reportScreenStateToVrManager(false);
}
// Called on the DisplayManager's DisplayPowerController thread.
@@ -6499,6 +6492,15 @@
mKeyguardDelegate.onScreenTurnedOn();
}
}
+ reportScreenStateToVrManager(true);
+ }
+
+ private void reportScreenStateToVrManager(boolean isScreenOn) {
+ VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
+ if (vrService == null) {
+ return;
+ }
+ vrService.onScreenStateChanged(isScreenOn);
}
private void finishWindowsDrawn() {
@@ -7609,6 +7611,32 @@
return vis;
}
+ private int updateLightNavigationBarLw(int vis, WindowState opaque,
+ WindowState opaqueOrDimming) {
+ final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
+
+ final WindowState navColorWin;
+ if (imeWin != null && imeWin.isVisibleLw()) {
+ navColorWin = imeWin;
+ } else {
+ navColorWin = opaqueOrDimming;
+ }
+
+ if (navColorWin != null) {
+ if (navColorWin == opaque) {
+ // If the top fullscreen-or-dimming window is also the top fullscreen, respect
+ // its light flag.
+ vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+ vis |= PolicyControl.getSystemUiVisibility(navColorWin, null)
+ & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+ } else if (navColorWin.isDimming() || navColorWin == imeWin) {
+ // Otherwise if it's dimming or it's the IME window, clear the light flag.
+ vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+ }
+ }
+ return vis;
+ }
+
private boolean drawsSystemBarBackground(WindowState win) {
return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
}
@@ -7739,6 +7767,9 @@
vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
+ vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState,
+ mTopFullscreenOpaqueOrDimmingWindowState);
+
return vis;
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 1790554..f2ccac5 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -134,6 +134,8 @@
private static final int DIRTY_DOCK_STATE = 1 << 10;
// Dirty bit: brightness boost changed
private static final int DIRTY_SCREEN_BRIGHTNESS_BOOST = 1 << 11;
+ // Dirty bit: sQuiescent changed
+ private static final int DIRTY_QUIESCENT = 1 << 12;
// Summarizes the state of all active wakelocks.
private static final int WAKE_LOCK_CPU = 1 << 0;
@@ -169,6 +171,9 @@
// Default setting for double tap to wake.
private static final int DEFAULT_DOUBLE_TAP_TO_WAKE = 0;
+ // System property indicating that the screen should remain off until an explicit user action
+ private static final String SYSTEM_PROPERTY_QUIESCENT = "ro.boot.quiescent";
+
/** Constants for {@link #shutdownOrRebootInternal} */
@Retention(RetentionPolicy.SOURCE)
@IntDef({HALT_MODE_SHUTDOWN, HALT_MODE_REBOOT, HALT_MODE_REBOOT_SAFE_MODE})
@@ -398,6 +403,9 @@
// True if the device should stay on.
private boolean mStayOn;
+ // True if the lights should stay off until an explicit user action.
+ private static boolean sQuiescent;
+
// True if the proximity sensor reads a positive result.
private boolean mProximityPositive;
@@ -530,6 +538,8 @@
mWakefulness = WAKEFULNESS_AWAKE;
+ sQuiescent = SystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1");
+
nativeInit();
nativeSetAutoSuspend(false);
nativeSetInteractive(true);
@@ -1190,12 +1200,19 @@
&& eventTime > mLastUserActivityTime) {
mLastUserActivityTimeNoChangeLights = eventTime;
mDirty |= DIRTY_USER_ACTIVITY;
+ if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
+ mDirty |= DIRTY_QUIESCENT;
+ }
+
return true;
}
} else {
if (eventTime > mLastUserActivityTime) {
mLastUserActivityTime = eventTime;
mDirty |= DIRTY_USER_ACTIVITY;
+ if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
+ mDirty |= DIRTY_QUIESCENT;
+ }
return true;
}
}
@@ -2096,7 +2113,7 @@
final boolean oldDisplayReady = mDisplayReady;
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
- | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST)) != 0) {
+ | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_QUIESCENT)) != 0) {
mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
// Determine appropriate screen brightness and auto-brightness adjustments.
@@ -2163,6 +2180,9 @@
mRequestWaitForNegativeProximity);
mRequestWaitForNegativeProximity = false;
+ if ((dirty & DIRTY_QUIESCENT) != 0) {
+ sQuiescent = false;
+ }
if (DEBUG_SPEW) {
Slog.d(TAG, "updateDisplayPowerStateLocked: mDisplayReady=" + mDisplayReady
+ ", policy=" + mDisplayPowerRequest.policy
@@ -2170,8 +2190,8 @@
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", mBootCompleted=" + mBootCompleted
- + ", mScreenBrightnessBoostInProgress="
- + mScreenBrightnessBoostInProgress);
+ + ", mScreenBrightnessBoostInProgress=" + mScreenBrightnessBoostInProgress
+ + ", sQuiescent=" + sQuiescent);
}
}
return mDisplayReady && !oldDisplayReady;
@@ -2210,7 +2230,7 @@
}
private int getDesiredScreenPolicyLocked() {
- if (mWakefulness == WAKEFULNESS_ASLEEP) {
+ if (mWakefulness == WAKEFULNESS_ASLEEP || sQuiescent) {
return DisplayPowerRequest.POLICY_OFF;
}
@@ -2899,10 +2919,25 @@
}
if (reason.equals(PowerManager.REBOOT_RECOVERY)
|| reason.equals(PowerManager.REBOOT_RECOVERY_UPDATE)) {
- SystemProperties.set("sys.powerctl", "reboot,recovery");
- } else {
- SystemProperties.set("sys.powerctl", "reboot," + reason);
+ reason = "recovery";
}
+
+ // If the reason is "quiescent", it means that the boot process should proceed
+ // without turning on the screen/lights.
+ // The "quiescent" property is sticky, meaning that any number
+ // of subsequent reboots should honor the property until it is reset.
+ if (reason.equals(PowerManager.REBOOT_QUIESCENT)) {
+ sQuiescent = true;
+ reason = "";
+ }
+
+ if (sQuiescent) {
+ // Pass the optional "quiescent" argument to the bootloader to let it know
+ // that it should not turn the screen/lights on.
+ reason = reason + ",quiescent";
+ }
+
+ SystemProperties.set("sys.powerctl", "reboot," + reason);
try {
Thread.sleep(20 * 1000L);
} catch (InterruptedException e) {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 9d02940..cca8cc8 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -169,7 +169,7 @@
CharSequence label;
Drawable icon;
ComponentName component; // service that implements ITrustAgent
- ComponentName settings; // setting to launch to modify agent.
+ SettingsAttrs settings; // setting to launch to modify agent.
TrustAgentWrapper agent;
int userId;
@@ -258,11 +258,6 @@
+ ": switchToByUser=false");
continue;
}
- if (!StorageManager.isUserKeyUnlocked(userInfo.id)) {
- if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
- + ": FDE still locked");
- continue;
- }
if (!mActivityManager.isUserRunning(userInfo.id)) {
if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
+ ": user not started");
@@ -273,13 +268,7 @@
+ ": no secure credential");
continue;
}
- if (!mStrongAuthTracker.canAgentsRunForUser(userInfo.id)) {
- if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
- + ": prevented by StrongAuthTracker = 0x"
- + Integer.toHexString(mStrongAuthTracker.getStrongAuthForUser(
- userInfo.id)));
- continue;
- }
+
DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
final boolean disableTrustAgents =
@@ -312,16 +301,49 @@
continue;
}
}
-
AgentInfo agentInfo = new AgentInfo();
agentInfo.component = name;
agentInfo.userId = userInfo.id;
if (!mActiveAgents.contains(agentInfo)) {
agentInfo.label = resolveInfo.loadLabel(pm);
agentInfo.icon = resolveInfo.loadIcon(pm);
- agentInfo.settings = getSettingsComponentName(pm, resolveInfo);
+ agentInfo.settings = getSettingsAttrs(pm, resolveInfo);
agentInfo.agent = new TrustAgentWrapper(mContext, this,
new Intent().setComponent(name), userInfo.getUserHandle());
+ } else {
+ int index = mActiveAgents.indexOf(agentInfo);
+ agentInfo = mActiveAgents.valueAt(index);
+ }
+
+ boolean directUnlock = resolveInfo.serviceInfo.directBootAware
+ && agentInfo.settings.canUnlockProfile;
+
+ if (directUnlock) {
+ if (DEBUG) Slog.d(TAG, "refreshAgentList: trustagent " + name
+ + "of user " + userInfo.id + "can unlock user profile.");
+ }
+
+ if (!StorageManager.isUserKeyUnlocked(userInfo.id)
+ && !directUnlock) {
+ if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
+ + "'s trust agent " + name + ": FDE still locked and "
+ + " the agent cannot unlock user profile.");
+ continue;
+ }
+
+ if (!mStrongAuthTracker.canAgentsRunForUser(userInfo.id)) {
+ int flag = mStrongAuthTracker.getStrongAuthForUser(userInfo.id);
+ if (flag != StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
+ || !directUnlock) {
+ if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
+ + ": prevented by StrongAuthTracker = 0x"
+ + Integer.toHexString(mStrongAuthTracker.getStrongAuthForUser(
+ userInfo.id)));
+ continue;
+ }
+ }
+
+ if (!mActiveAgents.contains(agentInfo)) {
mActiveAgents.add(agentInfo);
} else {
obsoleteAgents.remove(agentInfo);
@@ -468,10 +490,12 @@
refreshAgentList(userId);
}
- private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
+ private SettingsAttrs getSettingsAttrs(PackageManager pm, ResolveInfo resolveInfo) {
if (resolveInfo == null || resolveInfo.serviceInfo == null
|| resolveInfo.serviceInfo.metaData == null) return null;
String cn = null;
+ boolean canUnlockProfile = false;
+
XmlResourceParser parser = null;
Exception caughtException = null;
try {
@@ -496,6 +520,8 @@
TypedArray sa = res
.obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
+ canUnlockProfile = sa.getBoolean(
+ com.android.internal.R.styleable.TrustAgent_unlockProfile, false);
sa.recycle();
} catch (PackageManager.NameNotFoundException e) {
caughtException = e;
@@ -516,7 +542,7 @@
if (cn.indexOf('/') < 0) {
cn = resolveInfo.serviceInfo.packageName + "/" + cn;
}
- return ComponentName.unflattenFromString(cn);
+ return new SettingsAttrs(ComponentName.unflattenFromString(cn), canUnlockProfile);
}
private ComponentName getComponentName(ResolveInfo resolveInfo) {
@@ -554,6 +580,7 @@
private List<ResolveInfo> resolveAllowedTrustAgents(PackageManager pm, int userId) {
List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
+ PackageManager.GET_META_DATA |
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
userId);
ArrayList<ResolveInfo> allowedAgents = new ArrayList<>(resolveInfos.size());
@@ -991,6 +1018,18 @@
}
};
+ private static class SettingsAttrs {
+ public ComponentName componentName;
+ public boolean canUnlockProfile;
+
+ public SettingsAttrs(
+ ComponentName componentName,
+ boolean canUnlockProfile) {
+ this.componentName = componentName;
+ this.canUnlockProfile = canUnlockProfile;
+ }
+ };
+
private class Receiver extends BroadcastReceiver {
@Override
diff --git a/services/core/java/com/android/server/twilight/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java
index db7df25..bb4d67e 100644
--- a/services/core/java/com/android/server/twilight/TwilightService.java
+++ b/services/core/java/com/android/server/twilight/TwilightService.java
@@ -59,17 +59,17 @@
private final Handler mHandler;
- private AlarmManager mAlarmManager;
+ protected AlarmManager mAlarmManager;
private LocationManager mLocationManager;
private boolean mBootCompleted;
private boolean mHasListeners;
private BroadcastReceiver mTimeChangedReceiver;
- private Location mLastLocation;
+ protected Location mLastLocation;
@GuardedBy("mListeners")
- private TwilightState mLastTwilightState;
+ protected TwilightState mLastTwilightState;
public TwilightService(Context context) {
super(context);
@@ -247,7 +247,11 @@
@Override
public void onLocationChanged(Location location) {
- if (location != null) {
+ // Location providers may erroneously return (0.0, 0.0) when they fail to determine the
+ // device's location. These location updates can be safely ignored since the chance of a
+ // user actually being at these coordinates is quite low.
+ if (location != null
+ && !(location.getLongitude() == 0.0 && location.getLatitude() == 0.0)) {
Slog.d(TAG, "onLocationChanged:"
+ " provider=" + location.getProvider()
+ " accuracy=" + location.getAccuracy()
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index ad87a88..0fc1900 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -56,25 +56,27 @@
int userId, @NonNull ComponentName calling);
/**
- * Set the current VR mode state immediately.
+ * Set whether the system has acquired a sleep token.
*
- * @param enabled {@code true} to enable VR mode.
- * @param packageName The package name of the requested VrListenerService to bind.
- * @param userId the user requesting the VrListenerService component.
- * @param calling the component currently using VR mode, or null to leave unchanged.
+ * @param isAsleep is {@code true} if the device is asleep, or {@code false} otherwise.
*/
- public abstract void setVrModeImmediate(boolean enabled, @NonNull ComponentName packageName,
- int userId, @NonNull ComponentName calling);
+ public abstract void onSleepStateChanged(boolean isAsleep);
+ /**
+ * Set whether the display used for VR output is on.
+ *
+ * @param isScreenOn is {@code true} if the display is on and can receive commands,
+ * or {@code false} otherwise.
+ */
+ public abstract void onScreenStateChanged(boolean isScreenOn);
- /**
- * Return NO_ERROR if the given package is installed on the device and enabled as a
- * VrListenerService for the given current user, or a negative error code indicating a failure.
- *
- * @param packageName the name of the package to check, or null to select the default package.
- * @return NO_ERROR if the given package is installed and is enabled, or a negative error code
- * given in {@link android.service.vr.VrModeException} on failure.
- */
+ /**
+ * Return NO_ERROR if the given package is installed on the device and enabled as a
+ * VrListenerService for the given current user, or a negative error code indicating a failure.
+ *
+ * @param packageName the name of the package to check, or null to select the default package.
+ * @return NO_ERROR if the given package is installed and is enabled, or a negative error code
+ * given in {@link android.service.vr.VrModeException} on failure.
+ */
public abstract int hasVrPackage(@NonNull ComponentName packageName, int userId);
-
}
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index fdadc8d..1083e0a 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -101,6 +101,14 @@
private static final int PENDING_STATE_DELAY_MS = 300;
private static final int EVENT_LOG_SIZE = 32;
private static final int INVALID_APPOPS_MODE = -1;
+ /** Null set of sleep sleep flags. */
+ private static final int FLAG_NONE = 0;
+ /** Flag set when the device is not sleeping. */
+ private static final int FLAG_AWAKE = 1;
+ /** Flag set when the screen has been turned on. */
+ private static final int FLAG_SCREEN_ON = 2;
+ /** Flag indicating that all system sleep flags have been set.*/
+ private static final int FLAG_ALL = FLAG_AWAKE | FLAG_SCREEN_ON;
private static native void initializeNative();
private static native void setVrModeNative(boolean enabled);
@@ -110,6 +118,7 @@
private final IBinder mOverlayToken = new Binder();
// State protected by mLock
+ private boolean mVrModeAllowed;
private boolean mVrModeEnabled;
private EnabledComponentsObserver mComponentObserver;
private ManagedApplicationService mCurrentVrService;
@@ -125,10 +134,64 @@
private VrState mPendingState;
private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
+ /** Tracks the state of the screen and keyguard UI.*/
+ private int mSystemSleepFlags = FLAG_NONE;
private static final int MSG_VR_STATE_CHANGE = 0;
private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
+ /**
+ * Set whether VR mode may be enabled.
+ * <p/>
+ * If VR mode is not allowed to be enabled, calls to set VR mode will be cached. When VR mode
+ * is again allowed to be enabled, the most recent cached state will be applied.
+ *
+ * @param allowed {@code true} if calling any of the setVrMode methods may cause the device to
+ * enter VR mode.
+ */
+ private void setVrModeAllowedLocked(boolean allowed) {
+ if (mVrModeAllowed != allowed) {
+ mVrModeAllowed = allowed;
+ Slog.i(TAG, "VR mode is " + ((allowed) ? "allowed" : "disallowed"));
+ if (mVrModeAllowed) {
+ consumeAndApplyPendingStateLocked();
+ } else {
+ // Set pending state to current state.
+ mPendingState = (mVrModeEnabled && mCurrentVrService != null)
+ ? new VrState(mVrModeEnabled, mCurrentVrService.getComponent(),
+ mCurrentVrService.getUserId(), mCurrentVrModeComponent)
+ : null;
+
+ // Unbind current VR service and do necessary callbacks.
+ updateCurrentVrServiceLocked(false, null, 0, null);
+ }
+ }
+ }
+
+ private void setSleepState(boolean isAsleep) {
+ synchronized(mLock) {
+
+ if (!isAsleep) {
+ mSystemSleepFlags |= FLAG_AWAKE;
+ } else {
+ mSystemSleepFlags &= ~FLAG_AWAKE;
+ }
+
+ setVrModeAllowedLocked(mSystemSleepFlags == FLAG_ALL);
+ }
+ }
+
+ private void setScreenOn(boolean isScreenOn) {
+ synchronized(mLock) {
+ if (isScreenOn) {
+ mSystemSleepFlags |= FLAG_SCREEN_ON;
+ } else {
+ mSystemSleepFlags &= ~FLAG_SCREEN_ON;
+ }
+ setVrModeAllowedLocked(mSystemSleepFlags == FLAG_ALL);
+ }
+ }
+
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -148,7 +211,9 @@
} break;
case MSG_PENDING_VR_STATE_CHANGE : {
synchronized(mLock) {
- VrManagerService.this.consumeAndApplyPendingStateLocked();
+ if (mVrModeAllowed) {
+ VrManagerService.this.consumeAndApplyPendingStateLocked();
+ }
}
} break;
default :
@@ -268,8 +333,8 @@
}
mNotifAccessManager.update(enabledPackages);
- if (mCurrentVrService == null) {
- return; // No active services
+ if (!mVrModeAllowed) {
+ return; // Don't do anything, we shouldn't be in VR mode.
}
// If there is a pending state change, we'd better deal with that first
@@ -321,6 +386,7 @@
return;
}
pw.println("********* Dump of VrManagerService *********");
+ pw.println("VR mode is currently: " + ((mVrModeAllowed) ? "allowed" : "disallowed"));
pw.println("Previous state transitions:\n");
String tab = " ";
dumpStateTransitions(pw);
@@ -374,13 +440,17 @@
@Override
public void setVrMode(boolean enabled, ComponentName packageName, int userId,
ComponentName callingPackage) {
- VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage, false);
+ VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
}
@Override
- public void setVrModeImmediate(boolean enabled, ComponentName packageName, int userId,
- ComponentName callingPackage) {
- VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage, true);
+ public void onSleepStateChanged(boolean isAsleep) {
+ VrManagerService.this.setSleepState(isAsleep);
+ }
+
+ @Override
+ public void onScreenStateChanged(boolean isScreenOn) {
+ VrManagerService.this.setScreenOn(isScreenOn);
}
@Override
@@ -424,6 +494,10 @@
mComponentObserver.rebuildAll();
}
+ } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
+ synchronized (mLock) {
+ mVrModeAllowed = true;
+ }
}
}
@@ -466,12 +540,16 @@
false, mOverlayToken, null, oldUserId);
}
+ if (!mVrModeEnabled) {
+ return;
+ }
+
// Apply the restrictions for the current user based on vr state
String[] exemptions = (exemptedPackage == null) ? new String[0] :
new String[] { exemptedPackage };
appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
- mVrModeEnabled, mOverlayToken, exemptions, newUserId);
+ true, mOverlayToken, exemptions, newUserId);
}
private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId,
@@ -512,7 +590,8 @@
boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
EnabledComponentsObserver.NO_ERROR);
- if (!mVrModeEnabled && !enabled) {
+ boolean goingIntoVrMode = validUserComponent && enabled;
+ if (!mVrModeEnabled && !goingIntoVrMode) {
return validUserComponent; // Disabled -> Disabled transition does nothing.
}
@@ -520,29 +599,37 @@
? mCurrentVrService.getComponent().getPackageName() : null;
final int oldUserId = mCurrentVrModeUser;
- // Always send mode change events.
- changeVrModeLocked(enabled);
+ // Notify system services and VR HAL of mode change.
+ changeVrModeLocked(goingIntoVrMode);
- if (!enabled || !validUserComponent) {
- // Unbind whatever is running
+ boolean nothingChanged = false;
+ if (!goingIntoVrMode) {
+ // Not going into VR mode, unbind whatever is running
if (mCurrentVrService != null) {
Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " +
mCurrentVrService.getUserId());
mCurrentVrService.disconnect();
mCurrentVrService = null;
+ } else {
+ nothingChanged = true;
}
} else {
+ // Going into VR mode
if (mCurrentVrService != null) {
- // Unbind any running service that doesn't match the component/user selection
+ // Unbind any running service that doesn't match the latest component/user
+ // selection.
if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() +
" for user " + mCurrentVrService.getUserId());
createAndConnectService(component, userId);
sendUpdatedCaller = true;
+ } else {
+ nothingChanged = true;
}
- // The service with the correct component/user is bound
+ // The service with the correct component/user is already bound, do nothing.
} else {
- // Nothing was previously running, bind a new service
+ // Nothing was previously running, bind a new service for the latest
+ // component/user selection.
createAndConnectService(component, userId);
sendUpdatedCaller = true;
}
@@ -577,7 +664,10 @@
}
});
}
- logStateLocked();
+
+ if (!nothingChanged) {
+ logStateLocked();
+ }
return validUserComponent;
} finally {
@@ -663,16 +753,28 @@
private void grantCoarseLocationPermissionIfNeeded(String pkg, int userId) {
// Don't clobber the user if permission set in current state explicitly
if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
- mContext.getPackageManager().grantRuntimePermission(pkg,
- Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
+ try {
+ mContext.getPackageManager().grantRuntimePermission(pkg,
+ Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
+ } catch (IllegalArgumentException e) {
+ // Package was removed during update.
+ Slog.w(TAG, "Could not grant coarse location permission, package " + pkg
+ + " was removed.");
+ }
}
}
private void revokeCoarseLocationPermissionIfNeeded(String pkg, int userId) {
// Don't clobber the user if permission set in current state explicitly
if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
- mContext.getPackageManager().revokeRuntimePermission(pkg,
- Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
+ try {
+ mContext.getPackageManager().revokeRuntimePermission(pkg,
+ Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
+ } catch (IllegalArgumentException e) {
+ // Package was removed during update.
+ Slog.w(TAG, "Could not revoke coarse location permission, package " + pkg
+ + " was removed.");
+ }
}
}
@@ -772,7 +874,10 @@
mPendingState.targetPackageName, mPendingState.userId,
mPendingState.callingPackage);
mPendingState = null;
+ } else {
+ updateCurrentVrServiceLocked(false, null, 0, null);
}
+
}
private void logStateLocked() {
@@ -822,13 +927,20 @@
/*
* Implementation of VrManagerInternal calls. These are callable from system services.
*/
-
private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
- int userId, @NonNull ComponentName callingPackage, boolean immediate) {
+ int userId, @NonNull ComponentName callingPackage) {
synchronized (mLock) {
+ VrState pending = new VrState(enabled, targetPackageName, userId, callingPackage);
+ if (!mVrModeAllowed) {
+ // We're not allowed to be in VR mode. Make this state pending. This will be
+ // applied the next time we are allowed to enter VR mode unless it is superseded by
+ // another call.
+ mPendingState = pending;
+ return;
+ }
- if (!enabled && mCurrentVrService != null && !immediate) {
+ if (!enabled && mCurrentVrService != null) {
// If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls
// and service bind/unbind in case we are immediately switching to another VR app.
if (mPendingState == null) {
@@ -836,7 +948,7 @@
PENDING_STATE_DELAY_MS);
}
- mPendingState = new VrState(enabled, targetPackageName, userId, callingPackage);
+ mPendingState = pending;
return;
} else {
mHandler.removeMessages(MSG_PENDING_VR_STATE_CHANGE);
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index e1b598a..c42647e 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -411,7 +411,7 @@
}
if (mService.mInputMethodTarget != null
&& mService.mInputMethodTarget.mAppToken == mAppToken) {
- mAppToken.getDisplayContent().moveInputMethodWindowsIfNeeded(true);
+ mAppToken.getDisplayContent().computeImeTarget(true /* updateImeTarget */);
}
if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + mAppToken
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 5838a37..6147885 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -17,6 +17,8 @@
package com.android.server.wm;
import static android.app.ActivityManager.StackId;
+import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
+import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
@@ -42,10 +44,10 @@
import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
import static com.android.server.wm.WindowManagerService.H.NOTIFY_STARTING_WINDOW_DRAWN;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
-import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
import static com.android.server.wm.WindowManagerService.logWithStack;
+import android.content.pm.ActivityInfo;
import android.os.Debug;
import com.android.internal.util.ToBooleanFunction;
import com.android.server.input.InputApplicationHandle;
@@ -62,12 +64,10 @@
import android.view.IApplicationToken;
import android.view.View;
import android.view.WindowManager;
-import android.view.animation.Animation;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
-import java.util.function.Function;
class AppTokenList extends ArrayList<AppWindowToken> {
}
@@ -84,18 +84,18 @@
@NonNull final AppWindowAnimator mAppAnimator;
- final boolean voiceInteraction;
+ final boolean mVoiceInteraction;
// TODO: Use getParent instead?
Task mTask;
/** @see WindowContainer#fillsParent() */
private boolean mFillsParent;
boolean layoutConfigChanges;
- boolean showForAllUsers;
- int targetSdk;
+ boolean mShowForAllUsers;
+ int mTargetSdk;
// The input dispatching timeout for this application token in nanoseconds.
- long inputDispatchingTimeoutNanos;
+ long mInputDispatchingTimeoutNanos;
// These are used for determining when all windows associated with
// an activity have been drawn, so they can be made visible together
@@ -155,7 +155,7 @@
boolean mLaunchTaskBehind;
boolean mEnteringAnimation;
- boolean mAlwaysFocusable;
+ private boolean mAlwaysFocusable;
boolean mAppStopped;
int mRotationAnimationHint;
@@ -170,12 +170,31 @@
ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
- AppWindowToken(WindowManagerService service, IApplicationToken token, boolean _voiceInteraction,
- DisplayContent displayContent) {
- super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true,
- displayContent);
+ AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
+ DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen,
+ boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint,
+ int configChanges, boolean launchTaskBehind, boolean alwaysFocusable) {
+ this(service, token, voiceInteraction, dc);
+ mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
+ mFillsParent = fullscreen;
+ mShowForAllUsers = showForAllUsers;
+ mTargetSdk = targetSdk;
+ mOrientation = orientation;
+ layoutConfigChanges = (configChanges & (CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION)) != 0;
+ mLaunchTaskBehind = launchTaskBehind;
+ mAlwaysFocusable = alwaysFocusable;
+ mRotationAnimationHint = rotationAnimationHint;
+
+ // Application tokens start out hidden.
+ hidden = true;
+ hiddenRequested = true;
+ }
+
+ AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
+ DisplayContent dc) {
+ super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc);
appToken = token;
- voiceInteraction = _voiceInteraction;
+ mVoiceInteraction = voiceInteraction;
mInputApplicationHandle = new InputApplicationHandle(this);
mAppAnimator = new AppWindowAnimator(this, service);
}
@@ -390,10 +409,10 @@
@Override
void removeIfPossible() {
mIsExiting = false;
- removeAllWindows();
+ removeAllWindowsIfPossible();
if (mTask != null) {
mTask.mStack.mExitingAppTokens.remove(this);
- mTask.removeChild(this);
+ removeImmediately();
}
}
@@ -410,7 +429,7 @@
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
- boolean delayed = setVisibility(null, false, TRANSIT_UNSET, true, voiceInteraction);
+ boolean delayed = setVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
mService.mOpeningApps.remove(this);
mService.mUnknownAppVisibilityController.appRemoved(this);
@@ -1006,10 +1025,7 @@
tStartingWindow.mToken = this;
tStartingWindow.mAppToken = this;
- if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
- "Removing starting window: " + tStartingWindow);
- getDisplayContent().removeFromWindowList(tStartingWindow);
- if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
+ if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
"Removing starting " + tStartingWindow + " from " + fromToken);
fromToken.removeChild(tStartingWindow);
fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
@@ -1259,23 +1275,12 @@
mService.mAnimator.mAppWindowAnimating = true;
} else if (mAppAnimator.wasAnimating) {
// stopped animating, do one more pass through the layout
- setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER, "appToken " + this + " done");
+ setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
+ DEBUG_LAYOUT_REPEATS ? "appToken " + this + " done" : null);
if (DEBUG_ANIM) Slog.v(TAG, "updateWindowsApps...: done animating " + this);
}
}
- int rebuildWindowListUnchecked(int addIndex) {
- return super.rebuildWindowList(addIndex);
- }
-
- @Override
- int rebuildWindowList(int addIndex) {
- if (mIsExiting && !waitingForReplacement()) {
- return addIndex;
- }
- return rebuildWindowListUnchecked(addIndex);
- }
-
@Override
boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
// For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
@@ -1337,11 +1342,37 @@
mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
}
+ WindowState getImeTargetBelowWindow(WindowState w) {
+ final int index = mChildren.indexOf(w);
+ if (index > 0) {
+ final WindowState target = mChildren.get(index - 1);
+ if (target.canBeImeTarget()) {
+ return target;
+ }
+ }
+ return null;
+ }
+
+ WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
+ WindowState candidate = null;
+ for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
+ final WindowState w = mChildren.get(i);
+ if (w.mRemoved) {
+ continue;
+ }
+ if (candidate == null || w.mWinAnimator.mAnimLayer >
+ candidate.mWinAnimator.mAnimLayer) {
+ candidate = w;
+ }
+ }
+ return candidate;
+ }
+
@Override
void dump(PrintWriter pw, String prefix) {
super.dump(pw, prefix);
if (appToken != null) {
- pw.print(prefix); pw.print("app=true voiceInteraction="); pw.println(voiceInteraction);
+ pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
}
pw.print(prefix); pw.print("task="); pw.println(mTask);
pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e73acde..203137d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -33,10 +33,6 @@
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_TOP;
-import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
-import static android.view.WindowManager.INPUT_CONSUMER_PIP;
-import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -44,13 +40,10 @@
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -64,7 +57,6 @@
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
@@ -77,10 +69,8 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -94,7 +84,6 @@
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
import static com.android.server.wm.WindowManagerService.dipToPixel;
-import static com.android.server.wm.WindowManagerService.localLOGV;
import static com.android.server.wm.WindowManagerService.logSurface;
import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
@@ -120,29 +109,23 @@
import android.util.Slog;
import android.view.Display;
import android.view.DisplayInfo;
-import android.view.IWindow;
-import android.view.InputChannel;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.WindowManagerPolicy;
-import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.view.IInputMethodClient;
-import com.android.server.input.InputWindowHandle;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.io.StringWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
-import java.util.function.Function;
+import java.util.function.Predicate;
/**
* Utility class for keeping track of the WindowStates and other pertinent contents of a
@@ -174,8 +157,12 @@
private final NonAppWindowContainers mImeWindowsContainers =
new NonAppWindowContainers("mImeWindowsContainers");
- // Z-ordered (bottom-most first) list of all Window objects.
- private final WindowList mWindows = new WindowList();
+ private WindowState mTmpWindow;
+ private WindowState mTmpWindow2;
+ private WindowAnimator mTmpWindowAnimator;
+ private boolean mTmpRecoveringMemory;
+ private boolean mUpdateImeTarget;
+ private boolean mTmpInitial;
// Mapping from a token IBinder to a WindowToken object on this display.
private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
@@ -198,7 +185,7 @@
private boolean mLayoutNeeded;
int pendingLayoutChanges;
// TODO(multi-display): remove some of the usages.
- final boolean isDefaultDisplay;
+ boolean isDefaultDisplay;
/** Window tokens that are in the process of exiting, but still on screen for animations. */
final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
@@ -220,7 +207,7 @@
private final Matrix mTmpMatrix = new Matrix();
private final Region mTmpRegion = new Region();
- final WindowManagerService mService;
+ WindowManagerService mService;
/** Remove this display when animation on it has completed. */
private boolean mDeferredRemoval;
@@ -228,34 +215,413 @@
final DockedStackDividerController mDividerControllerLocked;
final PinnedStackController mPinnedStackControllerLocked;
- final DimLayerController mDimLayerController;
+ DimLayerController mDimLayerController;
final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
- /** Used when rebuilding window list to keep track of windows that have been removed. */
- private WindowState[] mRebuildTmp = new WindowState[20];
-
- /**
- * Temporary list for comparison. Always clear this after use so we don't end up with
- * orphaned windows references
- */
- private final ArrayList<WindowState> mTmpWindows = new ArrayList<>();
+ private boolean mHaveBootMsg = false;
+ private boolean mHaveApp = false;
+ private boolean mHaveWallpaper = false;
+ private boolean mHaveKeyguard = true;
private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
new TaskForResizePointSearchResult();
- private final GetWindowOnDisplaySearchResult mTmpGetWindowOnDisplaySearchResult =
- new GetWindowOnDisplaySearchResult();
+ private final ApplySurfaceChangesTransactionState mTmpApplySurfaceChangesTransactionState =
+ new ApplySurfaceChangesTransactionState();
+ private final ScreenshotApplicationState mScreenshotApplicationState =
+ new ScreenshotApplicationState();
// True if this display is in the process of being removed. Used to determine if the removal of
// the display's direct children should be allowed.
private boolean mRemovingDisplay = false;
private final WindowLayersController mLayersController;
- final WallpaperController mWallpaperController;
+ WallpaperController mWallpaperController;
int mInputMethodAnimLayerAdjustment;
+ private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
+ WindowStateAnimator winAnimator = w.mWinAnimator;
+ if (winAnimator.hasSurface()) {
+ final boolean wasAnimating = winAnimator.mWasAnimating;
+ final boolean nowAnimating = winAnimator.stepAnimationLocked(
+ mTmpWindowAnimator.mCurrentTime);
+ winAnimator.mWasAnimating = nowAnimating;
+ mTmpWindowAnimator.orAnimating(nowAnimating);
+
+ if (DEBUG_WALLPAPER) Slog.v(TAG,
+ w + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating);
+
+ if (wasAnimating && !winAnimator.mAnimating
+ && mWallpaperController.isWallpaperTarget(w)) {
+ mTmpWindowAnimator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
+ pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ if (DEBUG_LAYOUT_REPEATS) {
+ mService.mWindowPlacerLocked.debugLayoutRepeats(
+ "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges);
+ }
+ }
+ }
+
+ final AppWindowToken atoken = w.mAppToken;
+ if (winAnimator.mDrawState == READY_TO_SHOW) {
+ if (atoken == null || atoken.allDrawn) {
+ if (w.performShowLocked()) {
+ pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
+ if (DEBUG_LAYOUT_REPEATS) {
+ mService.mWindowPlacerLocked.debugLayoutRepeats(
+ "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges);
+ }
+ }
+ }
+ }
+ final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
+ if (appAnimator != null && appAnimator.thumbnail != null) {
+ if (appAnimator.thumbnailTransactionSeq
+ != mTmpWindowAnimator.mAnimTransactionSequence) {
+ appAnimator.thumbnailTransactionSeq =
+ mTmpWindowAnimator.mAnimTransactionSequence;
+ appAnimator.thumbnailLayer = 0;
+ }
+ if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
+ appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
+ }
+ }
+ };
+
+ private final Consumer<WindowState> mUpdateWallpaperForAnimator = w -> {
+ final WindowStateAnimator winAnimator = w.mWinAnimator;
+ if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
+ return;
+ }
+
+ final int flags = w.mAttrs.flags;
+
+ // If this window is animating, make a note that we have an animating window and take
+ // care of a request to run a detached wallpaper animation.
+ if (winAnimator.mAnimating) {
+ if (winAnimator.mAnimation != null) {
+ if ((flags & FLAG_SHOW_WALLPAPER) != 0
+ && winAnimator.mAnimation.getDetachWallpaper()) {
+ mTmpWindow = w;
+ }
+ final int color = winAnimator.mAnimation.getBackgroundColor();
+ if (color != 0) {
+ final TaskStack stack = w.getStack();
+ if (stack != null) {
+ stack.setAnimationBackground(winAnimator, color);
+ }
+ }
+ }
+ mTmpWindowAnimator.setAnimating(true);
+ }
+
+ // If this window's app token is running a detached wallpaper animation, make a note so
+ // we can ensure the wallpaper is displayed behind it.
+ final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
+ if (appAnimator != null && appAnimator.animation != null
+ && appAnimator.animating) {
+ if ((flags & FLAG_SHOW_WALLPAPER) != 0
+ && appAnimator.animation.getDetachWallpaper()) {
+ mTmpWindow = w;
+ }
+
+ final int color = appAnimator.animation.getBackgroundColor();
+ if (color != 0) {
+ final TaskStack stack = w.getStack();
+ if (stack != null) {
+ stack.setAnimationBackground(winAnimator, color);
+ }
+ }
+ }
+ };
+
+ private final Consumer<WindowState> mSetInputMethodAnimLayerAdjustment =
+ w -> w.adjustAnimLayer(mInputMethodAnimLayerAdjustment);
+
+ private final Consumer<WindowState> mScheduleToastTimeout = w -> {
+ final int lostFocusUid = mTmpWindow.mOwnerUid;
+ final Handler handler = mService.mH;
+ if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) {
+ if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) {
+ handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w),
+ w.mAttrs.hideTimeoutMilliseconds);
+ }
+ }
+ };
+
+ private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> {
+ final AppWindowToken focusedApp = mService.mFocusedApp;
+ if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + w
+ + ", flags=" + w.mAttrs.flags + ", canReceive=" + w.canReceiveKeys());
+
+ if (!w.canReceiveKeys()) {
+ return false;
+ }
+
+ final AppWindowToken wtoken = w.mAppToken;
+
+ // If this window's application has been removed, just skip it.
+ if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
+ if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
+ + (wtoken.removed ? "removed" : "sendingToBottom"));
+ return false;
+ }
+
+ if (focusedApp == null) {
+ if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
+ + " using new focus @ " + w);
+ mTmpWindow = w;
+ return true;
+ }
+
+ if (!focusedApp.windowsAreFocusable()) {
+ // Current focused app windows aren't focusable...
+ if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
+ + " focusable using new focus @ " + w);
+ mTmpWindow = w;
+ return true;
+ }
+
+ // Descend through all of the app tokens and find the first that either matches
+ // win.mAppToken (return win) or mFocusedApp (return null).
+ if (wtoken != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) {
+ if (focusedApp.compareTo(wtoken) > 0) {
+ // App stack below focused app stack. No focus for you!!!
+ if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
+ "findFocusedWindow: Reached focused app=" + focusedApp);
+ mTmpWindow = null;
+ return true;
+ }
+ }
+
+ if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + w);
+ mTmpWindow = w;
+ return true;
+ };
+
+ private final Consumer<WindowState> mPrepareWindowSurfaces =
+ w -> w.mWinAnimator.prepareSurfaceLocked(true);
+
+ private final Consumer<WindowState> mPerformLayout = w -> {
+ // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
+ // wasting time and funky changes while a window is animating away.
+ final boolean gone = (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w))
+ || w.isGoneForLayoutLw();
+
+ if (DEBUG_LAYOUT && !w.mLayoutAttached) {
+ Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame
+ + " mLayoutAttached=" + w.mLayoutAttached
+ + " screen changed=" + w.isConfigChanged());
+ final AppWindowToken atoken = w.mAppToken;
+ if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + w.mViewVisibility
+ + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden
+ + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
+ + " parentHidden=" + w.isParentWindowHidden());
+ else Slog.v(TAG, " VIS: mViewVisibility=" + w.mViewVisibility
+ + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden
+ + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
+ + " parentHidden=" + w.isParentWindowHidden());
+ }
+
+ // If this view is GONE, then skip it -- keep the current frame, and let the caller know
+ // so they can ignore it if they want. (We do the normal layout for INVISIBLE windows,
+ // since that means "perform layout as normal, just don't display").
+ if (!gone || !w.mHaveFrame || w.mLayoutNeeded
+ || ((w.isConfigChanged() || w.setReportResizeHints())
+ && !w.isGoneForLayoutLw() &&
+ ((w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
+ (w.mHasSurface && w.mAppToken != null &&
+ w.mAppToken.layoutConfigChanges)))) {
+ if (!w.mLayoutAttached) {
+ if (mTmpInitial) {
+ //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
+ w.mContentChanged = false;
+ }
+ if (w.mAttrs.type == TYPE_DREAM) {
+ // Don't layout windows behind a dream, so that if it does stuff like hide
+ // the status bar we won't get a bad transition when it goes away.
+ mTmpWindow = w;
+ }
+ w.mLayoutNeeded = false;
+ w.prelayout();
+ mService.mPolicy.layoutWindowLw(w, null);
+ w.mLayoutSeq = mService.mLayoutSeq;
+
+ // Window frames may have changed. Update dim layer with the new bounds.
+ final Task task = w.getTask();
+ if (task != null) {
+ mDimLayerController.updateDimLayer(task);
+ }
+
+ if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame
+ + " mContainingFrame=" + w.mContainingFrame
+ + " mDisplayFrame=" + w.mDisplayFrame);
+ }
+ }
+ };
+
+ private final Consumer<WindowState> mPerformLayoutAttached = w -> {
+ if (w.mLayoutAttached) {
+ if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
+ + " mViewVisibility=" + w.mViewVisibility
+ + " mRelayoutCalled=" + w.mRelayoutCalled);
+ // If this view is GONE, then skip it -- keep the current frame, and let the caller
+ // know so they can ignore it if they want. (We do the normal layout for INVISIBLE
+ // windows, since that means "perform layout as normal, just don't display").
+ if (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w)) {
+ return;
+ }
+ if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame
+ || w.mLayoutNeeded) {
+ if (mTmpInitial) {
+ //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
+ w.mContentChanged = false;
+ }
+ w.mLayoutNeeded = false;
+ w.prelayout();
+ mService.mPolicy.layoutWindowLw(w, w.getParentWindow());
+ w.mLayoutSeq = mService.mLayoutSeq;
+ if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame
+ + " mContainingFrame=" + w.mContainingFrame
+ + " mDisplayFrame=" + w.mDisplayFrame);
+ }
+ } else if (w.mAttrs.type == TYPE_DREAM) {
+ // Don't layout windows behind a dream, so that if it does stuff like hide the
+ // status bar we won't get a bad transition when it goes away.
+ mTmpWindow = mTmpWindow2;
+ }
+ };
+
+ private final Predicate<WindowState> mComputeImeTargetPredicate = w -> {
+ if (DEBUG_INPUT_METHOD && mUpdateImeTarget) Slog.i(TAG_WM, "Checking window @" + w
+ + " fl=0x" + Integer.toHexString(w.mAttrs.flags));
+ return w.canBeImeTarget();
+ };
+
+ private final Consumer<WindowState> mApplyPostLayoutPolicy =
+ w -> mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
+ mService.mInputMethodTarget);
+
+ private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
+ final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
+ final boolean obscuredChanged = w.mObscured !=
+ mTmpApplySurfaceChangesTransactionState.obscured;
+ final RootWindowContainer root = mService.mRoot;
+ // Only used if default window
+ final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
+
+ // Update effect.
+ w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;
+ if (!mTmpApplySurfaceChangesTransactionState.obscured) {
+ final boolean isDisplayed = w.isDisplayedLw();
+
+ if (isDisplayed && w.isObscuringDisplay()) {
+ // This window completely covers everything behind it, so we want to leave all
+ // of them as undimmed (for performance reasons).
+ root.mObscuringWindow = w;
+ mTmpApplySurfaceChangesTransactionState.obscured = true;
+ }
+
+ mTmpApplySurfaceChangesTransactionState.displayHasContent |=
+ root.handleNotObscuredLocked(w,
+ mTmpApplySurfaceChangesTransactionState.obscured,
+ mTmpApplySurfaceChangesTransactionState.syswin);
+
+ if (w.mHasSurface && isDisplayed) {
+ final int type = w.mAttrs.type;
+ if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
+ || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+ mTmpApplySurfaceChangesTransactionState.syswin = true;
+ }
+ if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0
+ && w.mAttrs.preferredRefreshRate != 0) {
+ mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
+ = w.mAttrs.preferredRefreshRate;
+ }
+ if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
+ && w.mAttrs.preferredDisplayModeId != 0) {
+ mTmpApplySurfaceChangesTransactionState.preferredModeId
+ = w.mAttrs.preferredDisplayModeId;
+ }
+ }
+ }
+
+ w.applyDimLayerIfNeeded();
+
+ if (isDefaultDisplay && obscuredChanged && w.isVisibleLw()
+ && mWallpaperController.isWallpaperTarget(w)) {
+ // This is the wallpaper target and its obscured state changed... make sure the
+ // current wallpaper's visibility has been updated accordingly.
+ mWallpaperController.updateWallpaperVisibility();
+ }
+
+ w.handleWindowMovedIfNeeded();
+
+ final WindowStateAnimator winAnimator = w.mWinAnimator;
+
+ //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
+ w.mContentChanged = false;
+
+ // Moved from updateWindowsAndWallpaperLocked().
+ if (w.mHasSurface) {
+ // Take care of the window being ready to display.
+ final boolean committed = winAnimator.commitFinishDrawingLocked();
+ if (isDefaultDisplay && committed) {
+ if (w.mAttrs.type == TYPE_DREAM) {
+ // HACK: When a dream is shown, it may at that point hide the lock screen.
+ // So we need to redo the layout to let the phone window manager make this
+ // happen.
+ pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
+ if (DEBUG_LAYOUT_REPEATS) {
+ surfacePlacer.debugLayoutRepeats(
+ "dream and commitFinishDrawingLocked true",
+ pendingLayoutChanges);
+ }
+ }
+ if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
+ if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+ "First draw done in potential wallpaper target " + w);
+ root.mWallpaperMayChange = true;
+ pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ if (DEBUG_LAYOUT_REPEATS) {
+ surfacePlacer.debugLayoutRepeats(
+ "wallpaper and commitFinishDrawingLocked true",
+ pendingLayoutChanges);
+ }
+ }
+ }
+ if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
+ // Updates the shown frame before we set up the surface. This is needed
+ // because the resizing could change the top-left position (in addition to
+ // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
+ // position the surface.
+ //
+ // If an animation is being started, we can't call this method because the
+ // animation hasn't processed its initial transformation yet, but in general
+ // we do want to update the position if the window is animating.
+ winAnimator.computeShownFrameLocked();
+ }
+ winAnimator.setSurfaceBoundariesLocked(mTmpRecoveringMemory /* recoveringMemory */);
+ }
+
+ final AppWindowToken atoken = w.mAppToken;
+ if (atoken != null) {
+ final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
+ if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
+ mTmpUpdateAllDrawn.add(atoken);
+ }
+ }
+
+ if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
+ && w.isDisplayedLw()) {
+ mTmpApplySurfaceChangesTransactionState.focusDisplayed = true;
+ }
+
+ w.updateResizingWindowIfNeeded();
+ };
+
/**
* @param display May not be null.
* @param service You know.
@@ -302,7 +668,7 @@
return token.asAppWindowToken();
}
- void setWindowToken(IBinder binder, WindowToken token) {
+ void addWindowToken(IBinder binder, WindowToken token) {
final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token);
if (dc != null) {
// We currently don't support adding a window token to the display if the display
@@ -335,20 +701,33 @@
WindowToken removeWindowToken(IBinder binder) {
final WindowToken token = mTokenMap.remove(binder);
if (token != null && token.asAppWindowToken() == null) {
+ token.setExiting();
+ }
+ return token;
+ }
+
+ /** Changes the display the input window token is housed on to this one. */
+ void reParentWindowToken(WindowToken token) {
+ final DisplayContent prevDc = token.getDisplayContent();
+ if (prevDc == this) {
+ return;
+ }
+ if (prevDc != null && prevDc.mTokenMap.remove(token.token) != null) {
switch (token.windowType) {
case TYPE_WALLPAPER:
- mBelowAppWindowsContainers.removeChild(token);
+ prevDc.mBelowAppWindowsContainers.removeChild(token);
break;
case TYPE_INPUT_METHOD:
case TYPE_INPUT_METHOD_DIALOG:
- mImeWindowsContainers.removeChild(token);
+ prevDc.mImeWindowsContainers.removeChild(token);
break;
default:
- mAboveAppWindowsContainers.removeChild(token);
+ prevDc.mAboveAppWindowsContainers.removeChild(token);
break;
}
}
- return token;
+
+ addWindowToken(token.token, token);
}
void removeAppToken(IBinder binder) {
@@ -455,17 +834,50 @@
@Override
void onAppTransitionDone() {
super.onAppTransitionDone();
- rebuildAppWindowList();
+ mService.mWindowsChanged = true;
+ }
+
+ @Override
+ boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
+ // Special handling so we can process IME windows with #forAllImeWindows above their IME
+ // target, or here in order if there isn't an IME target.
+ if (traverseTopToBottom) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final DisplayChildWindowContainer child = mChildren.get(i);
+ if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) {
+ // In this case the Ime windows will be processed above their target so we skip
+ // here.
+ continue;
+ }
+ if (child.forAllWindows(callback, traverseTopToBottom)) {
+ return true;
+ }
+ }
+ } else {
+ final int count = mChildren.size();
+ for (int i = 0; i < count; i++) {
+ final DisplayChildWindowContainer child = mChildren.get(i);
+ if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) {
+ // In this case the Ime windows will be processed above their target so we skip
+ // here.
+ continue;
+ }
+ if (child.forAllWindows(callback, traverseTopToBottom)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
+ return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom);
}
@Override
int getOrientation() {
final WindowManagerPolicy policy = mService.mPolicy;
- // TODO: All the logic before the last return statement in this method should really go in
- // #NonAppWindowContainer.getOrientation() since it is trying to decide orientation based
- // on non-app windows. But, we can not do that until the window list is always correct in
- // terms of z-ordering based on layers.
if (mService.mDisplayFrozen) {
if (mService.mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
@@ -486,31 +898,9 @@
return mService.mLastOrientation;
}
} else {
- for (int pos = mWindows.size() - 1; pos >= 0; --pos) {
- final WindowState win = mWindows.get(pos);
- if (win.mAppToken != null) {
- // We hit an application window. so the orientation will be determined by the
- // app window. No point in continuing further.
- break;
- }
- if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
- continue;
- }
- int req = win.mAttrs.screenOrientation;
- if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND) {
- continue;
- }
-
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
- if (policy.isKeyguardHostWindow(win.mAttrs)) {
- mService.mLastKeyguardForcedOrientation = req;
- }
- return (mService.mLastWindowForcedOrientation = req);
- }
- mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
-
- if (policy.isKeyguardShowingAndNotOccluded()) {
- return mService.mLastKeyguardForcedOrientation;
+ final int orientation = mAboveAppWindowsContainers.getOrientation();
+ if (orientation != SCREEN_ORIENTATION_UNSET) {
+ return orientation;
}
}
@@ -738,22 +1128,10 @@
}
}
+ @Override
void switchUser() {
- final int count = mWindows.size();
- for (int i = 0; i < count; i++) {
- final WindowState win = mWindows.get(i);
- if (win.isHiddenFromUserLocked()) {
- if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + win
- + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid);
- win.hideLw(false);
- }
- }
-
- for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
- mTaskStackContainers.get(stackNdx).switchUser();
- }
-
- rebuildAppWindowList();
+ super.switchUser();
+ mService.mWindowsChanged = true;
}
private void resetAnimationBackgroundAnimator() {
@@ -915,19 +1293,8 @@
void setInputMethodAnimLayerAdjustment(int adj) {
if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj);
mInputMethodAnimLayerAdjustment = adj;
- final WindowState imw = mService.mInputMethodWindow;
- if (imw != null) {
- imw.adjustAnimLayer(adj);
- }
- for (int i = mService.mInputMethodDialogs.size() - 1; i >= 0; i--) {
- final WindowState dialog = mService.mInputMethodDialogs.get(i);
- // TODO: This and other places setting mAnimLayer can probably use WS.adjustAnimLayer,
- // but need to make sure we are not setting things twice for child windows that are
- // already in the list.
- dialog.mWinAnimator.mAnimLayer = dialog.mLayer + adj;
- if (DEBUG_LAYERS) Slog.v(TAG_WM, "IM win " + imw
- + " anim layer: " + dialog.mWinAnimator.mAnimLayer);
- }
+ mImeWindowsContainers.forAllWindows(mSetInputMethodAnimLayerAdjustment,
+ true /* traverseTopToBottom */);
}
/**
@@ -936,11 +1303,11 @@
* suddenly disappear.
*/
int getLayerForAnimationBackground(WindowStateAnimator winAnimator) {
- for (int i = mWindows.size() - 1; i >= 0; --i) {
- final WindowState win = mWindows.get(i);
- if (win.mIsWallpaper && win.isVisibleNow()) {
- return win.mWinAnimator.mAnimLayer;
- }
+ final WindowState visibleWallpaper = mBelowAppWindowsContainers.getWindow(
+ w -> w.mIsWallpaper && w.isVisibleNow());
+
+ if (visibleWallpaper != null) {
+ return visibleWallpaper.mWinAnimator.mAnimLayer;
}
return winAnimator.mAnimLayer;
}
@@ -1088,317 +1455,60 @@
/** Find the visible, touch-deliverable window under the given point */
WindowState getTouchableWinAtPointLocked(float xf, float yf) {
- WindowState touchedWin = null;
final int x = (int) xf;
final int y = (int) yf;
-
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- WindowState window = mWindows.get(i);
- final int flags = window.mAttrs.flags;
- if (!window.isVisibleLw()) {
- continue;
+ final WindowState touchedWin = getWindow(w -> {
+ final int flags = w.mAttrs.flags;
+ if (!w.isVisibleLw()) {
+ return false;
}
if ((flags & FLAG_NOT_TOUCHABLE) != 0) {
- continue;
+ return false;
}
- window.getVisibleBounds(mTmpRect);
+ w.getVisibleBounds(mTmpRect);
if (!mTmpRect.contains(x, y)) {
- continue;
+ return false;
}
- window.getTouchableRegion(mTmpRegion);
+ w.getTouchableRegion(mTmpRegion);
final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL);
- if (mTmpRegion.contains(x, y) || touchFlags == 0) {
- touchedWin = window;
- break;
- }
- }
+ return mTmpRegion.contains(x, y) || touchFlags == 0;
+ });
return touchedWin;
}
boolean canAddToastWindowForUid(int uid) {
// We allow one toast window per UID being shown at a time.
- final int windowCount = mWindows.size();
- for (int i = 0; i < windowCount; i++) {
- final WindowState window = mWindows.get(i);
- if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid
- && !window.mPermanentlyHidden && !window.mWindowRemovalAllowed) {
- return false;
- }
- }
- return true;
+ final WindowState win = getWindow(w ->
+ w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == uid && !w.mPermanentlyHidden
+ && !w.mWindowRemovalAllowed);
+ return win == null;
}
void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) {
if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
return;
}
- final int lostFocusUid = oldFocus.mOwnerUid;
- final int windowCount = mWindows.size();
- final Handler handler = mService.mH;
- for (int i = 0; i < windowCount; i++) {
- final WindowState window = mWindows.get(i);
- if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) {
- if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, window)) {
- handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, window),
- window.mAttrs.hideTimeoutMilliseconds);
- }
- }
- }
+
+ // Used to communicate the old focus to the callback method.
+ mTmpWindow = oldFocus;
+
+ forAllWindows(mScheduleToastTimeout, false /* traverseTopToBottom */);
}
WindowState findFocusedWindow() {
- final AppWindowToken focusedApp = mService.mFocusedApp;
+ mTmpWindow = null;
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState win = mWindows.get(i);
+ forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */);
- if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + i + " = " + win
- + ", flags=" + win.mAttrs.flags + ", canReceive=" + win.canReceiveKeys());
-
- if (!win.canReceiveKeys()) {
- continue;
- }
-
- final AppWindowToken wtoken = win.mAppToken;
-
- // If this window's application has been removed, just skip it.
- if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
- if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
- + (wtoken.removed ? "removed" : "sendingToBottom"));
- continue;
- }
-
- if (focusedApp == null) {
- if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
- + " using new focus @ " + i + " = " + win);
- return win;
- }
-
- if (!focusedApp.windowsAreFocusable()) {
- // Current focused app windows aren't focusable...
- if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
- + " focusable using new focus @ " + i + " = " + win);
- return win;
- }
-
- // Descend through all of the app tokens and find the first that either matches
- // win.mAppToken (return win) or mFocusedApp (return null).
- if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
- if (focusedApp.compareTo(wtoken) > 0) {
- // App stack below focused app stack. No focus for you!!!
- if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
- "findFocusedWindow: Reached focused app=" + focusedApp);
- return null;
- }
- }
-
- if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ "
- + i + " = " + win);
- return win;
+ if (mTmpWindow == null) {
+ if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
+ return null;
}
-
- if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
- return null;
- }
-
- void addAppWindowToWindowList(final WindowState win) {
- final IWindow client = win.mClient;
-
- WindowList tokenWindowList = getTokenWindowsOnDisplay(win.mToken);
- if (!tokenWindowList.isEmpty()) {
- addAppWindowExisting(win, tokenWindowList);
- return;
- }
-
- // No windows from this token on this display
- if (localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window "
- + client.asBinder() + " (token=" + this + ")");
-
- final WindowToken wToken = win.mToken;
-
- // Figure out where the window should go, based on the order of applications.
- mTmpGetWindowOnDisplaySearchResult.reset();
- for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.get(i);
- stack.getWindowOnDisplayBeforeToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
- if (mTmpGetWindowOnDisplaySearchResult.reachedToken) {
- // We have reach the token we are interested in. End search.
- break;
- }
- }
-
- WindowState pos = mTmpGetWindowOnDisplaySearchResult.foundWindow;
-
- // We now know the index into the apps. If we found an app window above, that gives us the
- // position; else we need to look some more.
- if (pos != null) {
- // Move behind any windows attached to this one.
- final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
- if (atoken != null) {
- tokenWindowList = getTokenWindowsOnDisplay(atoken);
- final int NC = tokenWindowList.size();
- if (NC > 0) {
- WindowState bottom = tokenWindowList.get(0);
- if (bottom.mSubLayer < 0) {
- pos = bottom;
- }
- }
- }
- addWindowToListBefore(win, pos);
- return;
- }
-
- // Continue looking down until we find the first token that has windows on this display.
- mTmpGetWindowOnDisplaySearchResult.reset();
- for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.get(i);
- stack.getWindowOnDisplayAfterToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
- if (mTmpGetWindowOnDisplaySearchResult.foundWindow != null) {
- // We have found a window after the token. End search.
- break;
- }
- }
-
- pos = mTmpGetWindowOnDisplaySearchResult.foundWindow;
-
- if (pos != null) {
- // Move in front of any windows attached to this one.
- final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
- if (atoken != null) {
- final WindowState top = atoken.getTopWindow();
- if (top != null && top.mSubLayer >= 0) {
- pos = top;
- }
- }
- addWindowToListAfter(win, pos);
- return;
- }
-
- // Just search for the start of this layer.
- final int myLayer = win.mBaseLayer;
- int i;
- for (i = mWindows.size() - 1; i >= 0; --i) {
- final WindowState w = mWindows.get(i);
- // Dock divider shares the base layer with application windows, but we want to always
- // keep it above the application windows. The sharing of the base layer is intended
- // for window animations, which need to be above the dock divider for the duration
- // of the animation.
- if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) {
- break;
- }
- }
- if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "Based on layer: Adding window " + win + " at " + (i + 1) + " of "
- + mWindows.size());
- mWindows.add(i + 1, win);
- mService.mWindowsChanged = true;
- }
-
- /** Adds this non-app window to the window list. */
- void addNonAppWindowToWindowList(WindowState win) {
- // Figure out where window should go, based on layer.
- int i;
- for (i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState otherWin = mWindows.get(i);
- if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= win.mBaseLayer) {
- // Wallpaper wanders through the window list, for example to position itself
- // directly behind keyguard. Because of this it will break the ordering based on
- // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and
- // we don't want the new window to appear above them. An example of this is adding
- // of the docked stack divider. Consider a scenario with the following ordering (top
- // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider
- // to land below the assist preview, so the dock divider must ignore the wallpaper,
- // with which it shares the base layer.
- break;
- }
- }
-
- i++;
- if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "Free window: Adding window " + this + " at " + i + " of " + mWindows.size());
- mWindows.add(i, win);
- mService.mWindowsChanged = true;
- }
-
- void addToWindowList(WindowState win, int index) {
- mService.mWindowsChanged = true;
- mWindows.add(index, win);
- }
-
- boolean removeFromWindowList(WindowState win) {
- mService.mWindowsChanged = true;
- return mWindows.remove(win);
- }
-
- private int removeWindowAndChildrenFromWindowList(WindowState win, int interestingPos) {
- int wpos = mWindows.indexOf(win);
- if (wpos < 0) {
- return interestingPos;
- }
-
- if (wpos < interestingPos) interestingPos--;
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing at " + wpos + ": " + this);
- mWindows.remove(wpos);
- mService.mWindowsChanged = true;
- int childWinCount = win.mChildren.size();
- while (childWinCount > 0) {
- childWinCount--;
- final WindowState cw = win.mChildren.get(childWinCount);
- int cpos = mWindows.indexOf(cw);
- if (cpos >= 0) {
- if (cpos < interestingPos) interestingPos--;
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM,
- "Temp removing child at " + cpos + ": " + cw);
- mWindows.remove(cpos);
- }
- }
- return interestingPos;
- }
-
- void addChildWindowToWindowList(WindowState win) {
- final WindowState parentWindow = win.getParentWindow();
-
- WindowList windowsOnSameDisplay = getTokenWindowsOnDisplay(win.mToken);
-
- // Figure out this window's ordering relative to the parent window.
- final int wCount = windowsOnSameDisplay.size();
- final int sublayer = win.mSubLayer;
- int largestSublayer = Integer.MIN_VALUE;
- WindowState windowWithLargestSublayer = null;
- int i;
- for (i = 0; i < wCount; i++) {
- WindowState w = windowsOnSameDisplay.get(i);
- final int wSublayer = w.mSubLayer;
- if (wSublayer >= largestSublayer) {
- largestSublayer = wSublayer;
- windowWithLargestSublayer = w;
- }
- if (sublayer < 0) {
- // For negative sublayers, we go below all windows in the same sublayer.
- if (wSublayer >= sublayer) {
- addWindowToListBefore(win, wSublayer >= 0 ? parentWindow : w);
- break;
- }
- } else {
- // For positive sublayers, we go above all windows in the same sublayer.
- if (wSublayer > sublayer) {
- addWindowToListBefore(win, w);
- break;
- }
- }
- }
- if (i >= wCount) {
- if (sublayer < 0) {
- addWindowToListBefore(win, parentWindow);
- } else {
- addWindowToListAfter(win,
- largestSublayer >= 0 ? windowWithLargestSublayer : parentWindow);
- }
- }
+ return mTmpWindow;
}
/** Updates the layer assignment of windows on this display. */
@@ -1409,136 +1519,9 @@
}
}
- void adjustWallpaperWindows() {
- mWallpaperController.adjustWallpaperWindows(this);
- }
-
- /**
- * Z-orders the display window list so that:
- * <ul>
- * <li>Any windows that are currently below the wallpaper window stay below the wallpaper
- * window.
- * <li>Exiting application windows are at the bottom, but above the wallpaper window.
- * <li>All other application windows are above the exiting application windows and ordered based
- * on the ordering of their stacks and tasks on the display.
- * <li>Non-application windows are at the very top.
- * </ul>
- * <p>
- * NOTE: This isn't a complete picture of what the user see. Further manipulation of the window
- * surface layering is done in {@link WindowLayersController}.
- */
- void rebuildAppWindowList() {
- int count = mWindows.size();
- int i;
- int lastBelow = -1;
- int numRemoved = 0;
-
- if (mRebuildTmp.length < count) {
- mRebuildTmp = new WindowState[count + 10];
- }
-
- // First remove all existing app windows.
- i = 0;
- while (i < count) {
- final WindowState w = mWindows.get(i);
- if (w.mAppToken != null) {
- final WindowState win = mWindows.remove(i);
- win.mRebuilding = true;
- mRebuildTmp[numRemoved] = win;
- mService.mWindowsChanged = true;
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win);
- count--;
- numRemoved++;
- continue;
- } else if (lastBelow == i-1) {
- if (w.mAttrs.type == TYPE_WALLPAPER) {
- lastBelow = i;
- }
- }
- i++;
- }
-
- // Keep whatever windows were below the app windows still below, by skipping them.
- lastBelow++;
- i = lastBelow;
-
- // First add all of the exiting app tokens... these are no longer in the main app list,
- // but still have windows shown. We put them in the back because now that the animation is
- // over we no longer will care about them.
- final int numStacks = mTaskStackContainers.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- AppTokenList exitingAppTokens = mTaskStackContainers.get(stackNdx).mExitingAppTokens;
- int NT = exitingAppTokens.size();
- for (int j = 0; j < NT; j++) {
- i = exitingAppTokens.get(j).rebuildWindowListUnchecked(i);
- }
- }
-
- // And add in the still active app tokens in Z order.
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- i = mTaskStackContainers.get(stackNdx).rebuildWindowList(i);
- }
-
- i -= lastBelow;
- if (i != numRemoved) {
- setLayoutNeeded();
- Slog.w(TAG_WM, "On display=" + mDisplayId + " Rebuild removed " + numRemoved
- + " windows but added " + i + " rebuildAppWindowListLocked() "
- + " callers=" + Debug.getCallers(10));
- for (i = 0; i < numRemoved; i++) {
- WindowState ws = mRebuildTmp[i];
- if (ws.mRebuilding) {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new FastPrintWriter(sw, false, 1024);
- ws.dump(pw, "", true);
- pw.flush();
- Slog.w(TAG_WM, "This window was lost: " + ws);
- Slog.w(TAG_WM, sw.toString());
- ws.mWinAnimator.destroySurfaceLocked();
- }
- }
- Slog.w(TAG_WM, "Current window hierarchy:");
- dumpChildrenNames();
- Slog.w(TAG_WM, "Final window list:");
- dumpWindows();
- }
- Arrays.fill(mRebuildTmp, null);
- }
-
- /** Rebuilds the display's window list and does a relayout if something changed. */
- void rebuildAppWindowsAndLayoutIfNeeded() {
- mTmpWindows.clear();
- mTmpWindows.addAll(mWindows);
-
- rebuildAppWindowList();
-
- // Set displayContent.mLayoutNeeded if window order changed.
- final int tmpSize = mTmpWindows.size();
- final int winSize = mWindows.size();
- int tmpNdx = 0, winNdx = 0;
- while (tmpNdx < tmpSize && winNdx < winSize) {
- // Skip over all exiting windows, they've been moved out of order.
- WindowState tmp;
- do {
- tmp = mTmpWindows.get(tmpNdx++);
- } while (tmpNdx < tmpSize && tmp.mAppToken != null && tmp.mAppToken.mIsExiting);
-
- WindowState win;
- do {
- win = mWindows.get(winNdx++);
- } while (winNdx < winSize && win.mAppToken != null && win.mAppToken.mIsExiting);
-
- if (tmp != win) {
- // Window order changed.
- setLayoutNeeded();
- break;
- }
- }
- if (tmpNdx != winNdx) {
- // One list was different from the other.
- setLayoutNeeded();
- }
- mTmpWindows.clear();
+ void layoutAndAssignWindowLayersIfNeeded() {
+ mService.mWindowsChanged = true;
+ setLayoutNeeded();
if (!mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
false /*updateInputWindows*/)) {
@@ -1550,321 +1533,76 @@
mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
}
- void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) {
- final InputConsumerImpl navInputConsumer =
- mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_NAVIGATION, mDisplayId);
- final InputConsumerImpl pipInputConsumer =
- mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_PIP, mDisplayId);
- final InputConsumerImpl wallpaperInputConsumer =
- mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_WALLPAPER, mDisplayId);
- boolean addInputConsumerHandle = navInputConsumer != null;
- boolean addPipInputConsumerHandle = pipInputConsumer != null;
- boolean addWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
- final Rect pipTouchableBounds = addPipInputConsumerHandle ? new Rect() : null;
- boolean disableWallpaperTouchEvents = false;
-
- for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowState child = mWindows.get(winNdx);
- final InputChannel inputChannel = child.mInputChannel;
- final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
- if (inputChannel == null || inputWindowHandle == null || child.mRemoved
- || child.isAdjustedForMinimizedDock()) {
- // Skip this window because it cannot possibly receive input.
- continue;
- }
-
- if (addPipInputConsumerHandle
- && child.getStackId() == PINNED_STACK_ID
- && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) {
- // Update the bounds of the Pip input consumer to match the Pinned stack
- child.getStack().getBounds(pipTouchableBounds);
- pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
- inputMonitor.addInputWindowHandle(pipInputConsumer.mWindowHandle);
- addPipInputConsumerHandle = false;
- }
-
- if (addInputConsumerHandle
- && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
- inputMonitor.addInputWindowHandle(navInputConsumer.mWindowHandle);
- addInputConsumerHandle = false;
- }
-
- if (addWallpaperInputConsumerHandle) {
- if (child.mAttrs.type == TYPE_WALLPAPER && child.isVisibleLw()) {
- // Add the wallpaper input consumer above the first visible wallpaper.
- inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
- addWallpaperInputConsumerHandle = false;
- }
- }
-
- final int flags = child.mAttrs.flags;
- final int privateFlags = child.mAttrs.privateFlags;
- final int type = child.mAttrs.type;
-
- final boolean hasFocus = child == inputFocus;
- final boolean isVisible = child.isVisibleLw();
- if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
- disableWallpaperTouchEvents = true;
- }
- final boolean hasWallpaper = mWallpaperController.isWallpaperTarget(child)
- && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0
- && !disableWallpaperTouchEvents;
-
- // If there's a drag in progress and 'child' is a potential drop target,
- // make sure it's been told about the drag
- if (inDrag && isVisible && isDefaultDisplay) {
- mService.mDragState.sendDragStartedIfNeededLw(child);
- }
-
- inputMonitor.addInputWindowHandle(
- inputWindowHandle, child, flags, type, isVisible, hasFocus, hasWallpaper);
- }
-
- if (addWallpaperInputConsumerHandle) {
- // No visible wallpaper found, add the wallpaper input consumer at the end.
- inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
- }
- }
-
/** Returns true if a leaked surface was destroyed */
boolean destroyLeakedSurfaces() {
- boolean leakedSurface = false;
- final int numWindows = mWindows.size();
- for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
- final WindowState ws = mWindows.get(winNdx);
- final WindowStateAnimator wsa = ws.mWinAnimator;
+ // Used to indicate that a surface was leaked.
+ mTmpWindow = null;
+ forAllWindows(w -> {
+ final WindowStateAnimator wsa = w.mWinAnimator;
if (wsa.mSurfaceController == null) {
- continue;
+ return;
}
if (!mService.mSessions.contains(wsa.mSession)) {
Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
- + ws + " surface=" + wsa.mSurfaceController
- + " token=" + ws.mToken
- + " pid=" + ws.mSession.mPid
- + " uid=" + ws.mSession.mUid);
+ + w + " surface=" + wsa.mSurfaceController
+ + " token=" + w.mToken
+ + " pid=" + w.mSession.mPid
+ + " uid=" + w.mSession.mUid);
wsa.destroySurface();
- mService.mForceRemoves.add(ws);
- leakedSurface = true;
- } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
+ mService.mForceRemoves.add(w);
+ mTmpWindow = w;
+ } else if (w.mAppToken != null && w.mAppToken.clientHidden) {
Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
- + ws + " surface=" + wsa.mSurfaceController
- + " token=" + ws.mAppToken
- + " saved=" + ws.hasSavedSurface());
- if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
+ + w + " surface=" + wsa.mSurfaceController
+ + " token=" + w.mAppToken
+ + " saved=" + w.hasSavedSurface());
+ if (SHOW_TRANSACTIONS) logSurface(w, "LEAK DESTROY", false);
wsa.destroySurface();
- leakedSurface = true;
+ mTmpWindow = w;
}
- }
+ }, false /* traverseTopToBottom */);
- return leakedSurface;
- }
-
- /** Return the list of Windows on this display associated with the input token. */
- WindowList getTokenWindowsOnDisplay(WindowToken token) {
- final WindowList windowList = new WindowList();
- final int count = mWindows.size();
- for (int i = 0; i < count; i++) {
- final WindowState win = mWindows.get(i);
- if (win.mToken == token) {
- windowList.add(win);
- }
- }
- return windowList;
- }
-
- private void reAddToWindowList(WindowState win) {
- win.mToken.addWindow(win);
- // This is a hack to get all of the child windows added as well at the right position. Child
- // windows should be rare and this case should be rare, so it shouldn't be that big a deal.
- int wpos = mWindows.indexOf(win);
- if (wpos >= 0) {
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "ReAdd removing from " + wpos + ": " + win);
- mWindows.remove(wpos);
- mService.mWindowsChanged = true;
- win.reAddWindow(wpos);
- }
- }
-
- void moveInputMethodDialogs(int pos) {
- ArrayList<WindowState> dialogs = mService.mInputMethodDialogs;
-
- final int N = dialogs.size();
- if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Removing " + N + " dialogs w/pos=" + pos);
- for (int i = 0; i < N; i++) {
- pos = removeWindowAndChildrenFromWindowList(dialogs.get(i), pos);
- }
- if (DEBUG_INPUT_METHOD) {
- Slog.v(TAG_WM, "Window list w/pos=" + pos);
- logWindowList(mWindows, " ");
- }
-
- WindowState ime = mService.mInputMethodWindow;
- if (pos >= 0) {
- // Skip windows owned by the input method.
- if (ime != null) {
- while (pos < mWindows.size()) {
- WindowState wp = mWindows.get(pos);
- if (wp == ime || wp.getParentWindow() == ime) {
- pos++;
- continue;
- }
- break;
- }
- }
- if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Adding " + N + " dialogs at pos=" + pos);
- for (int i=0; i<N; i++) {
- WindowState win = dialogs.get(i);
- pos = win.reAddWindow(pos);
- }
- if (DEBUG_INPUT_METHOD) {
- Slog.v(TAG_WM, "Final window list:");
- logWindowList(mWindows, " ");
- }
- return;
- }
- for (int i=0; i<N; i++) {
- WindowState win = dialogs.get(i);
- reAddToWindowList(win);
- if (DEBUG_INPUT_METHOD) {
- Slog.v(TAG_WM, "No IM target, final list:");
- logWindowList(mWindows, " ");
- }
- }
- }
-
- boolean moveInputMethodWindowsIfNeeded(boolean needAssignLayers) {
- final WindowState imWin = mService.mInputMethodWindow;
- final int DN = mService.mInputMethodDialogs.size();
- if (imWin == null && DN == 0) {
- return false;
- }
-
- // TODO(multidisplay): IMEs are only supported on the default display.
- int imPos = findDesiredInputMethodWindowIndex(true);
- if (imPos >= 0) {
- // In this case, the input method windows are to be placed
- // immediately above the window they are targeting.
-
- // First check to see if the input method windows are already
- // located here, and contiguous.
- final int N = mWindows.size();
- final WindowState firstImWin = imPos < N ? mWindows.get(imPos) : null;
-
- // Figure out the actual input method window that should be
- // at the bottom of their stack.
- WindowState baseImWin = imWin != null ? imWin : mService.mInputMethodDialogs.get(0);
- final WindowState cw = baseImWin.getBottomChild();
- if (cw != null && cw.mSubLayer < 0) {
- baseImWin = cw;
- }
-
- if (firstImWin == baseImWin) {
- // The windows haven't moved... but are they still contiguous?
- // First find the top IM window.
- int pos = imPos+1;
- while (pos < N) {
- if (!(mWindows.get(pos)).mIsImWindow) {
- break;
- }
- pos++;
- }
- pos++;
- // Now there should be no more input method windows above.
- while (pos < N) {
- if ((mWindows.get(pos)).mIsImWindow) {
- break;
- }
- pos++;
- }
- if (pos >= N) {
- return false;
- }
- }
-
- if (imWin != null) {
- if (DEBUG_INPUT_METHOD) {
- Slog.v(TAG_WM, "Moving IM from " + imPos);
- logWindowList(mWindows, " ");
- }
- imPos = removeWindowAndChildrenFromWindowList(imWin, imPos);
- if (DEBUG_INPUT_METHOD) {
- Slog.v(TAG_WM, "List after removing with new pos " + imPos + ":");
- logWindowList(mWindows, " ");
- }
- imWin.reAddWindow(imPos);
- if (DEBUG_INPUT_METHOD) {
- Slog.v(TAG_WM, "List after moving IM to " + imPos + ":");
- logWindowList(mWindows, " ");
- }
- if (DN > 0) moveInputMethodDialogs(imPos+1);
- } else {
- moveInputMethodDialogs(imPos);
- }
-
- } else {
- // In this case, the input method windows go in a fixed layer,
- // because they aren't currently associated with a focus window.
-
- if (imWin != null) {
- if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Moving IM from " + imPos);
- removeWindowAndChildrenFromWindowList(imWin, 0);
- reAddToWindowList(imWin);
- if (DEBUG_INPUT_METHOD) {
- Slog.v(TAG_WM, "List with no IM target:");
- logWindowList(mWindows, " ");
- }
- if (DN > 0) moveInputMethodDialogs(-1);
- } else {
- moveInputMethodDialogs(-1);
- }
-
- }
-
- if (needAssignLayers) {
- assignWindowLayers(false /* setLayoutNeeded */);
- }
-
- return true;
+ return mTmpWindow != null;
}
/**
- * Dig through the WindowStates and find the one that the Input Method will target.
- * @param willMove
- * @return The index+1 in mWindows of the discovered target.
+ * Determine and return the window that should be the IME target.
+ * @param updateImeTarget If true the system IME target will be updated to match what we found.
+ * @return The window that should be used as the IME target or null if there isn't any.
*/
- int findDesiredInputMethodWindowIndex(boolean willMove) {
+ WindowState computeImeTarget(boolean updateImeTarget) {
+ if (mService.mInputMethodWindow == null) {
+ // There isn't an IME so there shouldn't be a target...That was easy!
+ if (updateImeTarget) {
+ if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from "
+ + mService.mInputMethodTarget + " to null since mInputMethodWindow is null");
+ setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim, 0);
+ }
+ return null;
+ }
+
// TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
// same display. Or even when the current IME/target are not on the same screen as the next
// IME/target. For now only look for input windows on the main screen.
- WindowState w = null;
- int i;
- for (i = mWindows.size() - 1; i >= 0; --i) {
- final WindowState win = mWindows.get(i);
+ mUpdateImeTarget = updateImeTarget;
+ WindowState target = getWindow(mComputeImeTargetPredicate);
- if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG_WM, "Checking window @" + i
- + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
- if (canBeImeTarget(win)) {
- w = win;
- //Slog.i(TAG_WM, "Putting input method here!");
- // Yet more tricksyness! If this window is a "starting" window, we do actually want
- // to be on top of it, but it is not -really- where input will go. So if the caller
- // is not actually looking to move the IME, look down below for a real window to
- // target...
- if (!willMove && w.mAttrs.type == TYPE_APPLICATION_STARTING && i > 0) {
- final WindowState wb = mWindows.get(i-1);
- if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
- i--;
- w = wb;
- }
+ // Yet more tricksyness! If this window is a "starting" window, we do actually want
+ // to be on top of it, but it is not -really- where input will go. So look down below
+ // for a real window to target...
+ if (target != null && target.mAttrs.type == TYPE_APPLICATION_STARTING) {
+ final AppWindowToken token = target.mAppToken;
+ if (token != null) {
+ final WindowState betterTarget = token.getImeTargetBelowWindow(target);
+ if (betterTarget != null) {
+ target = betterTarget;
}
- break;
}
}
- // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
-
- if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG_WM, "Proposed new IME target: " + w);
+ if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM,
+ "Proposed new IME target: " + target);
// Now, a special case -- if the last target's window is in the process of exiting, and is
// above the new target, keep on the last target to avoid flicker. Consider for example a
@@ -1872,18 +1610,28 @@
// until it is completely gone so it doesn't drop behind the dialog or its full-screen
// scrim.
final WindowState curTarget = mService.mInputMethodTarget;
- if (curTarget != null
- && curTarget.isDisplayedLw()
- && curTarget.isClosing()
- && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
+ if (curTarget != null && curTarget.isDisplayedLw() && curTarget.isClosing()
+ && (target == null
+ || curTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer)) {
if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing");
- return mWindows.indexOf(curTarget) + 1;
+ return curTarget;
}
- if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target="
- + w + " willMove=" + willMove);
+ if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" + target
+ + " updateImeTarget=" + updateImeTarget);
- if (willMove && w != null) {
+ if (target == null) {
+ if (updateImeTarget) {
+ if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
+ + " to null." + (SHOW_STACK_CRAWLS ? " Callers="
+ + Debug.getCallers(4) : ""));
+ setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim, 0);
+ }
+
+ return null;
+ }
+
+ if (updateImeTarget) {
AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
if (token != null) {
@@ -1891,24 +1639,8 @@
// to look at all windows below the current target that are in this app, finding the
// highest visible one in layering.
WindowState highestTarget = null;
- int highestPos = 0;
if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
- WindowList curWindows = token.getDisplayContent().mWindows;
- int pos = curWindows.indexOf(curTarget);
- while (pos >= 0) {
- WindowState win = curWindows.get(pos);
- if (win.mAppToken != token) {
- break;
- }
- if (!win.mRemoved) {
- if (highestTarget == null || win.mWinAnimator.mAnimLayer >
- highestTarget.mWinAnimator.mAnimLayer) {
- highestTarget = win;
- highestPos = pos;
- }
- }
- pos--;
- }
+ highestTarget = token.getHighestAnimLayerWindow(curTarget);
}
if (highestTarget != null) {
@@ -1916,121 +1648,76 @@
if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, appTransition + " " + highestTarget
+ " animating=" + highestTarget.mWinAnimator.isAnimationSet()
+ " layer=" + highestTarget.mWinAnimator.mAnimLayer
- + " new layer=" + w.mWinAnimator.mAnimLayer);
+ + " new layer=" + target.mWinAnimator.mAnimLayer);
if (appTransition.isTransitionSet()) {
// If we are currently setting up for an animation, hold everything until we
// can find out what will happen.
- mService.mInputMethodTargetWaitingAnim = true;
- mService.mInputMethodTarget = highestTarget;
- return highestPos + 1;
+ setInputMethodTarget(highestTarget, true, mInputMethodAnimLayerAdjustment);
+ return highestTarget;
} else if (highestTarget.mWinAnimator.isAnimationSet() &&
- highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
+ highestTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer) {
// If the window we are currently targeting is involved with an animation,
// and it is on top of the next target we will be over, then hold off on
// moving until that is done.
- mService.mInputMethodTargetWaitingAnim = true;
- mService.mInputMethodTarget = highestTarget;
- return highestPos + 1;
+ setInputMethodTarget(highestTarget, true, mInputMethodAnimLayerAdjustment);
+ return highestTarget;
}
}
}
+
+ if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
+ + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
+ setInputMethodTarget(target, false, target.mAppToken != null
+ ? target.mAppToken.mAppAnimator.animLayerAdjustment : 0);
}
- //Slog.i(TAG_WM, "Placing input method @" + (i+1));
- if (w != null) {
- if (willMove) {
- if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
- + w + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
- mService.mInputMethodTarget = w;
- mService.mInputMethodTargetWaitingAnim = false;
- if (w.mAppToken != null) {
- setInputMethodAnimLayerAdjustment(
- w.mAppToken.mAppAnimator.animLayerAdjustment);
- } else {
- setInputMethodAnimLayerAdjustment(0);
- }
- }
-
- // If the docked divider is visible, we still need to go through this whole excercise to
- // find the appropriate input method target (used for animations and dialog
- // adjustments), but for purposes of Z ordering we simply wish to place it above the
- // docked divider. Unless it is already above the divider.
- final WindowState dockedDivider = mDividerControllerLocked.getWindow();
- if (dockedDivider != null && dockedDivider.isVisibleLw()) {
- int dividerIndex = mWindows.indexOf(dockedDivider);
- if (dividerIndex > 0 && dividerIndex > i) {
- return dividerIndex + 1;
- }
- }
- return i+1;
- }
- if (willMove) {
- if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
- + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
- mService.mInputMethodTarget = null;
- setInputMethodAnimLayerAdjustment(0);
- }
- return -1;
+ return target;
}
- private static boolean canBeImeTarget(WindowState w) {
- final int fl = w.mAttrs.flags & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
- final int type = w.mAttrs.type;
-
- if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)
- && type != TYPE_APPLICATION_STARTING) {
- return false;
+ private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim, int layerAdj) {
+ if (target == mService.mInputMethodTarget
+ && mService.mInputMethodTargetWaitingAnim == targetWaitingAnim
+ && mInputMethodAnimLayerAdjustment == layerAdj) {
+ return;
}
- if (DEBUG_INPUT_METHOD) {
- Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
- if (!w.isVisibleOrAdding()) {
- Slog.i(TAG_WM, " mSurfaceController=" + w.mWinAnimator.mSurfaceController
- + " relayoutCalled=" + w.mRelayoutCalled
- + " viewVis=" + w.mViewVisibility
- + " policyVis=" + w.mPolicyVisibility
- + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
- + " parentHidden=" + w.isParentWindowHidden()
- + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying);
- if (w.mAppToken != null) {
- Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
- }
+ mService.mInputMethodTarget = target;
+ mService.mInputMethodTargetWaitingAnim = targetWaitingAnim;
+ setInputMethodAnimLayerAdjustment(layerAdj);
+ assignWindowLayers(false /* setLayoutNeeded */);
+ }
+
+ boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) {
+ if (top.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
+ return top.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
+ }
+
+ // Used to indicate we have reached the first window in the range we are interested in.
+ mTmpWindow = null;
+
+ // TODO: Figure-out a more efficient way to do this.
+ final WindowState candidate = getWindow(w -> {
+ if (w == top) {
+ // Reached the first window in the range we are interested in.
+ mTmpWindow = w;
}
- }
- return w.isVisibleOrAdding();
- }
+ if (mTmpWindow == null) {
+ return false;
+ }
- private void logWindowList(final WindowList windows, String prefix) {
- int N = windows.size();
- while (N > 0) {
- N--;
- Slog.v(TAG_WM, prefix + "#" + N + ": " + windows.get(N));
- }
- }
-
- boolean getNeedsMenu(WindowState win, WindowManagerPolicy.WindowState bottom) {
- int index = -1;
- while (true) {
- if (win.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
- return win.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
+ if (w.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
+ return true;
}
// If we reached the bottom of the range of windows we are considering,
// assume no menu is needed.
- if (win == bottom) {
- return false;
+ if (w == bottom) {
+ return true;
}
- // The current window hasn't specified whether menu key is needed; look behind it.
- // First, we may need to determine the starting position.
- if (index < 0) {
- index = mWindows.indexOf(win);
- }
- index--;
- if (index < 0) {
- return false;
- }
- win = mWindows.get(index);
- }
+ return false;
+ });
+
+ return candidate != null && candidate.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
}
void setLayoutNeeded() {
@@ -2047,85 +1734,6 @@
return mLayoutNeeded;
}
- private void addAppWindowExisting(WindowState win, WindowList tokenWindowList) {
-
- // If this application has existing windows, we simply place the new window on top of
- // them... but keep the starting window on top.
- if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
- // Base windows go behind everything else.
- final WindowState lowestWindow = tokenWindowList.get(0);
- addWindowToListBefore(win, lowestWindow);
- } else {
- final AppWindowToken atoken = win.mAppToken;
- final int windowListPos = tokenWindowList.size();
- final WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
- if (atoken != null && lastWindow == atoken.startingWindow) {
- addWindowToListBefore(win, lastWindow);
- } else {
- int newIdx = findIdxBasedOnAppTokens(win);
- // There is a window above this one associated with the same apptoken note that the
- // window could be a floating window that was created later or a window at the top
- // of the list of windows associated with this token.
- if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of "
- + mWindows.size());
- mWindows.add(newIdx + 1, win);
- mService.mWindowsChanged = true;
- }
- }
- }
-
- /** Places the first input window after the second input window in the window list. */
- private void addWindowToListAfter(WindowState first, WindowState second) {
- final int i = mWindows.indexOf(second);
- if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "Adding window " + this + " at " + (i + 1) + " of " + mWindows.size()
- + " (after " + second + ")");
- mWindows.add(i + 1, first);
- mService.mWindowsChanged = true;
- }
-
- /** Places the first input window before the second input window in the window list. */
- private void addWindowToListBefore(WindowState first, WindowState second) {
- int i = mWindows.indexOf(second);
- if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "Adding window " + this + " at " + i + " of " + mWindows.size()
- + " (before " + second + ")");
- if (i < 0) {
- Slog.w(TAG_WM, "addWindowToListBefore: Unable to find " + second + " in " + mWindows);
- i = 0;
- }
- mWindows.add(i, first);
- mService.mWindowsChanged = true;
- }
-
- /**
- * This method finds out the index of a window that has the same app token as win. used for z
- * ordering the windows in mWindows
- */
- private int findIdxBasedOnAppTokens(WindowState win) {
- for(int j = mWindows.size() - 1; j >= 0; j--) {
- final WindowState wentry = mWindows.get(j);
- if(wentry.mAppToken == win.mAppToken) {
- return j;
- }
- }
- return -1;
- }
-
- private void dumpChildrenNames() {
- StringBuilder output = new StringBuilder();
- dumpChildrenNames(output, " ");
- Slog.v(TAG_WM, output.toString());
- }
-
- private void dumpWindows() {
- Slog.v(TAG_WM, " Display #" + mDisplayId);
- for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
- Slog.v(TAG_WM, " #" + winNdx + ": " + mWindows.get(winNdx));
- }
- }
-
void dumpTokens(PrintWriter pw, boolean dumpAll) {
if (mTokenMap.isEmpty()) {
return;
@@ -2146,25 +1754,24 @@
}
void dumpWindowAnimators(PrintWriter pw, String subPrefix) {
- final int count = mWindows.size();
- for (int j = 0; j < count; j++) {
- final WindowStateAnimator wAnim = mWindows.get(j).mWinAnimator;
- pw.println(subPrefix + "Window #" + j + ": " + wAnim);
- }
+ final int[] index = new int[1];
+ forAllWindows(w -> {
+ final WindowStateAnimator wAnim = w.mWinAnimator;
+ pw.println(subPrefix + "Window #" + index[0] + ": " + wAnim);
+ index[0] = index[0] + 1;
+ }, false /* traverseTopToBottom */);
}
void enableSurfaceTrace(FileDescriptor fd) {
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState win = mWindows.get(i);
- win.mWinAnimator.enableSurfaceTrace(fd);
- }
+ forAllWindows(w -> {
+ w.mWinAnimator.enableSurfaceTrace(fd);
+ }, true /* traverseTopToBottom */);
}
void disableSurfaceTrace() {
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState win = mWindows.get(i);
- win.mWinAnimator.disableSurfaceTrace();
- }
+ forAllWindows(w -> {
+ w.mWinAnimator.disableSurfaceTrace();
+ }, true /* traverseTopToBottom */);
}
/**
@@ -2172,63 +1779,68 @@
*/
void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade) {
final WindowManagerPolicy policy = mService.mPolicy;
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState window = mWindows.get(i);
- if (window.mAppToken == null && policy.canBeHiddenByKeyguardLw(window)) {
- window.mWinAnimator.setAnimation(
+ forAllWindows(w -> {
+ if (w.mAppToken == null && policy.canBeHiddenByKeyguardLw(w)) {
+ w.mWinAnimator.setAnimation(
policy.createHiddenByKeyguardExit(onWallpaper, goingToShade));
}
- }
+ }, true /* traverseTopToBottom */);
}
boolean checkWaitingForWindows() {
- boolean haveBootMsg = false;
- boolean haveApp = false;
- // if the wallpaper service is disabled on the device, we're never going to have
- // wallpaper, don't bother waiting for it
- boolean haveWallpaper = false;
- boolean wallpaperEnabled = mService.mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_enableWallpaperService)
- && !mService.mOnlyCore;
- boolean haveKeyguard = true;
- final int count = mWindows.size();
- for (int i = 0; i < count; i++) {
- final WindowState w = mWindows.get(i);
+ mHaveBootMsg = false;
+ mHaveApp = false;
+ mHaveWallpaper = false;
+ mHaveKeyguard = true;
+
+ final WindowState visibleWindow = getWindow(w -> {
if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
return true;
}
if (w.isDrawnLw()) {
if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
- haveBootMsg = true;
+ mHaveBootMsg = true;
} else if (w.mAttrs.type == TYPE_APPLICATION
|| w.mAttrs.type == TYPE_DRAWN_APPLICATION) {
- haveApp = true;
+ mHaveApp = true;
} else if (w.mAttrs.type == TYPE_WALLPAPER) {
- haveWallpaper = true;
+ mHaveWallpaper = true;
} else if (w.mAttrs.type == TYPE_STATUS_BAR) {
- haveKeyguard = mService.mPolicy.isKeyguardDrawnLw();
+ mHaveKeyguard = mService.mPolicy.isKeyguardDrawnLw();
}
}
+ return false;
+ });
+
+ if (visibleWindow != null) {
+ // We have a visible window.
+ return true;
}
+ // if the wallpaper service is disabled on the device, we're never going to have
+ // wallpaper, don't bother waiting for it
+ boolean wallpaperEnabled = mService.mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableWallpaperService)
+ && !mService.mOnlyCore;
+
if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM,
"******** booted=" + mService.mSystemBooted
+ " msg=" + mService.mShowingBootMessages
- + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
- + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
- + " haveKeyguard=" + haveKeyguard);
+ + " haveBoot=" + mHaveBootMsg + " haveApp=" + mHaveApp
+ + " haveWall=" + mHaveWallpaper + " wallEnabled=" + wallpaperEnabled
+ + " haveKeyguard=" + mHaveKeyguard);
// If we are turning on the screen to show the boot message, don't do it until the boot
// message is actually displayed.
- if (!mService.mSystemBooted && !haveBootMsg) {
+ if (!mService.mSystemBooted && !mHaveBootMsg) {
return true;
}
// If we are turning on the screen after the boot is completed normally, don't do so until
// we have the application and wallpaper.
- if (mService.mSystemBooted && ((!haveApp && !haveKeyguard) ||
- (wallpaperEnabled && !haveWallpaper))) {
+ if (mService.mSystemBooted
+ && ((!mHaveApp && !mHaveKeyguard) || (wallpaperEnabled && !mHaveWallpaper))) {
return true;
}
@@ -2236,152 +1848,41 @@
}
void updateWindowsForAnimator(WindowAnimator animator) {
- final WallpaperController wallpaperController = mWallpaperController;
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- WindowState win = mWindows.get(i);
- WindowStateAnimator winAnimator = win.mWinAnimator;
- if (winAnimator.hasSurface()) {
- final boolean wasAnimating = winAnimator.mWasAnimating;
- final boolean nowAnimating = winAnimator.stepAnimationLocked(animator.mCurrentTime);
- winAnimator.mWasAnimating = nowAnimating;
- animator.orAnimating(nowAnimating);
-
- if (DEBUG_WALLPAPER) Slog.v(TAG,
- win + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating);
-
- if (wasAnimating && !winAnimator.mAnimating
- && wallpaperController.isWallpaperTarget(win)) {
- animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
- pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
- if (DEBUG_LAYOUT_REPEATS) {
- mService.mWindowPlacerLocked.debugLayoutRepeats(
- "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges);
- }
- }
- }
-
- final AppWindowToken atoken = win.mAppToken;
- if (winAnimator.mDrawState == READY_TO_SHOW) {
- if (atoken == null || atoken.allDrawn) {
- if (win.performShowLocked()) {
- pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
- if (DEBUG_LAYOUT_REPEATS) {
- mService.mWindowPlacerLocked.debugLayoutRepeats(
- "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges);
- }
- }
- }
- }
- final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
- if (appAnimator != null && appAnimator.thumbnail != null) {
- if (appAnimator.thumbnailTransactionSeq != animator.mAnimTransactionSequence) {
- appAnimator.thumbnailTransactionSeq = animator.mAnimTransactionSequence;
- appAnimator.thumbnailLayer = 0;
- }
- if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
- appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
- }
- }
- } // end forall windows
+ mTmpWindowAnimator = animator;
+ forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */);
}
void updateWallpaperForAnimator(WindowAnimator animator) {
resetAnimationBackgroundAnimator();
- final WindowList windows = mWindows;
- WindowState detachedWallpaper = null;
+ // Used to indicate a detached wallpaper.
+ mTmpWindow = null;
+ mTmpWindowAnimator = animator;
- for (int i = windows.size() - 1; i >= 0; i--) {
- final WindowState win = windows.get(i);
- final WindowStateAnimator winAnimator = win.mWinAnimator;
- if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
- continue;
- }
+ forAllWindows(mUpdateWallpaperForAnimator, true /* traverseTopToBottom */);
- final int flags = win.mAttrs.flags;
-
- // If this window is animating, make a note that we have an animating window and take
- // care of a request to run a detached wallpaper animation.
- if (winAnimator.mAnimating) {
- if (winAnimator.mAnimation != null) {
- if ((flags & FLAG_SHOW_WALLPAPER) != 0
- && winAnimator.mAnimation.getDetachWallpaper()) {
- detachedWallpaper = win;
- }
- final int color = winAnimator.mAnimation.getBackgroundColor();
- if (color != 0) {
- final TaskStack stack = win.getStack();
- if (stack != null) {
- stack.setAnimationBackground(winAnimator, color);
- }
- }
- }
- animator.setAnimating(true);
- }
-
- // If this window's app token is running a detached wallpaper animation, make a note so
- // we can ensure the wallpaper is displayed behind it.
- final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
- if (appAnimator != null && appAnimator.animation != null
- && appAnimator.animating) {
- if ((flags & FLAG_SHOW_WALLPAPER) != 0
- && appAnimator.animation.getDetachWallpaper()) {
- detachedWallpaper = win;
- }
-
- final int color = appAnimator.animation.getBackgroundColor();
- if (color != 0) {
- final TaskStack stack = win.getStack();
- if (stack != null) {
- stack.setAnimationBackground(winAnimator, color);
- }
- }
- }
- } // end forall windows
-
- if (animator.mWindowDetachedWallpaper != detachedWallpaper) {
+ if (animator.mWindowDetachedWallpaper != mTmpWindow) {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Detached wallpaper changed from "
- + animator.mWindowDetachedWallpaper + " to " + detachedWallpaper);
- animator.mWindowDetachedWallpaper = detachedWallpaper;
+ + animator.mWindowDetachedWallpaper + " to " + mTmpWindow);
+ animator.mWindowDetachedWallpaper = mTmpWindow;
animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
}
}
void prepareWindowSurfaces() {
- final int count = mWindows.size();
- for (int j = 0; j < count; j++) {
- mWindows.get(j).mWinAnimator.prepareSurfaceLocked(true);
- }
+ forAllWindows(mPrepareWindowSurfaces, false /* traverseTopToBottom */);
}
boolean inputMethodClientHasFocus(IInputMethodClient client) {
- // The focus for the client is the window immediately below where we would place the input
- // method window.
- int idx = findDesiredInputMethodWindowIndex(false);
- if (idx <= 0) {
- return false;
- }
-
- WindowState imFocus = mWindows.get(idx - 1);
- if (DEBUG_INPUT_METHOD) {
- Slog.i(TAG_WM, "Desired input method target: " + imFocus);
- Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus);
- Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus);
- }
-
+ final WindowState imFocus = computeImeTarget(false /* updateImeTarget */);
if (imFocus == null) {
return false;
}
- // This may be a starting window, in which case we still want to count it as okay.
- if (imFocus.mAttrs.type == TYPE_APPLICATION_STARTING && imFocus.mAppToken != null) {
- // The client has definitely started, so it really should have a window in this app
- // token. Let's look for it.
- final WindowState w = imFocus.mAppToken.getFirstNonStartingWindow();
- if (w != null) {
- if (DEBUG_INPUT_METHOD) Slog.i(TAG_WM, "Switching to real app window: " + w);
- imFocus = w;
- }
+ if (DEBUG_INPUT_METHOD) {
+ Slog.i(TAG_WM, "Desired input method target: " + imFocus);
+ Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus);
+ Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus);
}
final IInputMethodClient imeClient = imFocus.mSession.mClient;
@@ -2398,75 +1899,63 @@
}
boolean hasSecureWindowOnScreen() {
- for (int i = mWindows.size() - 1; i >= 0; --i) {
- final WindowState ws = mWindows.get(i);
- if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
- return true;
- }
- }
- return false;
+ final WindowState win = getWindow(
+ w -> w.isOnScreen() && (w.mAttrs.flags & FLAG_SECURE) != 0);
+ return win != null;
}
void updateSystemUiVisibility(int visibility, int globalDiff) {
- for (int i = mWindows.size() - 1; i >= 0; --i) {
- final WindowState ws = mWindows.get(i);
+ forAllWindows(w -> {
try {
- int curValue = ws.mSystemUiVisibility;
- int diff = (curValue ^ visibility) & globalDiff;
- int newValue = (curValue & ~diff) | (visibility & diff);
+ final int curValue = w.mSystemUiVisibility;
+ final int diff = (curValue ^ visibility) & globalDiff;
+ final int newValue = (curValue & ~diff) | (visibility & diff);
if (newValue != curValue) {
- ws.mSeq++;
- ws.mSystemUiVisibility = newValue;
+ w.mSeq++;
+ w.mSystemUiVisibility = newValue;
}
- if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
- ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
+ if (newValue != curValue || w.mAttrs.hasSystemUiListeners) {
+ w.mClient.dispatchSystemUiVisibilityChanged(w.mSeq,
visibility, newValue, diff);
}
} catch (RemoteException e) {
// so sorry
}
- }
+ }, true /* traverseTopToBottom */);
}
void onWindowFreezeTimeout() {
Slog.w(TAG_WM, "Window freeze timeout expired.");
mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
- for (int i = mWindows.size() - 1; i >= 0; --i) {
- final WindowState w = mWindows.get(i);
+
+ forAllWindows(w -> {
if (!w.mOrientationChanging) {
- continue;
+ return;
}
w.mOrientationChanging = false;
w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
- mService.mDisplayFreezeTime);
Slog.w(TAG_WM, "Force clearing orientation change: " + w);
- }
+ }, true /* traverseTopToBottom */);
mService.mWindowPlacerLocked.performSurfacePlacement();
}
void waitForAllWindowsDrawn() {
final WindowManagerPolicy policy = mService.mPolicy;
- for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
- final WindowState win = mWindows.get(winNdx);
- final boolean keyguard = policy.isKeyguardHostWindow(win.mAttrs);
- if (win.isVisibleLw() && (win.mAppToken != null || keyguard)) {
- win.mWinAnimator.mDrawState = DRAW_PENDING;
+ forAllWindows(w -> {
+ final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
+ if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
+ w.mWinAnimator.mDrawState = DRAW_PENDING;
// Force add to mResizingWindows.
- win.mLastContentInsets.set(-1, -1, -1, -1);
- mService.mWaitingForDrawn.add(win);
+ w.mLastContentInsets.set(-1, -1, -1, -1);
+ mService.mWaitingForDrawn.add(w);
}
- }
+ }, true /* traverseTopToBottom */);
}
// TODO: Super crazy long method that should be broken down...
boolean applySurfaceChangesTransaction(boolean recoveringMemory) {
- boolean focusDisplayed = false;
- boolean displayHasContent = false;
- float preferredRefreshRate = 0;
- int preferredModeId = 0;
-
-
final int dw = mDisplayInfo.logicalWidth;
final int dh = mDisplayInfo.logicalHeight;
final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
@@ -2490,7 +1979,7 @@
// Remove check for default display when there will be support for multiple wallpaper
// targets (on different displays).
if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
- adjustWallpaperWindows();
+ mWallpaperController.adjustWallpaperWindows(this);
}
if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
@@ -2517,137 +2006,23 @@
if (isDefaultDisplay) {
mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState w = mWindows.get(i);
- mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
- mService.mInputMethodTarget);
- }
+ forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw();
if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
"after finishPostLayoutPolicyLw", pendingLayoutChanges);
}
} while (pendingLayoutChanges != 0);
- RootWindowContainer root = mService.mRoot;
- boolean obscured = false;
- boolean syswin = false;
+ mTmpApplySurfaceChangesTransactionState.reset();
resetDimming();
- // Only used if default window
- final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
-
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState w = mWindows.get(i);
- final Task task = w.getTask();
- final boolean obscuredChanged = w.mObscured != obscured;
-
- // Update effect.
- w.mObscured = obscured;
- if (!obscured) {
- final boolean isDisplayed = w.isDisplayedLw();
-
- if (isDisplayed && w.isObscuringFullscreen(mDisplayInfo)) {
- // This window completely covers everything behind it, so we want to leave all
- // of them as undimmed (for performance reasons).
- root.mObscuringWindow = w;
- obscured = true;
- }
-
- displayHasContent |= root.handleNotObscuredLocked(w, obscured, syswin);
-
- if (w.mHasSurface && isDisplayed) {
- final int type = w.mAttrs.type;
- if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
- || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
- syswin = true;
- }
- if (preferredRefreshRate == 0 && w.mAttrs.preferredRefreshRate != 0) {
- preferredRefreshRate = w.mAttrs.preferredRefreshRate;
- }
- if (preferredModeId == 0 && w.mAttrs.preferredDisplayModeId != 0) {
- preferredModeId = w.mAttrs.preferredDisplayModeId;
- }
- }
- }
-
- w.applyDimLayerIfNeeded();
-
- if (isDefaultDisplay && obscuredChanged && w.isVisibleLw()
- && mWallpaperController.isWallpaperTarget(w)) {
- // This is the wallpaper target and its obscured state changed... make sure the
- // current wallpaper's visibility has been updated accordingly.
- mWallpaperController.updateWallpaperVisibility();
- }
-
- w.handleWindowMovedIfNeeded();
-
- final WindowStateAnimator winAnimator = w.mWinAnimator;
-
- //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
- w.mContentChanged = false;
-
- // Moved from updateWindowsAndWallpaperLocked().
- if (w.mHasSurface) {
- // Take care of the window being ready to display.
- final boolean committed = winAnimator.commitFinishDrawingLocked();
- if (isDefaultDisplay && committed) {
- if (w.mAttrs.type == TYPE_DREAM) {
- // HACK: When a dream is shown, it may at that point hide the lock screen.
- // So we need to redo the layout to let the phone window manager make this
- // happen.
- pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
- if (DEBUG_LAYOUT_REPEATS) {
- surfacePlacer.debugLayoutRepeats(
- "dream and commitFinishDrawingLocked true",
- pendingLayoutChanges);
- }
- }
- if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
- if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
- "First draw done in potential wallpaper target " + w);
- root.mWallpaperMayChange = true;
- pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
- if (DEBUG_LAYOUT_REPEATS) {
- surfacePlacer.debugLayoutRepeats(
- "wallpaper and commitFinishDrawingLocked true",
- pendingLayoutChanges);
- }
- }
- }
- if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
- // Updates the shown frame before we set up the surface. This is needed
- // because the resizing could change the top-left position (in addition to
- // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
- // position the surface.
- //
- // If an animation is being started, we can't call this method because the
- // animation hasn't processed its initial transformation yet, but in general
- // we do want to update the position if the window is animating.
- winAnimator.computeShownFrameLocked();
- }
- winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
- }
-
- final AppWindowToken atoken = w.mAppToken;
- if (atoken != null) {
- final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
- if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
- mTmpUpdateAllDrawn.add(atoken);
- }
- }
-
- if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
- && w.isDisplayedLw()) {
- focusDisplayed = true;
- }
-
- w.updateResizingWindowIfNeeded();
- }
+ mTmpRecoveringMemory = recoveringMemory;
+ forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
mService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
- displayHasContent,
- preferredRefreshRate,
- preferredModeId,
+ mTmpApplySurfaceChangesTransactionState.displayHasContent,
+ mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
+ mTmpApplySurfaceChangesTransactionState.preferredModeId,
true /* inTraversal, must call performTraversalInTrans... below */);
stopDimmingIfNeeded();
@@ -2659,7 +2034,7 @@
atoken.updateAllDrawn(this);
}
- return focusDisplayed;
+ return mTmpApplySurfaceChangesTransactionState.focusDisplayed;
}
void performLayout(boolean initial, boolean updateInputWindows) {
@@ -2671,8 +2046,6 @@
final int dw = mDisplayInfo.logicalWidth;
final int dh = mDisplayInfo.logicalHeight;
- int i;
-
if (DEBUG_LAYOUT) {
Slog.v(TAG, "-------------------------------------");
Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw + " dh=" + dh);
@@ -2692,110 +2065,23 @@
if (seq < 0) seq = 0;
mService.mLayoutSeq = seq;
- boolean behindDream = false;
+ // Used to indicate that we have processed the dream window and all additional windows are
+ // behind it.
+ mTmpWindow = null;
+ mTmpInitial = initial;
// First perform layout of any root windows (not attached to another window).
- int topAttached = -1;
- for (i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState win = mWindows.get(i);
+ forAllWindows(mPerformLayout, true /* traverseTopToBottom */);
- // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
- // wasting time and funky changes while a window is animating away.
- final boolean gone = (behindDream && mService.mPolicy.canBeHiddenByKeyguardLw(win))
- || win.isGoneForLayoutLw();
-
- if (DEBUG_LAYOUT && !win.mLayoutAttached) {
- Slog.v(TAG, "1ST PASS " + win + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
- + " mLayoutAttached=" + win.mLayoutAttached
- + " screen changed=" + win.isConfigChanged());
- final AppWindowToken atoken = win.mAppToken;
- if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + win.mViewVisibility
- + " mRelayoutCalled=" + win.mRelayoutCalled + " hidden=" + win.mToken.hidden
- + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
- + " parentHidden=" + win.isParentWindowHidden());
- else Slog.v(TAG, " VIS: mViewVisibility=" + win.mViewVisibility
- + " mRelayoutCalled=" + win.mRelayoutCalled + " hidden=" + win.mToken.hidden
- + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
- + " parentHidden=" + win.isParentWindowHidden());
- }
-
- // If this view is GONE, then skip it -- keep the current frame, and let the caller know
- // so they can ignore it if they want. (We do the normal layout for INVISIBLE windows,
- // since that means "perform layout as normal, just don't display").
- if (!gone || !win.mHaveFrame || win.mLayoutNeeded
- || ((win.isConfigChanged() || win.setReportResizeHints())
- && !win.isGoneForLayoutLw() &&
- ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
- (win.mHasSurface && win.mAppToken != null &&
- win.mAppToken.layoutConfigChanges)))) {
- if (!win.mLayoutAttached) {
- if (initial) {
- //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
- win.mContentChanged = false;
- }
- if (win.mAttrs.type == TYPE_DREAM) {
- // Don't layout windows behind a dream, so that if it does stuff like hide
- // the status bar we won't get a bad transition when it goes away.
- behindDream = true;
- }
- win.mLayoutNeeded = false;
- win.prelayout();
- mService.mPolicy.layoutWindowLw(win, null);
- win.mLayoutSeq = seq;
-
- // Window frames may have changed. Update dim layer with the new bounds.
- final Task task = win.getTask();
- if (task != null) {
- mDimLayerController.updateDimLayer(task);
- }
-
- if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + win.mFrame
- + " mContainingFrame=" + win.mContainingFrame
- + " mDisplayFrame=" + win.mDisplayFrame);
- } else {
- if (topAttached < 0) topAttached = i;
- }
- }
- }
-
- boolean attachedBehindDream = false;
+ // Used to indicate that we have processed the dream window and all additional attached
+ // windows are behind it.
+ mTmpWindow2 = mTmpWindow;
+ mTmpWindow = null;
// Now perform layout of attached windows, which usually depend on the position of the
// window they are attached to. XXX does not deal with windows that are attached to windows
// that are themselves attached.
- for (i = topAttached; i >= 0; i--) {
- final WindowState win = mWindows.get(i);
-
- if (win.mLayoutAttached) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win + " mHaveFrame=" + win.mHaveFrame
- + " mViewVisibility=" + win.mViewVisibility
- + " mRelayoutCalled=" + win.mRelayoutCalled);
- // If this view is GONE, then skip it -- keep the current frame, and let the caller
- // know so they can ignore it if they want. (We do the normal layout for INVISIBLE
- // windows, since that means "perform layout as normal, just don't display").
- if (attachedBehindDream && mService.mPolicy.canBeHiddenByKeyguardLw(win)) {
- continue;
- }
- if ((win.mViewVisibility != GONE && win.mRelayoutCalled) || !win.mHaveFrame
- || win.mLayoutNeeded) {
- if (initial) {
- //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
- win.mContentChanged = false;
- }
- win.mLayoutNeeded = false;
- win.prelayout();
- mService.mPolicy.layoutWindowLw(win, win.getParentWindow());
- win.mLayoutSeq = seq;
- if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + win.mFrame
- + " mContainingFrame=" + win.mContainingFrame
- + " mDisplayFrame=" + win.mDisplayFrame);
- }
- } else if (win.mAttrs.type == TYPE_DREAM) {
- // Don't layout windows behind a dream, so that if it does stuff like hide the
- // status bar we won't get a bad transition when it goes away.
- attachedBehindDream = behindDream;
- }
- }
+ forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */);
// Window frames may have changed. Tell the input dispatcher about it.
mService.mInputMonitor.layoutInputConsumers(dw, dh);
@@ -2819,7 +2105,7 @@
* @param config of the output bitmap
* @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
*/
- Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height,
+ Bitmap screenshotApplications(IBinder appToken, int width, int height,
boolean includeFullDisplay, float frameScale, Bitmap.Config config,
boolean wallpaperOnly) {
int dw = mDisplayInfo.logicalWidth;
@@ -2832,22 +2118,10 @@
Bitmap bm = null;
- int maxLayer = 0;
+ mScreenshotApplicationState.reset(appToken == null && !wallpaperOnly);
final Rect frame = new Rect();
final Rect stackBounds = new Rect();
- boolean screenshotReady;
- int minLayer;
- if (appToken == null && !wallpaperOnly) {
- screenshotReady = true;
- minLayer = 0;
- } else {
- screenshotReady = false;
- minLayer = Integer.MAX_VALUE;
- }
-
- WindowState appWin = null;
-
boolean includeImeInScreenshot;
synchronized(mService.mWindowMap) {
final AppWindowToken imeTargetAppToken = mService.mInputMethodTarget != null
@@ -2868,70 +2142,69 @@
synchronized(mService.mWindowMap) {
// Figure out the part of the screen that is actually the app.
- appWin = null;
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState ws = mWindows.get(i);
- if (!ws.mHasSurface) {
- continue;
+ mScreenshotApplicationState.appWin = null;
+ forAllWindows(w -> {
+ if (!w.mHasSurface) {
+ return false;
}
- if (ws.mLayer >= aboveAppLayer) {
- continue;
+ if (w.mLayer >= aboveAppLayer) {
+ return false;
}
- if (wallpaperOnly && !ws.mIsWallpaper) {
- continue;
+ if (wallpaperOnly && !w.mIsWallpaper) {
+ return false;
}
- if (ws.mIsImWindow) {
+ if (w.mIsImWindow) {
if (!includeImeInScreenshot) {
- continue;
+ return false;
}
- } else if (ws.mIsWallpaper) {
+ } else if (w.mIsWallpaper) {
// If this is the wallpaper layer and we're only looking for the wallpaper layer
// then the target window state is this one.
if (wallpaperOnly) {
- appWin = ws;
+ mScreenshotApplicationState.appWin = w;
}
- if (appWin == null) {
+ if (mScreenshotApplicationState.appWin == null) {
// We have not ran across the target window yet, so it is probably behind
// the wallpaper. This can happen when the keyguard is up and all windows
// are moved behind the wallpaper. We don't want to include the wallpaper
// layer in the screenshot as it will cover-up the layer of the target
// window.
- continue;
+ return false;
}
// Fall through. The target window is in front of the wallpaper. For this
// case we want to include the wallpaper layer in the screenshot because
// the target window might have some transparent areas.
} else if (appToken != null) {
- if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
+ if (w.mAppToken == null || w.mAppToken.token != appToken) {
// This app window is of no interest if it is not associated with the
// screenshot app.
- continue;
+ return false;
}
- appWin = ws;
+ mScreenshotApplicationState.appWin = w;
}
// Include this window.
- final WindowStateAnimator winAnim = ws.mWinAnimator;
+ final WindowStateAnimator winAnim = w.mWinAnimator;
int layer = winAnim.mSurfaceController.getLayer();
- if (maxLayer < layer) {
- maxLayer = layer;
+ if (mScreenshotApplicationState.maxLayer < layer) {
+ mScreenshotApplicationState.maxLayer = layer;
}
- if (minLayer > layer) {
- minLayer = layer;
+ if (mScreenshotApplicationState.minLayer > layer) {
+ mScreenshotApplicationState.minLayer = layer;
}
// Don't include wallpaper in bounds calculation
- if (!includeFullDisplay && !ws.mIsWallpaper) {
- final Rect wf = ws.mFrame;
- final Rect cr = ws.mContentInsets;
+ if (!includeFullDisplay && !w.mIsWallpaper) {
+ final Rect wf = w.mFrame;
+ final Rect cr = w.mContentInsets;
int left = wf.left + cr.left;
int top = wf.top + cr.top;
int right = wf.right - cr.right;
int bottom = wf.bottom - cr.bottom;
frame.union(left, top, right, bottom);
- ws.getVisibleBounds(stackBounds);
+ w.getVisibleBounds(stackBounds);
if (!Rect.intersects(frame, stackBounds)) {
// Set frame empty if there's no intersection.
frame.setEmpty();
@@ -2939,16 +2212,22 @@
}
final boolean foundTargetWs =
- (ws.mAppToken != null && ws.mAppToken.token == appToken)
- || (appWin != null && wallpaperOnly);
- if (foundTargetWs && ws.isDisplayedLw() && winAnim.getShown()) {
- screenshotReady = true;
+ (w.mAppToken != null && w.mAppToken.token == appToken)
+ || (mScreenshotApplicationState.appWin != null && wallpaperOnly);
+ if (foundTargetWs && w.isDisplayedLw() && winAnim.getShown()) {
+ mScreenshotApplicationState.screenshotReady = true;
}
- if (ws.isObscuringFullscreen(mDisplayInfo)){
- break;
+ if (w.isObscuringDisplay()){
+ return true;
}
- }
+ return false;
+ }, true /* traverseTopToBottom */);
+
+ final WindowState appWin = mScreenshotApplicationState.appWin;
+ final boolean screenshotReady = mScreenshotApplicationState.screenshotReady;
+ final int maxLayer = mScreenshotApplicationState.maxLayer;
+ final int minLayer = mScreenshotApplicationState.minLayer;
if (appToken != null && appWin == null) {
// Can't find a window to snapshot.
@@ -3020,14 +2299,13 @@
if (DEBUG_SCREENSHOT) {
Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
+ maxLayer + " appToken=" + appToken);
- for (int i = 0; i < mWindows.size(); i++) {
- final WindowState win = mWindows.get(i);
- final WindowSurfaceController controller = win.mWinAnimator.mSurfaceController;
- Slog.i(TAG_WM, win + ": " + win.mLayer
- + " animLayer=" + win.mWinAnimator.mAnimLayer
+ forAllWindows(w -> {
+ final WindowSurfaceController controller = w.mWinAnimator.mSurfaceController;
+ Slog.i(TAG_WM, w + ": " + w.mLayer
+ + " animLayer=" + w.mWinAnimator.mAnimLayer
+ " surfaceLayer=" + ((controller == null)
? "null" : controller.getLayer()));
- }
+ }, false /* traverseTopToBottom */);
}
final ScreenRotationAnimation screenRotationAnimation =
@@ -3064,6 +2342,9 @@
}
}
if (allBlack) {
+ final WindowState appWin = mScreenshotApplicationState.appWin;
+ final int maxLayer = mScreenshotApplicationState.maxLayer;
+ final int minLayer = mScreenshotApplicationState.minLayer;
Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" +
Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
(appWin != null ?
@@ -3104,32 +2385,23 @@
}
void onSeamlessRotationTimeout() {
- boolean layoutNeeded = false;
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- final WindowState w = mWindows.get(i);
+ // Used to indicate the layout is needed.
+ mTmpWindow = null;
+
+ forAllWindows(w -> {
if (!w.mSeamlesslyRotated) {
- continue;
+ return;
}
- layoutNeeded = true;
+ mTmpWindow = w;
w.setDisplayLayoutNeeded();
mService.markForSeamlessRotation(w, false);
- }
+ }, true /* traverseTopToBottom */);
- if (layoutNeeded) {
+ if (mTmpWindow != null) {
mService.mWindowPlacerLocked.performSurfacePlacement();
}
}
- static final class GetWindowOnDisplaySearchResult {
- boolean reachedToken;
- WindowState foundWindow;
-
- void reset() {
- reachedToken = false;
- foundWindow = null;
- }
- }
-
static final class TaskForResizePointSearchResult {
boolean searchDone;
Task taskForResize;
@@ -3140,6 +2412,39 @@
}
}
+ private static final class ApplySurfaceChangesTransactionState {
+ boolean displayHasContent;
+ boolean obscured;
+ boolean syswin;
+ boolean focusDisplayed;
+ float preferredRefreshRate;
+ int preferredModeId;
+
+ void reset() {
+ displayHasContent = false;
+ obscured = false;
+ syswin = false;
+ focusDisplayed = false;
+ preferredRefreshRate = 0;
+ preferredModeId = 0;
+ }
+ }
+
+ private static final class ScreenshotApplicationState {
+ WindowState appWin;
+ int maxLayer;
+ int minLayer;
+ boolean screenshotReady;
+
+ void reset(boolean screenshotReady) {
+ appWin = null;
+ maxLayer = 0;
+ minLayer = 0;
+ this.screenshotReady = screenshotReady;
+ minLayer = (screenshotReady) ? 0 : Integer.MAX_VALUE;
+ }
+ }
+
/**
* Base class for any direct child window container of {@link #DisplayContent} need to inherit
* from. This is mainly a pass through class that allows {@link #DisplayContent} to have
@@ -3192,15 +2497,6 @@
void removeStackFromDisplay(TaskStack stack) {
removeChild(stack);
stack.onRemovedFromDisplay();
- // TODO: remove when window list will be gone.
- // Manually remove records from window list and tap excluded windows list.
- for (int i = mWindows.size() - 1; i >= 0; --i) {
- final WindowState windowState = mWindows.get(i);
- if (stack == windowState.getStack()) {
- mWindows.remove(i);
- mTapExcludedWindows.remove(windowState);
- }
- }
}
void moveStack(TaskStack stack, boolean toTop) {
@@ -3330,11 +2626,23 @@
* Compares two child window tokens returns -1 if the first is lesser than the second in
* terms of z-order and 1 otherwise.
*/
- final Comparator<WindowToken> mWindowComparator = (token1, token2) ->
+ private final Comparator<WindowToken> mWindowComparator = (token1, token2) ->
// Tokens with higher base layer are z-ordered on-top.
mService.mPolicy.windowTypeToLayerLw(token1.windowType)
< mService.mPolicy.windowTypeToLayerLw(token2.windowType) ? -1 : 1;
+ private final Predicate<WindowState> mGetOrientingWindow = w -> {
+ if (!w.isVisibleLw() || !w.mPolicyVisibilityAfterAnim) {
+ return false;
+ }
+ final int req = w.mAttrs.screenOrientation;
+ if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND
+ || req == SCREEN_ORIENTATION_UNSET) {
+ return false;
+ }
+ return true;
+ };
+
private final String mName;
NonAppWindowContainers(String name) {
mName = name;
@@ -3345,6 +2653,30 @@
}
@Override
+ int getOrientation() {
+ final WindowManagerPolicy policy = mService.mPolicy;
+ // Find a window requesting orientation.
+ final WindowState win = getWindow(mGetOrientingWindow);
+
+ if (win != null) {
+ final int req = win.mAttrs.screenOrientation;
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
+ if (policy.isKeyguardHostWindow(win.mAttrs)) {
+ mService.mLastKeyguardForcedOrientation = req;
+ }
+ return (mService.mLastWindowForcedOrientation = req);
+ }
+
+ mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+
+ if (policy.isKeyguardShowingAndNotOccluded()) {
+ return mService.mLastKeyguardForcedOrientation;
+ }
+
+ return SCREEN_ORIENTATION_UNSET;
+ }
+
+ @Override
String getName() {
return mName;
}
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index f8b461e..e6bc7f4 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -390,9 +390,8 @@
inputMethodManagerInternal.hideCurrentInputMethod();
mImeHideRequested = true;
}
- } else if (setMinimizedDockedStack(false)) {
- mService.mWindowPlacerLocked.performSurfacePlacement();
}
+ setMinimizedDockedStack(false, false /* animate */);
}
/**
diff --git a/services/core/java/com/android/server/wm/DragResizeMode.java b/services/core/java/com/android/server/wm/DragResizeMode.java
index 08acf9d..8ab0406 100644
--- a/services/core/java/com/android/server/wm/DragResizeMode.java
+++ b/services/core/java/com/android/server/wm/DragResizeMode.java
@@ -20,6 +20,7 @@
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
/**
* Describes the mode in which a window is drag resizing.
@@ -45,7 +46,8 @@
case DRAG_RESIZE_MODE_DOCKED_DIVIDER:
return stackId == DOCKED_STACK_ID
|| stackId == FULLSCREEN_WORKSPACE_STACK_ID
- || stackId == HOME_STACK_ID;
+ || stackId == HOME_STACK_ID
+ || stackId == RECENTS_STACK_ID;
default:
return false;
}
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 40b737d..36520a9 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -68,7 +68,8 @@
* Drag/drop state
*/
class DragState {
- private static final long ANIMATION_DURATION_MS = 500;
+ private static final long MIN_ANIMATION_DURATION_MS = 195;
+ private static final long MAX_ANIMATION_DURATION_MS = 375;
private static final int DRAG_FLAGS_URI_ACCESS = View.DRAG_FLAG_GLOBAL_URI_READ |
View.DRAG_FLAG_GLOBAL_URI_WRITE;
@@ -103,6 +104,7 @@
private Animation mAnimation;
final Transformation mTransformation = new Transformation();
private final Interpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
+ private Point mDisplaySize = new Point();
DragState(WindowManagerService service, IBinder token, SurfaceControl surface,
int flags, IBinder localWin) {
@@ -171,10 +173,8 @@
// The drag window covers the entire display
mDragWindowHandle.frameLeft = 0;
mDragWindowHandle.frameTop = 0;
- Point p = new Point();
- display.getRealSize(p);
- mDragWindowHandle.frameRight = p.x;
- mDragWindowHandle.frameBottom = p.y;
+ mDragWindowHandle.frameRight = mDisplaySize.x;
+ mDragWindowHandle.frameBottom = mDisplaySize.y;
// Pause rotations before a drag.
if (DEBUG_ORIENTATION) {
@@ -215,6 +215,7 @@
* @param display The Display that the window being dragged is on.
*/
void register(Display display) {
+ display.getRealSize(mDisplaySize);
if (DEBUG_DRAG) Slog.d(TAG_WM, "registering drag input channel");
if (mInputInterceptor != null) {
Slog.e(TAG_WM, "Duplicate register of drag input channel");
@@ -326,7 +327,7 @@
// Global drags are limited to system windows, and windows for apps that are targeting N and
// above.
return targetWin.mAppToken == null
- || targetWin.mAppToken.targetSdk >= Build.VERSION_CODES.N;
+ || targetWin.mAppToken.mTargetSdk >= Build.VERSION_CODES.N;
}
/* helper - send a ACTION_DRAG_STARTED event only if the window has not
@@ -583,10 +584,17 @@
private Animation createReturnAnimationLocked() {
final AnimationSet set = new AnimationSet(false);
- set.addAnimation(new TranslateAnimation(
- 0, mOriginalX - mCurrentX, 0, mOriginalY - mCurrentY));
+ final float translateX = mOriginalX - mCurrentX;
+ final float translateY = mOriginalY - mCurrentY;
+ set.addAnimation(new TranslateAnimation( 0, translateX, 0, translateY));
set.addAnimation(new AlphaAnimation(mOriginalAlpha, mOriginalAlpha / 2));
- set.setDuration(ANIMATION_DURATION_MS);
+ // Adjust the duration to the travel distance.
+ final double travelDistance = Math.sqrt(translateX * translateX + translateY * translateY);
+ final double displayDiagonal =
+ Math.sqrt(mDisplaySize.x * mDisplaySize.x + mDisplaySize.y * mDisplaySize.y);
+ final long duration = MIN_ANIMATION_DURATION_MS + (long) (travelDistance / displayDiagonal
+ * (MAX_ANIMATION_DURATION_MS - MIN_ANIMATION_DURATION_MS));
+ set.setDuration(duration);
set.setInterpolator(mCubicEaseOutInterpolator);
set.initialize(0, 0, 0, 0);
set.start(); // Will start on the first call to getTransformation.
@@ -597,7 +605,7 @@
final AnimationSet set = new AnimationSet(false);
set.addAnimation(new ScaleAnimation(1, 0, 1, 0, mThumbOffsetX, mThumbOffsetY));
set.addAnimation(new AlphaAnimation(mOriginalAlpha, 0));
- set.setDuration(ANIMATION_DURATION_MS);
+ set.setDuration(MIN_ANIMATION_DURATION_MS);
set.setInterpolator(mCubicEaseOutInterpolator);
set.initialize(0, 0, 0, 0);
set.start(); // Will start on the first call to getTransformation.
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 12c72e9..3fbe36f 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -16,10 +16,15 @@
package com.android.server.wm;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
import static android.view.WindowManager.INPUT_CONSUMER_PIP;
import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
@@ -40,12 +45,14 @@
import android.view.WindowManager;
import android.view.WindowManagerPolicy;
+
import com.android.server.input.InputApplicationHandle;
import com.android.server.input.InputManagerService;
import com.android.server.input.InputWindowHandle;
import java.io.PrintWriter;
import java.util.Arrays;
+import java.util.function.Consumer;
final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
private final WindowManagerService mService;
@@ -70,6 +77,13 @@
// Array of window handles to provide to the input dispatcher.
private InputWindowHandle[] mInputWindowHandles;
private int mInputWindowHandleCount;
+ private boolean mAddInputConsumerHandle;
+ private boolean mAddPipInputConsumerHandle;
+ private boolean mAddWallpaperInputConsumerHandle;
+ private boolean mDisableWallpaperTouchEvents;
+ private final Rect mTmpRect = new Rect();
+ private final UpdateInputForAllWindowsConsumer mUpdateInputForAllWindowsConsumer =
+ new UpdateInputForAllWindowsConsumer();
// Set to true when the first input device configuration change notification
// is received to indicate that the input devices are ready.
@@ -244,7 +258,7 @@
if (! abort) {
// The activity manager declined to abort dispatching.
// Wait a bit longer and timeout again later.
- return appWindowToken.inputDispatchingTimeoutNanos;
+ return appWindowToken.mInputDispatchingTimeoutNanos;
}
} catch (RemoteException ex) {
}
@@ -323,12 +337,12 @@
}
}
- public void setUpdateInputWindowsNeededLw() {
+ void setUpdateInputWindowsNeededLw() {
mUpdateInputWindowsNeeded = true;
}
/* Updates the cached window information provided to the input dispatcher. */
- public void updateInputWindowsLw(boolean force) {
+ void updateInputWindowsLw(boolean force) {
if (!force && !mUpdateInputWindowsNeeded) {
return;
}
@@ -372,13 +386,7 @@
}
// Add all windows on the default display.
- mService.mRoot.updateInputWindows(this, mInputFocus, inDrag);
-
- // Send windows to native code.
- mService.mInputManager.setInputWindows(mInputWindowHandles);
-
- // Clear the list in preparation for the next round.
- clearInputWindowHandlesLw();
+ mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);
if (false) Slog.d(TAG_WM, "<<<<<<< EXITED updateInputWindowsLw");
}
@@ -496,7 +504,7 @@
} else {
final InputApplicationHandle handle = newApp.mInputApplicationHandle;
handle.name = newApp.toString();
- handle.dispatchingTimeoutNanos = newApp.inputDispatchingTimeoutNanos;
+ handle.dispatchingTimeoutNanos = newApp.mInputDispatchingTimeoutNanos;
mService.mInputManager.setFocusedApplication(handle);
}
@@ -571,4 +579,98 @@
pw.println(prefix + "mInputFreezeReason=" + mInputFreezeReason);
}
}
+
+ private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> {
+
+ InputConsumerImpl navInputConsumer;
+ InputConsumerImpl pipInputConsumer;
+ InputConsumerImpl wallpaperInputConsumer;
+ Rect pipTouchableBounds;
+ boolean inDrag;
+ WallpaperController wallpaperController;
+
+ private void updateInputWindows(boolean inDrag) {
+
+ // TODO: multi-display
+ navInputConsumer = getInputConsumer(INPUT_CONSUMER_NAVIGATION, DEFAULT_DISPLAY);
+ pipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP, DEFAULT_DISPLAY);
+ wallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER, DEFAULT_DISPLAY);
+ mAddInputConsumerHandle = navInputConsumer != null;
+ mAddPipInputConsumerHandle = pipInputConsumer != null;
+ mAddWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
+ mTmpRect.setEmpty();
+ pipTouchableBounds = mAddPipInputConsumerHandle ? mTmpRect : null;
+ mDisableWallpaperTouchEvents = false;
+ this.inDrag = inDrag;
+ wallpaperController = mService.mRoot.mWallpaperController;
+
+ mService.mRoot.forAllWindows(this, true /* traverseTopToBottom */);
+ if (mAddWallpaperInputConsumerHandle) {
+ // No visible wallpaper found, add the wallpaper input consumer at the end.
+ addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
+ }
+
+ // Send windows to native code.
+ mService.mInputManager.setInputWindows(mInputWindowHandles);
+
+ clearInputWindowHandlesLw();
+ }
+
+ @Override
+ public void accept(WindowState w) {
+ final InputChannel inputChannel = w.mInputChannel;
+ final InputWindowHandle inputWindowHandle = w.mInputWindowHandle;
+ if (inputChannel == null || inputWindowHandle == null || w.mRemoved
+ || w.isAdjustedForMinimizedDock()) {
+ // Skip this window because it cannot possibly receive input.
+ return;
+ }
+
+ if (mAddPipInputConsumerHandle
+ && w.getStackId() == PINNED_STACK_ID
+ && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) {
+ // Update the bounds of the Pip input consumer to match the Pinned stack
+ w.getStack().getBounds(pipTouchableBounds);
+ pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
+ addInputWindowHandle(pipInputConsumer.mWindowHandle);
+ mAddPipInputConsumerHandle = false;
+ }
+
+ if (mAddInputConsumerHandle
+ && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
+ addInputWindowHandle(navInputConsumer.mWindowHandle);
+ mAddInputConsumerHandle = false;
+ }
+
+ if (mAddWallpaperInputConsumerHandle) {
+ if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisibleLw()) {
+ // Add the wallpaper input consumer above the first visible wallpaper.
+ addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
+ mAddWallpaperInputConsumerHandle = false;
+ }
+ }
+
+ final int flags = w.mAttrs.flags;
+ final int privateFlags = w.mAttrs.privateFlags;
+ final int type = w.mAttrs.type;
+
+ final boolean hasFocus = w == mInputFocus;
+ final boolean isVisible = w.isVisibleLw();
+ if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
+ mDisableWallpaperTouchEvents = true;
+ }
+ final boolean hasWallpaper = wallpaperController.isWallpaperTarget(w)
+ && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0
+ && !mDisableWallpaperTouchEvents;
+
+ // If there's a drag in progress and 'child' is a potential drop target,
+ // make sure it's been told about the drag
+ if (inDrag && isVisible && w.getDisplayContent().isDefaultDisplay) {
+ mService.mDragState.sendDragStartedIfNeededLw(w);
+ }
+
+ addInputWindowHandle(
+ inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 01a50b7..0ad4e0a 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -135,7 +135,7 @@
mService = service;
mDisplayContent = displayContent;
mSnapAlgorithm = new PipSnapAlgorithm(service.mContext);
- mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler());
+ mMotionHelper = new PipMotionHelper(UiThread.getHandler());
mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
reloadResources();
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 88986e3..349740b 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -40,6 +40,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.function.Consumer;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
@@ -129,6 +130,23 @@
private final WindowLayersController mLayersController;
final WallpaperController mWallpaperController;
+ private String mCloseSystemDialogsReason;
+ private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
+ if (w.mHasSurface) {
+ try {
+ w.mClient.closeSystemDialogs(mCloseSystemDialogsReason);
+ } catch (RemoteException e) {
+ }
+ }
+ };
+
+ private static final Consumer<WindowState> sRemoveReplacedWindowsConsumer = w -> {
+ final AppWindowToken aToken = w.mAppToken;
+ if (aToken != null) {
+ aToken.removeReplacedWindowIfNeeded(w);
+ }
+ };
+
RootWindowContainer(WindowManagerService service) {
mService = service;
mLayersController = new WindowLayersController(mService);
@@ -219,7 +237,7 @@
return false;
}
- void getWindowsByName(WindowList output, String name) {
+ void getWindowsByName(ArrayList<WindowState> output, String name) {
int objectId = 0;
// See if this is an object ID.
try {
@@ -231,7 +249,7 @@
getWindowsByName(output, name, objectId);
}
- private void getWindowsByName(WindowList output, String name, int objectId) {
+ private void getWindowsByName(ArrayList<WindowState> output, String name, int objectId) {
forAllWindows((w) -> {
if (name != null) {
if (w.mAttrs.getTitle().toString().contains(name)) {
@@ -276,15 +294,6 @@
return null;
}
- // TODO: Users would have their own window containers under the display container?
- void switchUser() {
- final int count = mChildren.size();
- for (int i = 0; i < count; ++i) {
- final DisplayContent dc = mChildren.get(i);
- dc.switchUser();
- }
- }
-
/**
* Set new display override config and return array of ids of stacks that were changed during
* update. If called for the default display, global configuration will also be updated.
@@ -385,26 +394,15 @@
}
void closeSystemDialogs(String reason) {
- forAllWindows((w) -> {
- if (w.mHasSurface) {
- try {
- w.mClient.closeSystemDialogs(reason);
- } catch (RemoteException e) {
- }
- }
- }, false /* traverseTopToBottom */);
+ mCloseSystemDialogsReason = reason;
+ forAllWindows(mCloseSystemDialogsConsumer, false /* traverseTopToBottom */);
}
void removeReplacedWindows() {
if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
mService.openSurfaceTransaction();
try {
- forAllWindows((w) -> {
- final AppWindowToken aToken = w.mAppToken;
- if (aToken != null) {
- aToken.removeReplacedWindowIfNeeded(w);
- }
- }, true /* traverseTopToBottom */);
+ forAllWindows(sRemoveReplacedWindowsConsumer, true /* traverseTopToBottom */);
} finally {
mService.closeSurfaceTransaction();
if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
@@ -429,14 +427,6 @@
return hasChanges;
}
- void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) {
- final int count = mChildren.size();
- for (int i = 0; i < count; ++i) {
- final DisplayContent dc = mChildren.get(i);
- dc.updateInputWindows(inputMonitor, inputFocus, inDrag);
- }
- }
-
boolean reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation,
boolean secure) {
final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
@@ -662,7 +652,7 @@
WindowState win = mService.mDestroySurface.get(i);
win.mDestroying = false;
if (mService.mInputMethodWindow == win) {
- mService.mInputMethodWindow = null;
+ mService.setInputMethodWindowLocked(null);
}
if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) {
wallpaperDestroyed = true;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index b889db2..aa6e3c7 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -19,7 +19,9 @@
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -86,12 +88,15 @@
private boolean mIsOnTopLauncher;
Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
- Configuration overrideConfig, boolean isOnTopLauncher) {
+ Configuration overrideConfig, boolean isOnTopLauncher, int resizeMode,
+ boolean homeTask) {
mTaskId = taskId;
mStack = stack;
mUserId = userId;
mService = service;
mIsOnTopLauncher = isOnTopLauncher;
+ mResizeMode = resizeMode;
+ mHomeTask = homeTask;
setBounds(bounds, overrideConfig);
}
@@ -99,7 +104,8 @@
return mStack.getDisplayContent();
}
- void addAppToken(int addPos, AppWindowToken wtoken, int resizeMode, boolean homeTask) {
+ @Override
+ void addChild(AppWindowToken wtoken, int addPos) {
final int lastPos = mChildren.size();
if (addPos >= lastPos) {
addPos = lastPos;
@@ -116,11 +122,9 @@
if (parent != null) {
parent.removeChild(wtoken);
}
- addChild(wtoken, addPos);
+ super.addChild(wtoken, addPos);
wtoken.mTask = this;
mDeferRemoval = false;
- mResizeMode = resizeMode;
- mHomeTask = homeTask;
}
private boolean hasWindowsAlive() {
@@ -146,11 +150,11 @@
if (content != null) {
content.mDimLayerController.removeDimLayerUser(this);
}
- getParent().removeChild(this);
+ removeImmediately();
mService.mTaskIdToTask.delete(mTaskId);
}
- // Change to use reparenting in WC when TaskStack is switched to use WC.
+ // Change to use re-parenting in WC when TaskStack is switched to use WC.
void moveTaskToStack(TaskStack stack, boolean toTop) {
if (stack == mStack) {
return;
@@ -280,6 +284,17 @@
return ActivityInfo.isResizeableMode(mResizeMode) || mService.mForceResizableTasks;
}
+ /**
+ * Tests if the orientation should be preserved upon user interactive resizig operations.
+
+ * @return true if orientation should not get changed upon resizing operation.
+ */
+ boolean preserveOrientationOnResize() {
+ return mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
+ || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
+ || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
+ }
+
boolean isOnTopLauncher() {
return mIsOnTopLauncher;
}
@@ -523,11 +538,7 @@
boolean showForAllUsers() {
final int tokensCount = mChildren.size();
- return (tokensCount != 0) && mChildren.get(tokensCount - 1).showForAllUsers;
- }
-
- boolean inHomeStack() {
- return mStack != null && mStack.mStackId == HOME_STACK_ID;
+ return (tokensCount != 0) && mChildren.get(tokensCount - 1).mShowForAllUsers;
}
boolean inFreeformWorkspace() {
@@ -589,46 +600,6 @@
}
}
- void getWindowOnDisplayBeforeToken(DisplayContent dc, WindowToken token,
- DisplayContent.GetWindowOnDisplaySearchResult result) {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final AppWindowToken current = mChildren.get(i);
- if (current == token) {
- // We have reach the token we are interested in. End search.
- result.reachedToken = true;
- return;
- }
-
- // We haven't reached the token yet; if this token is not going to the bottom and
- // has windows on this display, then it is a candidate for what we are looking for.
- final WindowList tokenWindowList = dc.getTokenWindowsOnDisplay(current);
- if (!current.sendingToBottom && tokenWindowList.size() > 0) {
- result.foundWindow = tokenWindowList.get(0);
- }
- }
- }
-
- void getWindowOnDisplayAfterToken(DisplayContent dc, WindowToken token,
- DisplayContent.GetWindowOnDisplaySearchResult result) {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final AppWindowToken current = mChildren.get(i);
- if (!result.reachedToken) {
- if (current == token) {
- // We have reached the token we are interested in. Get whichever window occurs
- // after it that is on the same display.
- result.reachedToken = true;
- }
- continue;
- }
-
- final WindowList tokenWindowList = dc.getTokenWindowsOnDisplay(current);
- if (tokenWindowList.size() > 0) {
- result.foundWindow = tokenWindowList.get(tokenWindowList.size() - 1);
- return;
- }
- }
- }
-
@Override
boolean fillsParent() {
return mFillsParent || !StackId.isTaskResizeAllowed(mStack.mStackId);
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 6887312..267566b 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -50,9 +50,9 @@
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.MotionEvent;
-import android.view.SurfaceControl;
import android.view.WindowManager;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.input.InputApplicationHandle;
import com.android.server.input.InputWindowHandle;
import com.android.server.wm.WindowManagerService.H;
@@ -61,6 +61,7 @@
import java.lang.annotation.RetentionPolicy;
class TaskPositioner implements DimLayer.DimLayerUser {
+ private static final boolean DEBUG_ORIENTATION_VIOLATIONS = false;
private static final String TAG_LOCAL = "TaskPositioner";
private static final String TAG = TAG_WITH_CLASS_NAME ? TAG_LOCAL : TAG_WM;
@@ -89,6 +90,12 @@
public static final int RESIZING_HINT_DURATION_MS = 0;
+ // The minimal aspect ratio which needs to be met to count as landscape (or 1/.. for portrait).
+ // Note: We do not use the 1.33 from the CDD here since the user is allowed to use what ever
+ // aspect he desires.
+ @VisibleForTesting
+ static final float MIN_ASPECT = 1.2f;
+
private final WindowManagerService mService;
private WindowPositionerEventReceiver mInputEventReceiver;
private Display mDisplay;
@@ -103,8 +110,11 @@
private Task mTask;
private boolean mResizing;
+ private boolean mPreserveOrientation;
+ private boolean mStartOrientationWasLandscape;
private final Rect mWindowOriginalBounds = new Rect();
private final Rect mWindowDragBounds = new Rect();
+ private final Point mMaxVisibleSize = new Point();
private float mStartDragX;
private float mStartDragY;
@CtrlType
@@ -226,6 +236,11 @@
mService = service;
}
+ @VisibleForTesting
+ Rect getWindowDragBounds() {
+ return mWindowDragBounds;
+ }
+
/**
* @param display The Display that the window being dragged is on.
*/
@@ -294,6 +309,7 @@
mSideMargin = dipToPixel(SIDE_MARGIN_DIP, mDisplayMetrics);
mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics);
mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics);
+ mDisplay.getRealSize(mMaxVisibleSize);
mDragEnded = false;
}
@@ -335,44 +351,57 @@
mService.resumeRotationLocked();
}
- void startDragLocked(WindowState win, boolean resize, float startX, float startY) {
+ void startDrag(WindowState win, boolean resize, boolean preserveOrientation, float startX,
+ float startY) {
if (DEBUG_TASK_POSITIONING) {
- Slog.d(TAG, "startDragLocked: win=" + win + ", resize=" + resize
- + ", {" + startX + ", " + startY + "}");
+ Slog.d(TAG, "startDrag: win=" + win + ", resize=" + resize
+ + ", preserveOrientation=" + preserveOrientation + ", {" + startX + ", "
+ + startY + "}");
}
- mCtrlType = CTRL_NONE;
mTask = win.getTask();
- mStartDragX = startX;
- mStartDragY = startY;
-
// Use the dim bounds, not the original task bounds. The cursor
// movement should be calculated relative to the visible bounds.
// Also, use the dim bounds of the task which accounts for
// multiple app windows. Don't use any bounds from win itself as it
// may not be the same size as the task.
mTask.getDimBounds(mTmpRect);
+ startDrag(resize, preserveOrientation, startX, startY, mTmpRect);
+ }
+
+ @VisibleForTesting
+ void startDrag(boolean resize, boolean preserveOrientation,
+ float startX, float startY, Rect startBounds) {
+ mCtrlType = CTRL_NONE;
+ mStartDragX = startX;
+ mStartDragY = startY;
+ mPreserveOrientation = preserveOrientation;
if (resize) {
- if (startX < mTmpRect.left) {
+ if (startX < startBounds.left) {
mCtrlType |= CTRL_LEFT;
}
- if (startX > mTmpRect.right) {
+ if (startX > startBounds.right) {
mCtrlType |= CTRL_RIGHT;
}
- if (startY < mTmpRect.top) {
+ if (startY < startBounds.top) {
mCtrlType |= CTRL_TOP;
}
- if (startY > mTmpRect.bottom) {
+ if (startY > startBounds.bottom) {
mCtrlType |= CTRL_BOTTOM;
}
- mResizing = true;
+ mResizing = mCtrlType != CTRL_NONE;
}
- mWindowOriginalBounds.set(mTmpRect);
+ // In case of !isDockedInEffect we are using the union of all task bounds. These might be
+ // made up out of multiple windows which are only partially overlapping. When that happens,
+ // the orientation from the window of interest to the entire stack might diverge. However
+ // for now we treat them as the same.
+ mStartOrientationWasLandscape = startBounds.width() >= startBounds.height();
+ mWindowOriginalBounds.set(startBounds);
// Make sure we always have valid drag bounds even if the drag ends before any move events
// have been handled.
- mWindowDragBounds.set(mTmpRect);
+ mWindowDragBounds.set(startBounds);
}
private void endDragLocked() {
@@ -387,26 +416,7 @@
}
if (mCtrlType != CTRL_NONE) {
- // This is a resizing operation.
- final int deltaX = Math.round(x - mStartDragX);
- final int deltaY = Math.round(y - mStartDragY);
- int left = mWindowOriginalBounds.left;
- int top = mWindowOriginalBounds.top;
- int right = mWindowOriginalBounds.right;
- int bottom = mWindowOriginalBounds.bottom;
- if ((mCtrlType & CTRL_LEFT) != 0) {
- left = Math.min(left + deltaX, right - mMinVisibleWidth);
- }
- if ((mCtrlType & CTRL_TOP) != 0) {
- top = Math.min(top + deltaY, bottom - mMinVisibleHeight);
- }
- if ((mCtrlType & CTRL_RIGHT) != 0) {
- right = Math.max(left + mMinVisibleWidth, right + deltaX);
- }
- if ((mCtrlType & CTRL_BOTTOM) != 0) {
- bottom = Math.max(top + mMinVisibleHeight, bottom + deltaY);
- }
- mWindowDragBounds.set(left, top, right, bottom);
+ resizeDrag(x, y);
mTask.setDragResizing(true, DRAG_RESIZE_MODE_FREEFORM);
return false;
}
@@ -428,6 +438,168 @@
return false;
}
+ /**
+ * The user is drag - resizing the window.
+ *
+ * @param x The x coordinate of the current drag coordinate.
+ * @param y the y coordinate of the current drag coordinate.
+ */
+ @VisibleForTesting
+ void resizeDrag(float x, float y) {
+ // This is a resizing operation.
+ // We need to keep various constraints:
+ // 1. mMinVisible[Width/Height] <= [width/height] <= mMaxVisibleSize.[x/y]
+ // 2. The orientation is kept - if required.
+ final int deltaX = Math.round(x - mStartDragX);
+ final int deltaY = Math.round(y - mStartDragY);
+ int left = mWindowOriginalBounds.left;
+ int top = mWindowOriginalBounds.top;
+ int right = mWindowOriginalBounds.right;
+ int bottom = mWindowOriginalBounds.bottom;
+
+ // The aspect which we have to respect. Note that if the orientation does not need to be
+ // preserved the aspect will be calculated as 1.0 which neutralizes the following
+ // computations.
+ final float minAspect = !mPreserveOrientation
+ ? 1.0f
+ : (mStartOrientationWasLandscape ? MIN_ASPECT : (1.0f / MIN_ASPECT));
+ // Calculate the resulting width and height of the drag operation.
+ int width = right - left;
+ int height = bottom - top;
+ if ((mCtrlType & CTRL_LEFT) != 0) {
+ width = Math.max(mMinVisibleWidth, width - deltaX);
+ } else if ((mCtrlType & CTRL_RIGHT) != 0) {
+ width = Math.max(mMinVisibleWidth, width + deltaX);
+ }
+ if ((mCtrlType & CTRL_TOP) != 0) {
+ height = Math.max(mMinVisibleHeight, height - deltaY);
+ } else if ((mCtrlType & CTRL_BOTTOM) != 0) {
+ height = Math.max(mMinVisibleHeight, height + deltaY);
+ }
+
+ // If we have to preserve the orientation - check that we are doing so.
+ final float aspect = (float) width / (float) height;
+ if (mPreserveOrientation && ((mStartOrientationWasLandscape && aspect < MIN_ASPECT)
+ || (!mStartOrientationWasLandscape && aspect > (1.0 / MIN_ASPECT)))) {
+ // Calculate 2 rectangles fulfilling all requirements for either X or Y being the major
+ // drag axis. What ever is producing the bigger rectangle will be chosen.
+ int width1;
+ int width2;
+ int height1;
+ int height2;
+ if (mStartOrientationWasLandscape) {
+ // Assuming that the width is our target we calculate the height.
+ width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, width));
+ height1 = Math.min(height, Math.round((float)width1 / MIN_ASPECT));
+ if (height1 < mMinVisibleHeight) {
+ // If the resulting height is too small we adjust to the minimal size.
+ height1 = mMinVisibleHeight;
+ width1 = Math.max(mMinVisibleWidth,
+ Math.min(mMaxVisibleSize.x, Math.round((float)height1 * MIN_ASPECT)));
+ }
+ // Assuming that the height is our target we calculate the width.
+ height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, height));
+ width2 = Math.max(width, Math.round((float)height2 * MIN_ASPECT));
+ if (width2 < mMinVisibleWidth) {
+ // If the resulting width is too small we adjust to the minimal size.
+ width2 = mMinVisibleWidth;
+ height2 = Math.max(mMinVisibleHeight,
+ Math.min(mMaxVisibleSize.y, Math.round((float)width2 / MIN_ASPECT)));
+ }
+ } else {
+ // Assuming that the width is our target we calculate the height.
+ width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, width));
+ height1 = Math.max(height, Math.round((float)width1 * MIN_ASPECT));
+ if (height1 < mMinVisibleHeight) {
+ // If the resulting height is too small we adjust to the minimal size.
+ height1 = mMinVisibleHeight;
+ width1 = Math.max(mMinVisibleWidth,
+ Math.min(mMaxVisibleSize.x, Math.round((float)height1 / MIN_ASPECT)));
+ }
+ // Assuming that the height is our target we calculate the width.
+ height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, height));
+ width2 = Math.min(width, Math.round((float)height2 / MIN_ASPECT));
+ if (width2 < mMinVisibleWidth) {
+ // If the resulting width is too small we adjust to the minimal size.
+ width2 = mMinVisibleWidth;
+ height2 = Math.max(mMinVisibleHeight,
+ Math.min(mMaxVisibleSize.y, Math.round((float)width2 * MIN_ASPECT)));
+ }
+ }
+
+ // Use the bigger of the two rectangles if the major change was positive, otherwise
+ // do the opposite.
+ final boolean grows = width > (right - left) || height > (bottom - top);
+ if (grows == (width1 * height1 > width2 * height2)) {
+ width = width1;
+ height = height1;
+ } else {
+ width = width2;
+ height = height2;
+ }
+ }
+
+ // Update mWindowDragBounds to the new drag size.
+ updateDraggedBounds(left, top, right, bottom, width, height);
+ }
+
+ /**
+ * Given the old coordinates and the new width and height, update the mWindowDragBounds.
+ *
+ * @param left The original left bound before the user started dragging.
+ * @param top The original top bound before the user started dragging.
+ * @param right The original right bound before the user started dragging.
+ * @param bottom The original bottom bound before the user started dragging.
+ * @param newWidth The new dragged width.
+ * @param newHeight The new dragged height.
+ */
+ void updateDraggedBounds(int left, int top, int right, int bottom, int newWidth,
+ int newHeight) {
+ // Generate the final bounds by keeping the opposite drag edge constant.
+ if ((mCtrlType & CTRL_LEFT) != 0) {
+ left = right - newWidth;
+ } else { // Note: The right might have changed - if we pulled at the right or not.
+ right = left + newWidth;
+ }
+ if ((mCtrlType & CTRL_TOP) != 0) {
+ top = bottom - newHeight;
+ } else { // Note: The height might have changed - if we pulled at the bottom or not.
+ bottom = top + newHeight;
+ }
+
+ mWindowDragBounds.set(left, top, right, bottom);
+
+ checkBoundsForOrientationViolations(mWindowDragBounds);
+ }
+
+ /**
+ * Validate bounds against orientation violations (if DEBUG_ORIENTATION_VIOLATIONS is set).
+ *
+ * @param bounds The bounds to be checked.
+ */
+ private void checkBoundsForOrientationViolations(Rect bounds) {
+ // When using debug check that we are not violating the given constraints.
+ if (DEBUG_ORIENTATION_VIOLATIONS) {
+ if (mStartOrientationWasLandscape != (bounds.width() >= bounds.height())) {
+ Slog.e(TAG, "Orientation violation detected! should be "
+ + (mStartOrientationWasLandscape ? "landscape" : "portrait")
+ + " but is the other");
+ } else {
+ Slog.v(TAG, "new bounds size: " + bounds.width() + " x " + bounds.height());
+ }
+ if (mMinVisibleWidth > bounds.width() || mMinVisibleHeight > bounds.height()) {
+ Slog.v(TAG, "Minimum requirement violated: Width(min, is)=(" + mMinVisibleWidth
+ + ", " + bounds.width() + ") Height(min,is)=("
+ + mMinVisibleHeight + ", " + bounds.height() + ")");
+ }
+ if (mMaxVisibleSize.x < bounds.width() || mMaxVisibleSize.y < bounds.height()) {
+ Slog.v(TAG, "Maximum requirement violated: Width(min, is)=(" + mMaxVisibleSize.x
+ + ", " + bounds.width() + ") Height(min,is)=("
+ + mMaxVisibleSize.y + ", " + bounds.height() + ")");
+ }
+ }
+ }
+
private void updateWindowDragBounds(int x, int y, Rect stackBounds) {
final int offsetX = Math.round(x - mStartDragX);
final int offsetY = Math.round(y - mStartDragY);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 203ba72..74c0919 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -859,7 +859,9 @@
}
// TODO: Should each user have there own stacks?
+ @Override
void switchUser() {
+ super.switchUser();
int top = mChildren.size();
for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
Task task = mChildren.get(taskNdx);
@@ -1183,7 +1185,7 @@
@Override
public boolean dimFullscreen() {
- return mStackId == HOME_STACK_ID || fillsParent();
+ return StackId.isHomeOrRecentsStack(mStackId) || fillsParent();
}
@Override
@@ -1488,30 +1490,6 @@
}
}
- void getWindowOnDisplayBeforeToken(DisplayContent dc, WindowToken token,
- DisplayContent.GetWindowOnDisplaySearchResult result) {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final Task task = mChildren.get(i);
- task.getWindowOnDisplayBeforeToken(dc, token, result);
- if (result.reachedToken) {
- // We have reach the token we are interested in. End search.
- return;
- }
- }
- }
-
- void getWindowOnDisplayAfterToken(DisplayContent dc, WindowToken token,
- DisplayContent.GetWindowOnDisplaySearchResult result) {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final Task task = mChildren.get(i);
- task.getWindowOnDisplayAfterToken(dc, token, result);
- if (result.foundWindow != null) {
- // We have found a window after the token. End search.
- return;
- }
- }
- }
-
@Override
int getOrientation() {
return (StackId.canSpecifyOrientation(mStackId))
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 8dbf2b3..feceb8e 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import com.android.internal.util.ToBooleanFunction;
+
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
@@ -51,7 +53,7 @@
*/
class WallpaperController {
private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperController" : TAG_WM;
- final private WindowManagerService mService;
+ private WindowManagerService mService;
private final ArrayList<WallpaperWindowToken> mWallpaperTokens = new ArrayList<>();
@@ -97,6 +99,78 @@
private final FindWallpaperTargetResult mFindResults = new FindWallpaperTargetResult();
+ private final ToBooleanFunction<WindowState> mFindWallpaperTargetFunction = w -> {
+ final WindowAnimator winAnimator = mService.mAnimator;
+ if ((w.mAttrs.type == TYPE_WALLPAPER)) {
+ if (mFindResults.topWallpaper == null || mFindResults.resetTopWallpaper) {
+ mFindResults.setTopWallpaper(w);
+ mFindResults.resetTopWallpaper = false;
+ }
+ return false;
+ }
+
+ mFindResults.resetTopWallpaper = true;
+ if (w != winAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
+ // If this window's app token is hidden and not animating, it is of no interest to us.
+ if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
+ if (DEBUG_WALLPAPER) Slog.v(TAG,
+ "Skipping hidden and not animating token: " + w);
+ return false;
+ }
+ }
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w + ": isOnScreen=" + w.isOnScreen()
+ + " mDrawState=" + w.mWinAnimator.mDrawState);
+
+ if (w.mWillReplaceWindow && mWallpaperTarget == null
+ && !mFindResults.useTopWallpaperAsTarget) {
+ // When we are replacing a window and there was wallpaper before replacement, we want to
+ // keep the window until the new windows fully appear and can determine the visibility,
+ // to avoid flickering.
+ mFindResults.setUseTopWallpaperAsTarget(true);
+ }
+
+ final boolean keyguardGoingAwayWithWallpaper = (w.mAppToken != null
+ && AppTransition.isKeyguardGoingAwayTransit(
+ w.mAppToken.mAppAnimator.getTransit())
+ && (w.mAppToken.mAppAnimator.getTransitFlags()
+ & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0);
+
+ boolean needsShowWhenLockedWallpaper = false;
+ if ((w.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
+ && mService.mPolicy.isKeyguardLocked()
+ && mService.mPolicy.isKeyguardOccluded()) {
+ // The lowest show when locked window decides whether we need to put the wallpaper
+ // behind.
+ needsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
+ || (w.mAppToken != null && !w.mAppToken.fillsParent());
+ }
+
+ if (keyguardGoingAwayWithWallpaper || needsShowWhenLockedWallpaper) {
+ // Keep the wallpaper during Keyguard exit but also when it's needed for a
+ // non-fullscreen show when locked activity.
+ mFindResults.setUseTopWallpaperAsTarget(true);
+ }
+
+ final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
+ if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
+ if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: " + w);
+ mFindResults.setWallpaperTarget(w);
+ if (w == mWallpaperTarget && w.mWinAnimator.isAnimationSet()) {
+ // The current wallpaper target is animating, so we'll look behind it for
+ // another possible target and figure out what is going on later.
+ if (DEBUG_WALLPAPER) Slog.v(TAG,
+ "Win " + w + ": token animating, looking behind.");
+ }
+ // Found a target! End search.
+ return true;
+ } else if (w == winAnimator.mWindowDetachedWallpaper) {
+ if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
+ "Found animating detached wallpaper target win: " + w);
+ mFindResults.setUseTopWallpaperAsTarget(true);
+ }
+ return false;
+ };
+
public WallpaperController(WindowManagerService service) {
mService = service;
}
@@ -371,89 +445,18 @@
return mWallpaperAnimLayerAdjustment;
}
- private void findWallpaperTarget(DisplayContent dc , FindWallpaperTargetResult result) {
- final WindowAnimator winAnimator = mService.mAnimator;
- result.reset();
+ private void findWallpaperTarget(DisplayContent dc) {
+ mFindResults.reset();
if (mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
// In freeform mode we set the wallpaper as its own target, so we don't need an
// additional window to make it visible.
- result.setUseTopWallpaperAsTarget(true);
+ mFindResults.setUseTopWallpaperAsTarget(true);
}
- dc.forAllWindows(w -> {
- if ((w.mAttrs.type == TYPE_WALLPAPER)) {
- if (result.topWallpaper == null || result.resetTopWallpaper) {
- result.setTopWallpaper(w);
- result.resetTopWallpaper = false;
- }
- return false;
- }
+ dc.forAllWindows(mFindWallpaperTargetFunction, true /* traverseTopToBottom */);
- result.resetTopWallpaper = true;
- if (w != winAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
- // If this window's app token is hidden and not animating,
- // it is of no interest to us.
- if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
- if (DEBUG_WALLPAPER) Slog.v(TAG,
- "Skipping hidden and not animating token: " + w);
- return false;
- }
- }
- if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w + ": isOnScreen=" + w.isOnScreen()
- + " mDrawState=" + w.mWinAnimator.mDrawState);
-
- if (w.mWillReplaceWindow && mWallpaperTarget == null
- && !result.useTopWallpaperAsTarget) {
- // When we are replacing a window and there was wallpaper before replacement, we
- // want to keep the window until the new windows fully appear and can determine the
- // visibility, to avoid flickering.
- result.setUseTopWallpaperAsTarget(true);
- }
-
- final boolean keyguardGoingAwayWithWallpaper = (w.mAppToken != null
- && AppTransition.isKeyguardGoingAwayTransit(
- w.mAppToken.mAppAnimator.getTransit())
- && (w.mAppToken.mAppAnimator.getTransitFlags()
- & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0);
-
- boolean needsShowWhenLockedWallpaper = false;
- if ((w.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
- && mService.mPolicy.isKeyguardLocked()
- && mService.mPolicy.isKeyguardOccluded()) {
- // The lowest show when locked window decides whether we need to put the wallpaper
- // behind.
- needsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
- || (w.mAppToken != null && !w.mAppToken.fillsParent());
- }
-
- if (keyguardGoingAwayWithWallpaper || needsShowWhenLockedWallpaper) {
- // Keep the wallpaper during Keyguard exit but also when it's needed for a
- // non-fullscreen show when locked activity.
- result.setUseTopWallpaperAsTarget(true);
- }
-
- final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
- if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
- if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: " + w);
- result.setWallpaperTarget(w);
- if (w == mWallpaperTarget && w.mWinAnimator.isAnimationSet()) {
- // The current wallpaper target is animating, so we'll look behind it for
- // another possible target and figure out what is going on later.
- if (DEBUG_WALLPAPER) Slog.v(TAG,
- "Win " + w + ": token animating, looking behind.");
- }
- // Found a target! End search.
- return true;
- } else if (w == winAnimator.mWindowDetachedWallpaper) {
- if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
- "Found animating detached wallpaper target win: " + w);
- result.setUseTopWallpaperAsTarget(true);
- }
- return false;
- }, true /* traverseTopToBottom */);
-
- if (result.wallpaperTarget == null && result.useTopWallpaperAsTarget) {
- result.setWallpaperTarget(result.topWallpaper);
+ if (mFindResults.wallpaperTarget == null && mFindResults.useTopWallpaperAsTarget) {
+ mFindResults.setWallpaperTarget(mFindResults.topWallpaper);
}
}
@@ -552,7 +555,7 @@
// First find top-most window that has asked to be on top of the wallpaper;
// all wallpapers go behind it.
- findWallpaperTarget(dc, mFindResults);
+ findWallpaperTarget(dc);
updateWallpaperWindowsTarget(dc, mFindResults);
// The window is visible to the compositor...but is it visible to the user?
@@ -683,24 +686,6 @@
}
}
- void dumpTokens(PrintWriter pw, String prefix, boolean dumpAll) {
- if (!mWallpaperTokens.isEmpty()) {
- pw.println();
- pw.print(prefix); pw.println("Wallpaper tokens:");
- for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
- WindowToken token = mWallpaperTokens.get(i);
- pw.print(prefix); pw.print("Wallpaper #"); pw.print(i);
- pw.print(' '); pw.print(token);
- if (dumpAll) {
- pw.println(':');
- token.dump(pw, " ");
- } else {
- pw.println();
- }
- }
- }
- }
-
/** Helper class for storing the results of a wallpaper target find operation. */
final private static class FindWallpaperTargetResult {
WindowState topWallpaper = null;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index a6a907c..4a1c067 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -18,13 +18,13 @@
import android.annotation.CallSuper;
import android.content.res.Configuration;
-import android.view.animation.Animation;
+import android.util.Pools;
+
import com.android.internal.util.ToBooleanFunction;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.function.Consumer;
-import java.util.function.Function;
import java.util.function.Predicate;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
@@ -69,6 +69,9 @@
// The specified orientation for this window container.
protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+ private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
+ new Pools.SynchronizedPool<>(3);
+
final protected WindowContainer getParent() {
return mParent;
}
@@ -126,7 +129,7 @@
/** Adds the input window container has a child of this container at the input index. */
@CallSuper
- protected void addChild(E child, int index) {
+ void addChild(E child, int index) {
if (child.getParent() != null) {
throw new IllegalArgumentException("addChild: container=" + child.getName()
+ " is already a child of container=" + child.getParent().getName()
@@ -483,19 +486,11 @@
return false;
}
- /**
- * Rebuilds the WindowList for the input display content.
- * @param addIndex The index in the window list to add the next entry to.
- * @return The next index in the window list to.
- */
- // TODO: Hoping we can get rid of WindowList so this method wouldn't be needed.
- int rebuildWindowList(int addIndex) {
- final int count = mChildren.size();
- for (int i = 0; i < count; i++) {
- final WindowContainer wc = mChildren.get(i);
- addIndex = wc.rebuildWindowList(addIndex);
+ // TODO: Users would have their own window containers under the display container?
+ void switchUser() {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ mChildren.get(i).switchUser();
}
- return addIndex;
}
/**
@@ -505,7 +500,7 @@
* @param traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
* z-order, else from bottom-to-top.
* @return True if the search ended before we reached the end of the hierarchy due to
- * {@link Function#apply} returning true.
+ * {@link ToBooleanFunction#apply} returning true.
*/
boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
if (traverseTopToBottom) {
@@ -526,10 +521,9 @@
}
void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
- forAllWindows(w -> {
- callback.accept(w);
- return false;
- }, traverseTopToBottom);
+ ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
+ forAllWindows(wrapper, traverseTopToBottom);
+ wrapper.release();
}
WindowState getWindow(Predicate<WindowState> callback) {
@@ -622,4 +616,32 @@
return toString();
}
+ private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
+ ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire();
+ if (wrapper == null) {
+ wrapper = new ForAllWindowsConsumerWrapper();
+ }
+ wrapper.setConsumer(consumer);
+ return wrapper;
+ }
+
+ private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> {
+
+ private Consumer<WindowState> mConsumer;
+
+ void setConsumer(Consumer<WindowState> consumer) {
+ mConsumer = consumer;
+ }
+
+ @Override
+ public boolean apply(WindowState w) {
+ mConsumer.accept(w);
+ return false;
+ }
+
+ void release() {
+ mConsumer = null;
+ mConsumerWrapperPool.release(this);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowLayersController.java b/services/core/java/com/android/server/wm/WindowLayersController.java
index 32373f9..e0c3d60 100644
--- a/services/core/java/com/android/server/wm/WindowLayersController.java
+++ b/services/core/java/com/android/server/wm/WindowLayersController.java
@@ -20,6 +20,7 @@
import android.view.Display;
import java.util.ArrayDeque;
+import java.util.function.Consumer;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
@@ -66,46 +67,50 @@
private boolean mAnyLayerChanged;
private int mHighestLayerInImeTargetBaseLayer;
private WindowState mImeTarget;
+ private boolean mAboveImeTarget;
+ private ArrayDeque<WindowState> mAboveImeTargetAppWindows = new ArrayDeque();
+
+ private final Consumer<WindowState> mAssignWindowLayersConsumer = w -> {
+ boolean layerChanged = false;
+
+ int oldLayer = w.mLayer;
+ if (w.mBaseLayer == mCurBaseLayer) {
+ mCurLayer += WINDOW_LAYER_MULTIPLIER;
+ } else {
+ mCurBaseLayer = mCurLayer = w.mBaseLayer;
+ }
+ assignAnimLayer(w, mCurLayer);
+
+ // TODO: Preserved old behavior of code here but not sure comparing oldLayer to
+ // mAnimLayer and mLayer makes sense...though the worst case would be unintentional
+ // layer reassignment.
+ if (w.mLayer != oldLayer || w.mWinAnimator.mAnimLayer != oldLayer) {
+ layerChanged = true;
+ mAnyLayerChanged = true;
+ }
+
+ if (w.mAppToken != null) {
+ mHighestApplicationLayer = Math.max(mHighestApplicationLayer,
+ w.mWinAnimator.mAnimLayer);
+ }
+ if (mImeTarget != null && w.mBaseLayer == mImeTarget.mBaseLayer) {
+ mHighestLayerInImeTargetBaseLayer = Math.max(mHighestLayerInImeTargetBaseLayer,
+ w.mWinAnimator.mAnimLayer);
+ }
+
+ collectSpecialWindows(w);
+
+ if (layerChanged) {
+ w.scheduleAnimationIfDimming();
+ }
+ };
final void assignWindowLayers(DisplayContent dc) {
if (DEBUG_LAYERS) Slog.v(TAG_WM, "Assigning layers based",
new RuntimeException("here").fillInStackTrace());
reset();
- dc.forAllWindows((w) -> {
- boolean layerChanged = false;
-
- int oldLayer = w.mLayer;
- if (w.mBaseLayer == mCurBaseLayer) {
- mCurLayer += WINDOW_LAYER_MULTIPLIER;
- } else {
- mCurBaseLayer = mCurLayer = w.mBaseLayer;
- }
- assignAnimLayer(w, mCurLayer);
-
- // TODO: Preserved old behavior of code here but not sure comparing oldLayer to
- // mAnimLayer and mLayer makes sense...though the worst case would be unintentional
- // layer reassignment.
- if (w.mLayer != oldLayer || w.mWinAnimator.mAnimLayer != oldLayer) {
- layerChanged = true;
- mAnyLayerChanged = true;
- }
-
- if (w.mAppToken != null) {
- mHighestApplicationLayer = Math.max(mHighestApplicationLayer,
- w.mWinAnimator.mAnimLayer);
- }
- if (mImeTarget != null && w.mBaseLayer == mImeTarget.mBaseLayer) {
- mHighestLayerInImeTargetBaseLayer = Math.max(mHighestLayerInImeTargetBaseLayer,
- w.mWinAnimator.mAnimLayer);
- }
-
- collectSpecialWindows(w);
-
- if (layerChanged) {
- w.scheduleAnimationIfDimming();
- }
- }, false /* traverseTopToBottom */);
+ dc.forAllWindows(mAssignWindowLayersConsumer, false /* traverseTopToBottom */);
adjustSpecialWindows();
@@ -143,6 +148,8 @@
mImeTarget = mService.mInputMethodTarget;
mHighestLayerInImeTargetBaseLayer = (mImeTarget != null) ? mImeTarget.mBaseLayer : 0;
+ mAboveImeTarget = false;
+ mAboveImeTargetAppWindows.clear();
}
private void collectSpecialWindows(WindowState w) {
@@ -157,6 +164,20 @@
mInputMethodWindows.add(w);
return;
}
+ if (mImeTarget != null) {
+ if (w.getParentWindow() == mImeTarget && w.mSubLayer > 0) {
+ // Child windows of the ime target with a positive sub-layer should be placed above
+ // the IME.
+ mAboveImeTargetAppWindows.add(w);
+ } else if (mAboveImeTarget && w.mAppToken != null) {
+ // windows of apps above the IME target should be placed above the IME.
+ mAboveImeTargetAppWindows.add(w);
+ }
+ if (w == mImeTarget) {
+ mAboveImeTarget = true;
+ }
+ }
+
final Task task = w.getTask();
if (task == null) {
return;
@@ -211,6 +232,12 @@
while (!mInputMethodWindows.isEmpty()) {
layer = assignAndIncreaseLayerIfNeeded(mInputMethodWindows.remove(), layer);
}
+
+ // Adjust app windows the should be displayed above the IME since they are above the IME
+ // target.
+ while (!mAboveImeTargetAppWindows.isEmpty()) {
+ layer = assignAndIncreaseLayerIfNeeded(mAboveImeTargetAppWindows.remove(), layer);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 6ec3161..158fd2b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -32,7 +32,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
@@ -238,6 +237,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static java.lang.Integer.MAX_VALUE;
/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
@@ -604,17 +604,6 @@
boolean mInputMethodTargetWaitingAnim;
WindowState mInputMethodWindow = null;
- // TODO: Remove with extreme prejudice! This list is maintained so that we can keep track of
- // dialogs that should go on top of the IME so they can be re-arranged in the window list any
- // time the IME changes position in the window list. Normally you would have a dialog be a child
- // window of the IME, but they don't share the same token since they are added by different
- // clients. This doesn't really affect what the user sees on screen since this dialogs have an
- // higher base layer than the IME window, but it will affect users of the window list that
- // expect the list to represent the order of things on-screen (e.g input service). This makes
- // the code for managing the window list hard to follow (see all the places it is used).
- // We can remove the use of this field when we automatically assign layers and z-order the
- // window list before it is used whenever window container order changes.
- final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<>();
boolean mHardKeyboardAvailable;
WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
@@ -1375,19 +1364,15 @@
boolean imMayMove = true;
+ win.mToken.addWindow(win);
if (type == TYPE_INPUT_METHOD) {
win.mGivenInsetsPending = true;
- mInputMethodWindow = win;
- win.mToken.addImeWindow(win);
+ setInputMethodWindowLocked(win);
imMayMove = false;
} else if (type == TYPE_INPUT_METHOD_DIALOG) {
- mInputMethodDialogs.add(win);
- win.mToken.addWindow(win);
- displayContent.moveInputMethodDialogs(
- displayContent.findDesiredInputMethodWindowIndex(true));
+ displayContent.computeImeTarget(true /* updateImeTarget */);
imMayMove = false;
} else {
- win.mToken.addWindow(win);
if (type == TYPE_WALLPAPER) {
displayContent.mWallpaperController.clearLastWallpaperTimeoutTime();
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
@@ -1415,7 +1400,8 @@
winAnimator.mEnterAnimationPending = true;
winAnimator.mEnteringAnimation = true;
// Check if we need to prepare a transition for replacing window first.
- if (atoken != null && !prepareWindowReplacementTransition(atoken)) {
+ if (atoken != null && atoken.isVisible()
+ && !prepareWindowReplacementTransition(atoken)) {
// If not, check if need to set up a dummy transition during display freeze
// so that the unfreeze wait for the apps to draw. This might be needed if
// the app is relaunching.
@@ -1460,7 +1446,7 @@
}
if (imMayMove) {
- displayContent.moveInputMethodWindowsIfNeeded(false);
+ displayContent.computeImeTarget(true /* updateImeTarget */);
}
// Don't do layout here, the window must call
@@ -1494,7 +1480,7 @@
// Try using the target SDK of the root window
if (attachedWindow != null) {
return attachedWindow.mAppToken != null
- && attachedWindow.mAppToken.targetSdk > Build.VERSION_CODES.N_MR1;
+ && attachedWindow.mAppToken.mTargetSdk > Build.VERSION_CODES.N_MR1;
} else {
// Otherwise, look at the package
try {
@@ -1643,9 +1629,7 @@
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win);
if (mInputMethodWindow == win) {
- mInputMethodWindow = null;
- } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
- mInputMethodDialogs.remove(win);
+ setInputMethodWindowLocked(null);
}
final WindowToken token = win.mToken;
@@ -1653,7 +1637,7 @@
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Removing " + win + " from " + token);
// Window will already be removed from token before this post clean-up method is called.
if (token.isEmpty()) {
- if (!token.explicit) {
+ if (!token.mPersistOnEmpty) {
token.removeImmediately();
} else if (atoken != null) {
// TODO: Should this be moved into AppWindowToken.removeWindow? Might go away after
@@ -1675,19 +1659,24 @@
dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
}
- if (dc != null && dc.removeFromWindowList(win)) {
- if (!mWindowPlacerLocked.isInLayout()) {
- dc.assignWindowLayers(true /* setLayoutNeeded */);
- mWindowPlacerLocked.performSurfacePlacement();
- if (win.mAppToken != null) {
- win.mAppToken.updateReportedVisibilityLocked();
- }
+ if (dc != null && !mWindowPlacerLocked.isInLayout()) {
+ dc.assignWindowLayers(true /* setLayoutNeeded */);
+ mWindowPlacerLocked.performSurfacePlacement();
+ if (win.mAppToken != null) {
+ win.mAppToken.updateReportedVisibilityLocked();
}
}
mInputMonitor.updateInputWindowsLw(true /*force*/);
}
+ void setInputMethodWindowLocked(WindowState win) {
+ mInputMethodWindow = win;
+ final DisplayContent dc = win != null
+ ? win.getDisplayContent() : getDefaultDisplayContentLocked();
+ dc.computeImeTarget(true /* updateImeTarget */);
+ }
+
private void updateAppOpsState() {
synchronized(mWindowMap) {
mRoot.updateAppOpsState();
@@ -1996,7 +1985,7 @@
focusMayChange = isDefaultDisplay;
}
if (win.mAttrs.type == TYPE_INPUT_METHOD && mInputMethodWindow == null) {
- mInputMethodWindow = win;
+ setInputMethodWindowLocked(win);
imMayMove = true;
}
win.adjustStartingWindowFlags();
@@ -2062,14 +2051,15 @@
// reassign them at this point if the IM window state gets shuffled
boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
final DisplayContent dc = win.getDisplayContent();
- if (imMayMove && (dc.moveInputMethodWindowsIfNeeded(false) || toBeDisplayed)) {
- // Little hack here -- we -should- be able to rely on the function to return true if
- // the IME has moved and needs its layer recomputed. However, if the IME was hidden
- // and isn't actually moved in the list, its layer may be out of data so we make
- // sure to recompute it.
- // TODO: Probably not needed once the window list always has the right z-ordering
- // when the window hierarchy is updated.
- dc.assignWindowLayers(false /* setLayoutNeeded */);
+ if (imMayMove) {
+ dc.computeImeTarget(true /* updateImeTarget */);
+ if (toBeDisplayed) {
+ // Little hack here -- we -should- be able to rely on the function to return
+ // true if the IME has moved and needs its layer recomputed. However, if the IME
+ // was hidden and isn't actually moved in the list, its layer may be out of data
+ // so we make sure to recompute it.
+ dc.assignWindowLayers(false /* setLayoutNeeded */);
+ }
}
if (wallpaperMayMove) {
@@ -2163,7 +2153,7 @@
win.mWinAnimator.mAnimating = true;
} else {
if (mInputMethodWindow == win) {
- mInputMethodWindow = null;
+ setInputMethodWindowLocked(null);
}
win.destroyOrSaveSurface();
}
@@ -2442,8 +2432,6 @@
return;
}
- token.setExiting();
-
mInputMonitor.updateInputWindowsLw(true /*force*/);
}
} finally {
@@ -2451,28 +2439,11 @@
}
}
- private Task createTaskLocked(int taskId, int stackId, int userId, AppWindowToken atoken,
- Rect bounds, Configuration overrideConfig, boolean isOnTopLauncher) {
- if (DEBUG_STACK) Slog.i(TAG_WM, "createTaskLocked: taskId=" + taskId + " stackId=" + stackId
- + " atoken=" + atoken + " bounds=" + bounds);
- final TaskStack stack = mStackIdToStack.get(stackId);
- if (stack == null) {
- throw new IllegalArgumentException("createTaskLocked: invalid stackId=" + stackId);
- }
- EventLog.writeEvent(WM_TASK_CREATED, taskId, stackId);
- Task task = new Task(taskId, stack, userId, this, bounds, overrideConfig, isOnTopLauncher);
- mTaskIdToTask.put(taskId, task);
- stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */, atoken.showForAllUsers);
- return task;
- }
-
@Override
- public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
- int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int userId,
+ public void addAppToken(int addPos, IApplicationToken token, int taskId,
+ int requestedOrientation, boolean fullscreen, boolean showForAllUsers,
int configChanges, boolean voiceInteraction, boolean launchTaskBehind,
- Rect taskBounds, Configuration overrideConfig, int taskResizeMode,
- boolean alwaysFocusable, boolean homeTask, int targetSdkVersion,
- int rotationAnimationHint, boolean isOnTopLauncher) {
+ boolean alwaysFocusable, int targetSdkVersion, int rotationAnimationHint) {
if (!checkCallingPermission(MANAGE_APP_TOKENS, "addAppToken()")) {
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
}
@@ -2498,42 +2469,24 @@
return;
}
- final TaskStack stack = mStackIdToStack.get(stackId);
- if (stack == null) {
- throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
- }
-
- atoken = new AppWindowToken(this, token, voiceInteraction, stack.getDisplayContent());
- atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
- atoken.setFillsParent(fullscreen);
- atoken.showForAllUsers = showForAllUsers;
- atoken.targetSdk = targetSdkVersion;
- atoken.setOrientation(requestedOrientation);
- atoken.layoutConfigChanges = (configChanges &
- (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
- atoken.mLaunchTaskBehind = launchTaskBehind;
- atoken.mAlwaysFocusable = alwaysFocusable;
- if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
- + " to stack=" + stackId + " task=" + taskId + " at " + addPos);
- atoken.mRotationAnimationHint = rotationAnimationHint;
-
Task task = mTaskIdToTask.get(taskId);
if (task == null) {
- task = createTaskLocked(taskId, stackId, userId, atoken, taskBounds, overrideConfig,
- isOnTopLauncher);
+ throw new IllegalArgumentException("addAppToken: invalid taskId=" + taskId);
}
- task.addAppToken(addPos, atoken, taskResizeMode, homeTask);
- // Application tokens start out hidden.
- atoken.hidden = true;
- atoken.hiddenRequested = true;
+ atoken = new AppWindowToken(this, token, voiceInteraction, task.getDisplayContent(),
+ inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdkVersion,
+ requestedOrientation, rotationAnimationHint, configChanges, launchTaskBehind,
+ alwaysFocusable);
+ if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
+ + " task=" + taskId + " at " + addPos);
+
+ task.addChild(atoken, addPos);
}
}
@Override
- public void setAppTask(IBinder token, int taskId, int stackId, Rect taskBounds,
- Configuration overrideConfig, int taskResizeMode, boolean homeTask,
- boolean isOnTopLauncher) {
+ public void addAppToTask(IBinder token, int taskId) {
if (!checkCallingPermission(MANAGE_APP_TOKENS, "setAppTask()")) {
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
}
@@ -2545,12 +2498,40 @@
return;
}
- Task newTask = mTaskIdToTask.get(taskId);
- if (newTask == null) {
- newTask = createTaskLocked(taskId, stackId, atoken.mTask.mUserId, atoken,
- taskBounds, overrideConfig, isOnTopLauncher);
+ Task task = mTaskIdToTask.get(taskId);
+ if (task == null) {
+ throw new IllegalArgumentException("setAppTask: invalid taskId=" + taskId);
}
- newTask.addAppToken(Integer.MAX_VALUE /* at top */, atoken, taskResizeMode, homeTask);
+ task.addChild(atoken, MAX_VALUE /* at top */);
+ }
+ }
+
+ public void addTask(int taskId, int stackId, int userId, Rect bounds,
+ Configuration overrideConfig, int resizeMode, boolean homeTask, boolean isOnTopLauncher,
+ boolean toTop, boolean showForAllUsers) {
+ if (!checkCallingPermission(MANAGE_APP_TOKENS, "addTask()")) {
+ throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
+ }
+
+ synchronized(mWindowMap) {
+ Task task = mTaskIdToTask.get(taskId);
+ if (task != null) {
+ throw new IllegalArgumentException(
+ "addTask: Attempt to add already existing task=" + task);
+ }
+
+ if (DEBUG_STACK) Slog.i(TAG_WM, "createTaskLocked: taskId=" + taskId
+ + " stackId=" + stackId + " bounds=" + bounds);
+
+ final TaskStack stack = mStackIdToStack.get(stackId);
+ if (stack == null) {
+ throw new IllegalArgumentException("addTask: invalid stackId=" + stackId);
+ }
+ EventLog.writeEvent(WM_TASK_CREATED, taskId, stackId);
+ task = new Task(taskId, stack, userId, this, bounds, overrideConfig, isOnTopLauncher,
+ resizeMode, homeTask);
+ mTaskIdToTask.put(taskId, task);
+ stack.addTask(task, toTop, showForAllUsers);
}
}
@@ -3215,7 +3196,7 @@
}
final long origId = Binder.clearCallingIdentity();
- wtoken.setVisibility(null, visible, TRANSIT_UNSET, true, wtoken.voiceInteraction);
+ wtoken.setVisibility(null, visible, TRANSIT_UNSET, true, wtoken.mVoiceInteraction);
wtoken.updateReportedVisibilityLocked();
Binder.restoreCallingIdentity(origId);
}
@@ -3349,7 +3330,7 @@
if (mAppTransition.isTransitionSet()) {
task.setSendingToBottom(false);
}
- displayContent.rebuildAppWindowsAndLayoutIfNeeded();
+ displayContent.layoutAndAssignWindowLayersIfNeeded();
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -3371,7 +3352,7 @@
if (mAppTransition.isTransitionSet()) {
task.setSendingToBottom(true);
}
- stack.getDisplayContent().rebuildAppWindowsAndLayoutIfNeeded();
+ stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -3614,6 +3595,11 @@
}
@Override
+ public WindowManagerPolicy.WindowState getInputMethodWindowLw() {
+ return mInputMethodWindow;
+ }
+
+ @Override
public void notifyKeyguardTrustedChanged() {
mH.sendEmptyMessage(H.NOTIFY_KEYGUARD_TRUSTED_CHANGED);
}
@@ -4089,24 +4075,6 @@
}
}
- // Called by window manager policy. Not exposed externally.
- @Override
- public boolean isInputMethodWindowVisible() {
- synchronized (mWindowMap) {
- return mInputMethodWindow != null && mInputMethodWindow.isVisibleLw();
- }
- }
-
- // Called by window manager policy. Not exposed externally.
- @Override
- public void hideCurrentInputMethod() {
- final InputMethodManagerInternal inputMethodManagerInternal =
- LocalServices.getService(InputMethodManagerInternal.class);
- if (inputMethodManagerInternal != null) {
- inputMethodManagerInternal.hideCurrentInputMethod();
- }
- }
-
// Called by window manager policy. Not exposed externally.
@Override
public void lockDeviceNow() {
@@ -4628,7 +4596,7 @@
return null;
}
}
- return displayContent.screenshotApplications(appToken, displayId, width, height,
+ return displayContent.screenshotApplications(appToken, width, height,
includeFullDisplay, frameScale, config, wallpaperOnly);
}
@@ -5190,7 +5158,7 @@
boolean result = true;
- final WindowList windows = new WindowList();
+ final ArrayList<WindowState> windows = new ArrayList();
synchronized (mWindowMap) {
mRoot.forAllWindows(w -> {
windows.add(w);
@@ -5756,7 +5724,8 @@
win = windowForClientLocked(null, window, false);
// win shouldn't be null here, pass it down to startPositioningLocked
// to get warning if it's null.
- if (!startPositioningLocked(win, false /*resize*/, startX, startY)) {
+ if (!startPositioningLocked(
+ win, false /*resize*/, false /*preserveOrientation*/, startX, startY)) {
return false;
}
}
@@ -5771,8 +5740,8 @@
synchronized (mWindowMap) {
final Task task = displayContent.findTaskForResizePoint(x, y);
if (task != null) {
- if (!startPositioningLocked(
- task.getTopVisibleAppMainWindow(), true /*resize*/, x, y)) {
+ if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true /*resize*/,
+ task.preserveOrientationOnResize(), x, y)) {
return;
}
taskId = task.mTaskId;
@@ -5787,10 +5756,12 @@
}
}
- private boolean startPositioningLocked(
- WindowState win, boolean resize, float startX, float startY) {
- if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "startPositioningLocked: "
- + "win=" + win + ", resize=" + resize + ", {" + startX + ", " + startY + "}");
+ private boolean startPositioningLocked(WindowState win, boolean resize,
+ boolean preserveOrientation, float startX, float startY) {
+ if (DEBUG_TASK_POSITIONING)
+ Slog.d(TAG_WM, "startPositioningLocked: "
+ + "win=" + win + ", resize=" + resize + ", preserveOrientation="
+ + preserveOrientation + ", {" + startX + ", " + startY + "}");
if (win == null || win.getAppToken() == null) {
Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
@@ -5831,7 +5802,7 @@
return false;
}
- mTaskPositioner.startDragLocked(win, resize, startX, startY);
+ mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY);
return true;
}
@@ -7285,7 +7256,7 @@
changes |= FINISH_LAYOUT_REDO_LAYOUT;
if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
"Wallpaper layer changed: assigning layers + relayout");
- dc.moveInputMethodWindowsIfNeeded(true);
+ dc.computeImeTarget(true /* updateImeTarget */);
mRoot.mWallpaperMayChange = true;
// Since the window list has been rebuilt, focus might have to be recomputed since the
// actual order of windows might have changed again.
@@ -7378,10 +7349,25 @@
mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
// TODO(multidisplay): Focused windows on default display only.
final DisplayContent displayContent = getDefaultDisplayContentLocked();
- final boolean imWindowChanged = displayContent.moveInputMethodWindowsIfNeeded(
- mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
- && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
+ boolean imWindowChanged = false;
+ if (mInputMethodWindow != null) {
+ final WindowState prevTarget = mInputMethodTarget;
+ final WindowState newTarget =
+ displayContent.computeImeTarget(true /* updateImeTarget*/);
+
+ imWindowChanged = prevTarget != newTarget;
+
+ if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
+ && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) {
+ final int prevImeAnimLayer = mInputMethodWindow.mWinAnimator.mAnimLayer;
+ displayContent.assignWindowLayers(false /* setLayoutNeeded */);
+ imWindowChanged |=
+ prevImeAnimLayer != mInputMethodWindow.mWinAnimator.mAnimLayer;
+ }
+ }
+
if (imWindowChanged) {
+ mWindowsChanged = true;
displayContent.setLayoutNeeded();
newFocus = mRoot.computeFocusedWindow();
}
@@ -7856,7 +7842,6 @@
private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
mRoot.dumpTokens(pw, dumpAll);
- mRoot.mWallpaperController.dumpTokens(pw, " ", dumpAll);
if (!mFinishedStarting.isEmpty()) {
pw.println();
pw.println(" Finishing start of application tokens:");
@@ -7902,16 +7887,6 @@
ArrayList<WindowState> windows) {
mRoot.dumpWindowsNoHeader(pw, dumpAll, windows);
- if (mInputMethodDialogs.size() > 0) {
- pw.println();
- pw.println(" Input method dialogs:");
- for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
- WindowState w = mInputMethodDialogs.get(i);
- if (windows == null || windows.contains(w)) {
- pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
- }
- }
- }
if (mPendingRemove.size() > 0) {
pw.println();
pw.println(" Remove pending for:");
@@ -8070,7 +8045,7 @@
private boolean dumpWindows(PrintWriter pw, String name, String[] args, int opti,
boolean dumpAll) {
- final WindowList windows = new WindowList();
+ final ArrayList<WindowState> windows = new ArrayList();
if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
final boolean appsOnly = name.contains("apps");
final boolean visibleOnly = name.contains("visible");
@@ -8923,7 +8898,7 @@
return;
}
- token.removeAllWindows();
+ token.removeAllWindowsIfPossible();
}
WindowManagerService.this.removeWindowToken(binder, displayId);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 572581e..3daad43 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -60,8 +60,6 @@
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
-import java.util.function.Consumer;
-import java.util.function.Function;
import java.util.function.Predicate;
import static android.app.ActivityManager.StackId;
@@ -76,6 +74,7 @@
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
@@ -91,7 +90,6 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
@@ -115,6 +113,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -125,7 +124,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
@@ -140,9 +138,6 @@
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
-class WindowList extends ArrayList<WindowState> {
-}
-
/** A window in the window manager. */
class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState {
static final String TAG = TAG_WITH_CLASS_NAME ? "WindowState" : TAG_WM;
@@ -448,12 +443,6 @@
*/
boolean mWindowRemovalAllowed;
- /**
- * Temp for keeping track of windows that have been removed when
- * rebuilding window list.
- */
- boolean mRebuilding;
-
// Input channel and input window handle used by the input dispatcher.
final InputWindowHandle mInputWindowHandle;
InputChannel mInputChannel;
@@ -644,7 +633,7 @@
}
mIsFloatingLayer = mIsImWindow || mIsWallpaper;
- if (mAppToken != null && mAppToken.showForAllUsers) {
+ if (mAppToken != null && mAppToken.mShowForAllUsers) {
// Windows for apps that can show for all users should also show when the device is
// locked.
mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED;
@@ -1045,7 +1034,7 @@
@Override
public boolean isVoiceInteraction() {
- return mAppToken != null && mAppToken.voiceInteraction;
+ return mAppToken != null && mAppToken.mVoiceInteraction;
}
boolean setReportResizeHints() {
@@ -1235,7 +1224,7 @@
public long getInputDispatchingTimeoutNanos() {
return mAppToken != null
- ? mAppToken.inputDispatchingTimeoutNanos
+ ? mAppToken.mInputDispatchingTimeoutNanos
: WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
}
@@ -1654,18 +1643,16 @@
&& (!mIsChildWindow || !getParentWindow().hasMoved());
}
- boolean isObscuringFullscreen(final DisplayInfo displayInfo) {
+ boolean isObscuringDisplay() {
Task task = getTask();
if (task != null && task.mStack != null && !task.mStack.fillsParent()) {
return false;
}
- if (!isOpaqueDrawn() || !isFrameFullscreen(displayInfo)) {
- return false;
- }
- return true;
+ return isOpaqueDrawn() && fillsDisplay();
}
- boolean isFrameFullscreen(final DisplayInfo displayInfo) {
+ boolean fillsDisplay() {
+ final DisplayInfo displayInfo = getDisplayInfo();
return mFrame.left <= 0 && mFrame.top <= 0
&& mFrame.right >= displayInfo.appWidth && mFrame.bottom >= displayInfo.appHeight;
}
@@ -1726,7 +1713,7 @@
final DisplayContent dc = getDisplayContent();
if (mService.mInputMethodTarget == this) {
- dc.moveInputMethodWindowsIfNeeded(false);
+ dc.computeImeTarget(true /* updateImeTarget */);
}
final int type = mAttrs.type;
@@ -1936,6 +1923,41 @@
return mLayer + specialAdjustment;
}
+ boolean canBeImeTarget() {
+ if (mIsImWindow) {
+ // IME windows can't be IME targets. IME targets are required to be below the IME
+ // windows and that wouldn't be possible if the IME window is its own target...silly.
+ return false;
+ }
+
+ final int fl = mAttrs.flags & (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);
+ final int type = mAttrs.type;
+
+ // Can only be an IME target if both FLAG_NOT_FOCUSABLE and FLAG_ALT_FOCUSABLE_IM are set or
+ // both are cleared...and not a starting window.
+ if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)
+ && type != TYPE_APPLICATION_STARTING) {
+ return false;
+ }
+
+ if (DEBUG_INPUT_METHOD) {
+ Slog.i(TAG_WM, "isVisibleOrAdding " + this + ": " + isVisibleOrAdding());
+ if (!isVisibleOrAdding()) {
+ Slog.i(TAG_WM, " mSurfaceController=" + mWinAnimator.mSurfaceController
+ + " relayoutCalled=" + mRelayoutCalled
+ + " viewVis=" + mViewVisibility
+ + " policyVis=" + mPolicyVisibility
+ + " policyVisAfterAnim=" + mPolicyVisibilityAfterAnim
+ + " parentHidden=" + isParentWindowHidden()
+ + " exiting=" + mAnimatingExit + " destroying=" + mDestroying);
+ if (mAppToken != null) {
+ Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + mAppToken.hiddenRequested);
+ }
+ }
+ }
+ return isVisibleOrAdding();
+ }
+
void scheduleAnimationIfDimming() {
final DisplayContent dc = getDisplayContent();
if (dc == null) {
@@ -2090,7 +2112,7 @@
return false;
}
- void removeReplacedWindow() {
+ private void removeReplacedWindow() {
if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + this);
if (isDimming()) {
transferDimToReplacement();
@@ -2143,6 +2165,16 @@
}
}
+ @Override
+ void switchUser() {
+ super.switchUser();
+ if (isHiddenFromUserLocked()) {
+ if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + this
+ + ", attrs=" + mAttrs.type + ", belonging to " + mOwnerUid);
+ hideLw(false);
+ }
+ }
+
int getTouchableRegion(Region region, int flags) {
final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
if (modal && mAppToken != null) {
@@ -2850,11 +2882,11 @@
mShowToOwnerOnly = showToOwnerOnly;
}
- boolean isHiddenFromUserLocked() {
+ private boolean isHiddenFromUserLocked() {
// Child windows are evaluated based on their parent window.
final WindowState win = getTopParentWindow();
if (win.mAttrs.type < FIRST_SYSTEM_WINDOW
- && win.mAppToken != null && win.mAppToken.showForAllUsers) {
+ && win.mAppToken != null && win.mAppToken.mShowForAllUsers) {
// All window frames that are fullscreen extend above status bar, but some don't extend
// below navigation bar. Thus, check for display frame for top/left and stable frame for
@@ -3256,7 +3288,7 @@
pw.print(mPolicyVisibilityAfterAnim);
pw.print(" mAppOpVisibility=");
pw.print(mAppOpVisibility);
- pw.print(" parentHidden="); pw.println(isParentWindowHidden());
+ pw.print(" parentHidden="); pw.print(isParentWindowHidden());
pw.print(" mPermanentlyHidden="); pw.println(mPermanentlyHidden);
}
if (!mRelayoutCalled || mLayoutNeeded) {
@@ -3505,16 +3537,6 @@
return mIsChildWindow;
}
- /**
- * Returns the bottom child window in regards to z-order of this window or null if no children.
- */
- WindowState getBottomChild() {
- // Child windows are z-ordered based on sub-layer using {@link #sWindowSubLayerComparator}
- // and the child with the lowest z-order will be at the head of the list.
- WindowState c = mChildren.peekFirst();
- return c == null ? null : c;
- }
-
boolean layoutInParentFrame() {
return mIsChildWindow
&& (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0;
@@ -3529,16 +3551,23 @@
/** Returns the topmost parent window if this is a child of another window, else this. */
WindowState getTopParentWindow() {
- WindowState w = this;
- while (w != null && w.mIsChildWindow) {
- w = w.getParentWindow();
+ WindowState current = this;
+ WindowState topParent = current;
+ while (current != null && current.mIsChildWindow) {
+ current = current.getParentWindow();
+ // Parent window can be null if the child is detached from it's parent already, but
+ // someone still has a reference to access it. So, we return the top parent value we
+ // already have instead of null.
+ if (current != null) {
+ topParent = current;
+ }
}
- return w;
+ return topParent;
}
boolean isParentWindowHidden() {
final WindowState parent = getParentWindow();
- return (parent == null) ? false : parent.mHidden;
+ return parent != null && parent.mHidden;
}
void setWillReplaceWindow(boolean animate) {
@@ -3801,48 +3830,10 @@
}
@Override
- int rebuildWindowList(int addIndex) {
- return reAddWindow(addIndex);
- }
-
- // TODO: come-up with a better name for this method that represents what it does.
- // Or, it is probably not going to matter anyways if we are successful in getting rid of
- // the WindowList concept.
- int reAddWindow(int index) {
- final DisplayContent dc = getDisplayContent();
- // Adding child windows relies on child windows being ordered by mSubLayer using
- // {@link #sWindowSubLayerComparator}.
- final int childCount = mChildren.size();
- boolean winAdded = false;
- for (int j = 0; j < childCount; j++) {
- final WindowState child = mChildren.get(j);
- if (!winAdded && child.mSubLayer >= 0) {
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM,
- "Re-adding child window at " + index + ": " + child);
- mRebuilding = false;
- dc.addToWindowList(this, index);
- index++;
- winAdded = true;
- }
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding window at " + index + ": " + child);
- child.mRebuilding = false;
- dc.addToWindowList(child, index);
- index++;
- }
- if (!winAdded) {
- if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding window at " + index + ": " + this);
- mRebuilding = false;
- dc.addToWindowList(this, index);
- index++;
- }
- return index;
- }
-
- @Override
boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
if (mChildren.isEmpty()) {
// The window has no children so we just return it.
- return callback.apply(this);
+ return applyInOrderWithImeWindows(callback, traverseTopToBottom);
}
if (traverseTopToBottom) {
@@ -3871,7 +3862,7 @@
child = mChildren.get(i);
}
- if (callback.apply(this)) {
+ if (applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
return true;
}
@@ -3907,7 +3898,7 @@
child = mChildren.get(i);
}
- if (callback.apply(this)) {
+ if (applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
return true;
}
@@ -3925,6 +3916,35 @@
return false;
}
+ private boolean applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback,
+ boolean traverseTopToBottom) {
+ if (traverseTopToBottom) {
+ if (mService.mInputMethodTarget == this) {
+ // This window is the current IME target, so we need to process the IME windows
+ // directly above it.
+ if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) {
+ return true;
+ }
+ }
+ if (callback.apply(this)) {
+ return true;
+ }
+ } else {
+ if (callback.apply(this)) {
+ return true;
+ }
+ if (mService.mInputMethodTarget == this) {
+ // This window is the current IME target, so we need to process the IME windows
+ // directly above it.
+ if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
WindowState getWindow(Predicate<WindowState> callback) {
if (callback.test(this)) {
return this;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 04db499..37bd402 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -57,7 +57,6 @@
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.MagnificationSpec;
-import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
import android.view.WindowManager;
@@ -1108,10 +1107,9 @@
/**
* Calculate the window-space crop rect and fill clipRect.
- * @return true if clipRect has been filled otherwise, no window space
- * crop should be applied.
+ * @return true if clipRect has been filled otherwise, no window space crop should be applied.
*/
- boolean calculateCrop(Rect clipRect) {
+ private boolean calculateCrop(Rect clipRect) {
final WindowState w = mWin;
final DisplayContent displayContent = w.getDisplayContent();
clipRect.setEmpty();
@@ -1130,7 +1128,6 @@
return false;
}
- final DisplayInfo displayInfo = displayContent.getDisplayInfo();
if (DEBUG_WINDOW_CROP) Slog.d(TAG,
"Updating crop win=" + w + " mLastCrop=" + mLastClipRect);
@@ -1139,7 +1136,7 @@
if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
+ w.mDecorFrame + " mSystemDecorRect=" + mSystemDecorRect);
- final boolean fullscreen = w.isFrameFullscreen(displayInfo);
+ final boolean fullscreen = w.fillsDisplay();
final boolean isFreeformResizing =
w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 7e1880f..1aabd5e 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -5,8 +5,6 @@
import static android.app.ActivityManagerInternal.APP_TRANSITION_STARTING_WINDOW;
import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
import static android.app.ActivityManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_CLOSE;
@@ -27,7 +25,6 @@
import static com.android.server.wm.AppTransition.TRANSIT_WALLPAPER_OPEN;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -35,7 +32,6 @@
import static com.android.server.wm.WindowManagerService.H.DO_TRAVERSAL;
import static com.android.server.wm.WindowManagerService.H.NOTIFY_APP_TRANSITION_STARTING;
import static com.android.server.wm.WindowManagerService.H.REPORT_WINDOWS_CHANGE;
-import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
@@ -53,7 +49,6 @@
import android.view.DisplayInfo;
import android.view.Surface;
import android.view.SurfaceControl;
-import android.view.View;
import android.view.WindowManager.LayoutParams;
import android.view.animation.Animation;
@@ -239,7 +234,8 @@
mService.mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
final DisplayContent displayContent = mService.getDefaultDisplayContentLocked();
- displayContent.rebuildAppWindowList();
+ // TODO: Don't believe this is really needed...
+ //mService.mWindowsChanged = true;
mService.mRoot.mWallpaperMayChange = false;
@@ -292,7 +288,7 @@
}
}
- voiceInteraction |= wtoken.voiceInteraction;
+ voiceInteraction |= wtoken.mVoiceInteraction;
if (wtoken.fillsParent()) {
final WindowState ws = wtoken.findMainWindow();
@@ -356,12 +352,8 @@
displayContent.setLayoutNeeded();
// TODO(multidisplay): IMEs are only supported on the default display.
- // TODO: Probably not needed once the window list always has the right z-ordering
- // when the window hierarchy is updated.
final DisplayContent dc = mService.getDefaultDisplayContentLocked();
- if (!dc.moveInputMethodWindowsIfNeeded(true)) {
- dc.assignWindowLayers(false /*setLayoutNeeded*/);
- }
+ dc.computeImeTarget(true /* updateImeTarget */);
mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
true /*updateInputWindows*/);
mService.mFocusMayChange = false;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index a2eebc3..4b94d15 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -18,25 +18,18 @@
import java.util.Comparator;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
-import android.os.Bundle;
import android.os.Debug;
import android.os.IBinder;
-import android.os.RemoteException;
import android.util.Slog;
-import android.view.DisplayInfo;
-import android.view.animation.Animation;
import java.io.PrintWriter;
@@ -58,8 +51,8 @@
final int windowType;
// Set if this token was explicitly added by a client, so should
- // not be removed when all windows are removed.
- final boolean explicit;
+ // persist (not be removed) when all windows are removed.
+ boolean mPersistOnEmpty;
// For printing.
String stringName;
@@ -104,27 +97,28 @@
return isFirstChildWindowGreaterThanSecond(newWindow, existingWindow) ? 1 : -1;
};
- WindowToken(WindowManagerService service, IBinder _token, int type, boolean _explicit,
+ WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
DisplayContent dc) {
mService = service;
token = _token;
windowType = type;
- explicit = _explicit;
+ mPersistOnEmpty = persistOnEmpty;
onDisplayChanged(dc);
}
- void removeAllWindows() {
+ void removeAllWindowsIfPossible() {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowState win = mChildren.get(i);
- if (DEBUG_WINDOW_MOVEMENT) Slog.w(TAG_WM, "removeAllWindows: removing win=" + win);
+ if (DEBUG_WINDOW_MOVEMENT) Slog.w(TAG_WM,
+ "removeAllWindowsIfPossible: removing win=" + win);
win.removeIfPossible();
- if (mChildren.contains(win)) {
- removeChild(win);
- }
}
}
void setExiting() {
+ // This token is exiting, so allow it to be removed when it no longer contains any windows.
+ mPersistOnEmpty = false;
+
if (hidden) {
return;
}
@@ -168,13 +162,6 @@
return highestAnimLayer;
}
- WindowState getTopWindow() {
- if (mChildren.isEmpty()) {
- return null;
- }
- return (WindowState) mChildren.get(mChildren.size() - 1).getTop();
- }
-
/**
* Returns true if the new window is considered greater than the existing window in terms of
* z-order.
@@ -189,51 +176,16 @@
if (DEBUG_FOCUS) Slog.d(TAG_WM,
"addWindow: win=" + win + " Callers=" + Debug.getCallers(5));
- if (!win.isChildWindow()) {
- if (asAppWindowToken() != null) {
- mDisplayContent.addAppWindowToWindowList(win);
- } else {
- mDisplayContent.addNonAppWindowToWindowList(win);
- }
-
- if (!mChildren.contains(win)) {
- if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
- addChild(win, mWindowComparator);
- }
- } else {
- mDisplayContent.addChildWindowToWindowList(win);
- }
- }
-
- void addImeWindow(WindowState win) {
- int pos = mDisplayContent.findDesiredInputMethodWindowIndex(true);
-
- if (pos < 0) {
- addWindow(win);
- mDisplayContent.moveInputMethodDialogs(pos);
+ if (win.isChildWindow()) {
+ // Child windows are added to their parent windows.
return;
}
-
- if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
- "Adding input method window " + win + " at " + pos);
- mDisplayContent.addToWindowList(win, pos);
if (!mChildren.contains(win)) {
- addChild(win, null);
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
+ addChild(win, mWindowComparator);
+ mService.mWindowsChanged = true;
+ // TODO: Should we also be setting layout needed here and other places?
}
- mDisplayContent.moveInputMethodDialogs(pos + 1);
- }
-
- /** Return the first window in the token window list that isn't a starting window or null. */
- WindowState getFirstNonStartingWindow() {
- final int count = mChildren.size();
- // We only care about parent windows so no need to loop through child windows.
- for (int i = 0; i < count; i++) {
- final WindowState w = mChildren.get(i);
- if (w.mAttrs.type != TYPE_APPLICATION_STARTING) {
- return w;
- }
- }
- return null;
}
/** Returns true if the token windows list is empty. */
@@ -297,16 +249,8 @@
}
void onDisplayChanged(DisplayContent dc) {
- if (mDisplayContent == dc) {
- return;
- }
-
- if (mDisplayContent != null) {
- mDisplayContent.removeWindowToken(token);
- }
+ dc.reParentWindowToken(this);
mDisplayContent = dc;
- mDisplayContent.setWindowToken(token, this);
-
super.onDisplayChanged(dc);
}
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index ac0e622..50a6095 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -73,6 +73,7 @@
libhwbinder \
libutils \
android.hardware.audio.common@2.0 \
+ android.hardware.gnss@1.0 \
android.hardware.light@2.0 \
android.hardware.power@1.0 \
android.hardware.thermal@1.0 \
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 25e819c..7db6d42 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -18,10 +18,13 @@
#define LOG_NDEBUG 0
+#include <android/hardware/gnss/1.0/IGnss.h>
+
+#include <hwbinder/IPCThreadState.h>
+#include <hwbinder/ProcessState.h>
+
#include "JNIHelp.h"
#include "jni.h"
-#include "hardware/hardware.h"
-#include "hardware/gps_internal.h"
#include "hardware_legacy/power.h"
#include "utils/Log.h"
#include "utils/misc.h"
@@ -34,6 +37,7 @@
#include <linux/in6.h>
#include <pthread.h>
#include <string.h>
+#include <cinttypes>
static jobject mCallbacksObj = NULL;
@@ -58,978 +62,65 @@
static jmethodID method_reportMeasurementData;
static jmethodID method_reportNavigationMessages;
-static const GpsInterface* sGpsInterface = NULL;
-static const GpsXtraInterface* sGpsXtraInterface = NULL;
-static const AGpsInterface* sAGpsInterface = NULL;
-static const GpsNiInterface* sGpsNiInterface = NULL;
-static const GpsDebugInterface* sGpsDebugInterface = NULL;
-static const AGpsRilInterface* sAGpsRilInterface = NULL;
-static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL;
-static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL;
-static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
-static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL;
+using android::OK;
+using android::sp;
+using android::status_t;
+using android::String16;
-#define GPS_MAX_SATELLITE_COUNT 32
-#define GNSS_MAX_SATELLITE_COUNT 64
+using android::hardware::IPCThreadState;
+using android::hardware::ProcessState;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::hidl_vec;
-// Let these through, with ID remapped down to 1, 2... by offset
-#define GLONASS_SVID_OFFSET 64
-#define GLONASS_SVID_COUNT 24
-#define BEIDOU_SVID_OFFSET 200
-#define BEIDOU_SVID_COUNT 35
+using android::hardware::gnss::V1_0::IAGnss;
+using android::hardware::gnss::V1_0::IAGnssCallback;
+using android::hardware::gnss::V1_0::IAGnssCallback;
+using android::hardware::gnss::V1_0::IAGnssRil;
+using android::hardware::gnss::V1_0::IAGnssRilCallback;
+using android::hardware::gnss::V1_0::IGnss;
+using android::hardware::gnss::V1_0::IGnssCallback;
+using android::hardware::gnss::V1_0::IGnssConfiguration;
+using android::hardware::gnss::V1_0::IGnssDebug;
+using android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using android::hardware::gnss::V1_0::IGnssGeofencing;
+using android::hardware::gnss::V1_0::IGnssMeasurement;
+using android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+using android::hardware::gnss::V1_0::IGnssNavigationMessage;
+using android::hardware::gnss::V1_0::IGnssNavigationMessageCallback;
+using android::hardware::gnss::V1_0::IGnssNi;
+using android::hardware::gnss::V1_0::IGnssNiCallback;
+using android::hardware::gnss::V1_0::IGnssXtra;
+using android::hardware::gnss::V1_0::IGnssXtraCallback;
-// Let these through, with ID remapped up (33->120 ... 64->151, etc.)
-#define SBAS_SVID_MIN 33
-#define SBAS_SVID_MAX 64
-#define SBAS_SVID_ADD 87
-// Let these through, with no ID remapping
-#define QZSS_SVID_MIN 193
-#define QZSS_SVID_MAX 200
-
-#define SVID_SHIFT_WIDTH 7
-#define CONSTELLATION_TYPE_SHIFT_WIDTH 3
-
-// temporary storage for GPS callbacks
-static GnssSvInfo sGnssSvList[GNSS_MAX_SATELLITE_COUNT];
-static size_t sGnssSvListSize;
-static const char* sNmeaString;
-static int sNmeaStringLength;
+sp<IGnss> gnssHal = nullptr;
+sp<IGnssXtra> gnssXtraIface = nullptr;
+sp<IAGnssRil> agnssRilIface = nullptr;
+sp<IGnssGeofencing> gnssGeofencingIface = nullptr;
+sp<IAGnss> agnssIface = nullptr;
+sp<IGnssDebug> gnssDebugIface = nullptr;
+sp<IGnssConfiguration> gnssConfigurationIface = nullptr;
+sp<IGnssNi> gnssNiIface = nullptr;
+sp<IGnssMeasurement> gnssMeasurementIface = nullptr;
+sp<IGnssNavigationMessage> gnssNavigationMessageIface = nullptr;
#define WAKE_LOCK_NAME "GPS"
namespace android {
-static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
- if (env->ExceptionCheck()) {
- ALOGE("An exception was thrown by callback '%s'.", methodName);
- LOGE_EX(env);
- env->ExceptionClear();
- }
-}
-
-static void location_callback(GpsLocation* location)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
- (jdouble)location->latitude, (jdouble)location->longitude,
- (jdouble)location->altitude,
- (jfloat)location->speed, (jfloat)location->bearing,
- (jfloat)location->accuracy, (jlong)location->timestamp);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void status_callback(GpsStatus* status)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_reportStatus, status->status);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void sv_status_callback(GpsSvStatus* sv_status)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- size_t status_size = sv_status->size;
- // Some drives doesn't set the size field correctly. Assume GpsSvStatus_v1
- // if it doesn't provide a valid size.
- if (status_size == 0) {
- ALOGW("Invalid size of GpsSvStatus found: %zd.", status_size);
- }
- sGnssSvListSize = sv_status->num_svs;
- // Clamp the list size. Legacy GpsSvStatus has only 32 elements in sv_list.
- if (sGnssSvListSize > GPS_MAX_SATELLITE_COUNT) {
- ALOGW("Too many satellites %zd. Clamps to %d.",
- sGnssSvListSize,
- GPS_MAX_SATELLITE_COUNT);
- sGnssSvListSize = GPS_MAX_SATELLITE_COUNT;
- }
- uint32_t ephemeris_mask = sv_status->ephemeris_mask;
- uint32_t almanac_mask = sv_status->almanac_mask;
- uint32_t used_in_fix_mask = sv_status->used_in_fix_mask;
- for (size_t i = 0; i < sGnssSvListSize; i++) {
- GnssSvInfo& info = sGnssSvList[i];
- info.svid = sv_status->sv_list[i].prn;
- // Defacto mapping from the overused API that was designed for GPS-only
- if (info.svid >=1 && info.svid <= 32) {
- info.constellation = GNSS_CONSTELLATION_GPS;
- } else if (info.svid > GLONASS_SVID_OFFSET &&
- info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
- info.constellation = GNSS_CONSTELLATION_GLONASS;
- info.svid -= GLONASS_SVID_OFFSET;
- } else if (info.svid > BEIDOU_SVID_OFFSET &&
- info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
- info.constellation = GNSS_CONSTELLATION_BEIDOU;
- info.svid -= BEIDOU_SVID_OFFSET;
- } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
- info.constellation = GNSS_CONSTELLATION_SBAS;
- info.svid += SBAS_SVID_ADD;
- } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
- info.constellation = GNSS_CONSTELLATION_QZSS;
- } else {
- ALOGD("Unknown constellation type with Svid = %d.", info.svid);
- info.constellation = GNSS_CONSTELLATION_UNKNOWN;
- }
- info.c_n0_dbhz = sv_status->sv_list[i].snr;
- info.elevation = sv_status->sv_list[i].elevation;
- info.azimuth = sv_status->sv_list[i].azimuth;
- info.flags = GNSS_SV_FLAGS_NONE;
- // Only GPS info is valid for these fields, as these masks are just 32 bits, by GPS prn
- if (info.constellation == GNSS_CONSTELLATION_GPS) {
- int32_t this_svid_mask = (1 << (info.svid - 1));
- if ((ephemeris_mask & this_svid_mask) != 0) {
- info.flags |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA;
- }
- if ((almanac_mask & this_svid_mask) != 0) {
- info.flags |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA;
- }
- if ((used_in_fix_mask & this_svid_mask) != 0) {
- info.flags |= GNSS_SV_FLAGS_USED_IN_FIX;
- }
- }
- }
- env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void gnss_sv_status_callback(GnssSvStatus* sv_status) {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- size_t status_size = sv_status->size;
- // Check the size, and reject the object that has invalid size.
- if (status_size != sizeof(GnssSvStatus)) {
- ALOGE("Invalid size of GnssSvStatus found: %zd.", status_size);
- return;
- }
- sGnssSvListSize = sv_status->num_svs;
- // Clamp the list size
- if (sGnssSvListSize > GNSS_MAX_SATELLITE_COUNT) {
- ALOGD("Too many satellites %zd. Clamps to %d.",
- sGnssSvListSize,
- GNSS_MAX_SATELLITE_COUNT);
- sGnssSvListSize = GNSS_MAX_SATELLITE_COUNT;
- }
- // Copy GNSS SV info into sGnssSvList, if any.
- if (sGnssSvListSize > 0) {
- memcpy(sGnssSvList,
- sv_status->gnss_sv_list,
- sizeof(GnssSvInfo) * sGnssSvListSize);
- }
- env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- // The Java code will call back to read these values
- // We do this to avoid creating unnecessary String objects
- sNmeaString = nmea;
- sNmeaStringLength = length;
- env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void set_system_info_callback(const GnssSystemInfo* info) {
- ALOGD("set_system_info_callback: year_of_hw=%d\n", info->year_of_hw);
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
- info->year_of_hw);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void set_capabilities_callback(uint32_t capabilities)
-{
- ALOGD("set_capabilities_callback: %du\n", capabilities);
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void acquire_wakelock_callback()
-{
- acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
-}
-
-static void release_wakelock_callback()
-{
- release_wake_lock(WAKE_LOCK_NAME);
-}
-
-static void request_utc_time_callback()
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
-{
- return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
-}
-
-GpsCallbacks sGpsCallbacks = {
- sizeof(GpsCallbacks),
- location_callback,
- status_callback,
- sv_status_callback,
- nmea_callback,
- set_capabilities_callback,
- acquire_wakelock_callback,
- release_wakelock_callback,
- create_thread_callback,
- request_utc_time_callback,
- set_system_info_callback,
- gnss_sv_status_callback,
-};
-
-static void xtra_download_request_callback()
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-GpsXtraCallbacks sGpsXtraCallbacks = {
- xtra_download_request_callback,
- create_thread_callback,
-};
-
-static jbyteArray convert_to_ipv4(uint32_t ip, bool net_order)
-{
- if (INADDR_NONE == ip) {
- return NULL;
- }
-
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jbyteArray byteArray = env->NewByteArray(4);
- if (byteArray == NULL) {
- ALOGE("Unable to allocate byte array for IPv4 address");
- return NULL;
- }
-
- jbyte ipv4[4];
- if (net_order) {
- ALOGV("Converting IPv4 address(net_order) %x", ip);
- memcpy(ipv4, &ip, sizeof(ipv4));
- } else {
- ALOGV("Converting IPv4 address(host_order) %x", ip);
- //endianess transparent conversion from int to char[]
- ipv4[0] = (jbyte) (ip & 0xFF);
- ipv4[1] = (jbyte)((ip>>8) & 0xFF);
- ipv4[2] = (jbyte)((ip>>16) & 0xFF);
- ipv4[3] = (jbyte) (ip>>24);
- }
-
- env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*) ipv4);
- return byteArray;
-}
-
-static void agps_status_callback(AGpsStatus* agps_status)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jbyteArray byteArray = NULL;
- bool isSupported = false;
-
- size_t status_size = agps_status->size;
- if (status_size == sizeof(AGpsStatus)) {
- ALOGV("AGpsStatus is V3: %zd", status_size);
- switch (agps_status->addr.ss_family)
- {
- case AF_INET:
- {
- struct sockaddr_in *in = (struct sockaddr_in*)&(agps_status->addr);
- uint32_t ipAddr = *(uint32_t*)&(in->sin_addr);
- byteArray = convert_to_ipv4(ipAddr, true /* net_order */);
- if (ipAddr == INADDR_NONE || byteArray != NULL) {
- isSupported = true;
- }
- IF_ALOGD() {
- // log the IP for reference in case there is a bogus value pushed by HAL
- char str[INET_ADDRSTRLEN];
- inet_ntop(AF_INET, &(in->sin_addr), str, INET_ADDRSTRLEN);
- ALOGD("AGPS IP is v4: %s", str);
- }
- }
- break;
- case AF_INET6:
- {
- struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(agps_status->addr);
- byteArray = env->NewByteArray(16);
- if (byteArray != NULL) {
- env->SetByteArrayRegion(byteArray, 0, 16, (const jbyte *)&(in6->sin6_addr));
- isSupported = true;
- } else {
- ALOGE("Unable to allocate byte array for IPv6 address.");
- }
- IF_ALOGD() {
- // log the IP for reference in case there is a bogus value pushed by HAL
- char str[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, &(in6->sin6_addr), str, INET6_ADDRSTRLEN);
- ALOGD("AGPS IP is v6: %s", str);
- }
- }
- break;
- default:
- ALOGE("Invalid ss_family found: %d", agps_status->addr.ss_family);
- break;
- }
- } else if (status_size >= sizeof(AGpsStatus_v2)) {
- ALOGV("AGpsStatus is V2+: %zd", status_size);
- // for back-compatibility reasons we check in v2 that the data structure size is greater or
- // equal to the declared size in gps.h
- uint32_t ipaddr = agps_status->ipaddr;
- ALOGV("AGPS IP is v4: %x", ipaddr);
- byteArray = convert_to_ipv4(ipaddr, false /* net_order */);
- if (ipaddr == INADDR_NONE || byteArray != NULL) {
- isSupported = true;
- }
- } else if (status_size >= sizeof(AGpsStatus_v1)) {
- ALOGV("AGpsStatus is V1+: %zd", status_size);
- // because we have to check for >= with regards to v2, we also need to relax the check here
- // and only make sure that the size is at least what we expect
- isSupported = true;
- } else {
- ALOGE("Invalid size of AGpsStatus found: %zd.", status_size);
- }
-
- if (isSupported) {
- jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
- ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
- env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status->type,
- agps_status->status, byteArray);
-
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
- } else {
- ALOGD("Skipping calling method_reportAGpsStatus.");
- }
-
- if (byteArray) {
- env->DeleteLocalRef(byteArray);
- }
-}
-
-AGpsCallbacks sAGpsCallbacks = {
- agps_status_callback,
- create_thread_callback,
-};
-
-static void gps_ni_notify_callback(GpsNiNotification *notification)
-{
- ALOGD("gps_ni_notify_callback\n");
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jstring requestor_id = env->NewStringUTF(notification->requestor_id);
- jstring text = env->NewStringUTF(notification->text);
- jstring extras = env->NewStringUTF(notification->extras);
-
- if (requestor_id && text && extras) {
- env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
- notification->notification_id, notification->ni_type,
- notification->notify_flags, notification->timeout,
- notification->default_response, requestor_id, text,
- notification->requestor_id_encoding,
- notification->text_encoding, extras);
- } else {
- ALOGE("out of memory in gps_ni_notify_callback\n");
- }
-
- if (requestor_id)
- env->DeleteLocalRef(requestor_id);
- if (text)
- env->DeleteLocalRef(text);
- if (extras)
- env->DeleteLocalRef(extras);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-GpsNiCallbacks sGpsNiCallbacks = {
- gps_ni_notify_callback,
- create_thread_callback,
-};
-
-static void agps_request_set_id(uint32_t flags)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_requestSetID, flags);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-static void agps_request_ref_location(uint32_t flags)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_requestRefLocation, flags);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-AGpsRilCallbacks sAGpsRilCallbacks = {
- agps_request_set_id,
- agps_request_ref_location,
- create_thread_callback,
-};
-
-static void gps_geofence_transition_callback(int32_t geofence_id, GpsLocation* location,
- int32_t transition, GpsUtcTime timestamp)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
-
- env->CallVoidMethod(mCallbacksObj, method_reportGeofenceTransition, geofence_id,
- location->flags, (jdouble)location->latitude, (jdouble)location->longitude,
- (jdouble)location->altitude,
- (jfloat)location->speed, (jfloat)location->bearing,
- (jfloat)location->accuracy, (jlong)location->timestamp,
- transition, timestamp);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_status_callback(int32_t status, GpsLocation* location)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jint flags = 0;
- jdouble latitude = 0;
- jdouble longitude = 0;
- jdouble altitude = 0;
- jfloat speed = 0;
- jfloat bearing = 0;
- jfloat accuracy = 0;
- jlong timestamp = 0;
- if (location != NULL) {
- flags = location->flags;
- latitude = location->latitude;
- longitude = location->longitude;
- altitude = location->altitude;
- speed = location->speed;
- bearing = location->bearing;
- accuracy = location->accuracy;
- timestamp = location->timestamp;
- }
-
- env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, status,
- flags, latitude, longitude, altitude, speed, bearing, accuracy, timestamp);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_add_callback(int32_t geofence_id, int32_t status)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
- ALOGE("Error in geofence_add_callback: %d\n", status);
- }
- env->CallVoidMethod(mCallbacksObj, method_reportGeofenceAddStatus, geofence_id, status);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_remove_callback(int32_t geofence_id, int32_t status)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
- ALOGE("Error in geofence_remove_callback: %d\n", status);
- }
- env->CallVoidMethod(mCallbacksObj, method_reportGeofenceRemoveStatus, geofence_id, status);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_resume_callback(int32_t geofence_id, int32_t status)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
- ALOGE("Error in geofence_resume_callback: %d\n", status);
- }
- env->CallVoidMethod(mCallbacksObj, method_reportGeofenceResumeStatus, geofence_id, status);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-static void gps_geofence_pause_callback(int32_t geofence_id, int32_t status)
-{
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
- ALOGE("Error in geofence_pause_callback: %d\n", status);
- }
- env->CallVoidMethod(mCallbacksObj, method_reportGeofencePauseStatus, geofence_id, status);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-};
-
-GpsGeofenceCallbacks sGpsGeofenceCallbacks = {
- gps_geofence_transition_callback,
- gps_geofence_status_callback,
- gps_geofence_add_callback,
- gps_geofence_remove_callback,
- gps_geofence_pause_callback,
- gps_geofence_resume_callback,
- create_thread_callback,
-};
-
-static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
- int err;
- hw_module_t* module;
-
- method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
- method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
- method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
- method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
- method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
- method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
- method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
- method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
- method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
- "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
- method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");
- method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");
- method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
- method_reportGeofenceTransition = env->GetMethodID(clazz,"reportGeofenceTransition",
- "(IIDDDFFFJIJ)V");
- method_reportGeofenceStatus = env->GetMethodID(clazz,"reportGeofenceStatus",
- "(IIDDDFFFJ)V");
- method_reportGeofenceAddStatus = env->GetMethodID(clazz,"reportGeofenceAddStatus",
- "(II)V");
- method_reportGeofenceRemoveStatus = env->GetMethodID(clazz,"reportGeofenceRemoveStatus",
- "(II)V");
- method_reportGeofenceResumeStatus = env->GetMethodID(clazz,"reportGeofenceResumeStatus",
- "(II)V");
- method_reportGeofencePauseStatus = env->GetMethodID(clazz,"reportGeofencePauseStatus",
- "(II)V");
- method_reportMeasurementData = env->GetMethodID(
- clazz,
- "reportMeasurementData",
- "(Landroid/location/GnssMeasurementsEvent;)V");
- method_reportNavigationMessages = env->GetMethodID(
- clazz,
- "reportNavigationMessage",
- "(Landroid/location/GnssNavigationMessage;)V");
-
- err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
- if (err == 0) {
- hw_device_t* device;
- err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
- if (err == 0) {
- gps_device_t* gps_device = (gps_device_t *)device;
- sGpsInterface = gps_device->get_gps_interface(gps_device);
- }
- }
- if (sGpsInterface) {
- sGpsXtraInterface =
- (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE);
- sAGpsInterface =
- (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
- sGpsNiInterface =
- (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
- sGpsDebugInterface =
- (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE);
- sAGpsRilInterface =
- (const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE);
- sGpsGeofencingInterface =
- (const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE);
- sGpsMeasurementInterface =
- (const GpsMeasurementInterface*)sGpsInterface->get_extension(GPS_MEASUREMENT_INTERFACE);
- sGpsNavigationMessageInterface =
- (const GpsNavigationMessageInterface*)sGpsInterface->get_extension(
- GPS_NAVIGATION_MESSAGE_INTERFACE);
- sGnssConfigurationInterface =
- (const GnssConfigurationInterface*)sGpsInterface->get_extension(
- GNSS_CONFIGURATION_INTERFACE);
- }
-}
-
-static jboolean android_location_GnssLocationProvider_is_supported(
- JNIEnv* /* env */, jclass /* clazz */)
-{
- return (sGpsInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
- JNIEnv* /* env */, jclass /* clazz */)
-{
- return (sAGpsRilInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported(
- JNIEnv* /* env */, jclass /* jclazz */)
-{
- return (sGnssConfigurationInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj)
-{
- // this must be set before calling into the HAL library
- if (!mCallbacksObj)
- mCallbacksObj = env->NewGlobalRef(obj);
-
- // fail if the main interface fails to initialize
- if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
- return JNI_FALSE;
-
- // if XTRA initialization fails we will disable it by sGpsXtraInterface to NULL,
- // but continue to allow the rest of the GPS interface to work.
- if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0)
- sGpsXtraInterface = NULL;
- if (sAGpsInterface)
- sAGpsInterface->init(&sAGpsCallbacks);
- if (sGpsNiInterface)
- sGpsNiInterface->init(&sGpsNiCallbacks);
- if (sAGpsRilInterface)
- sAGpsRilInterface->init(&sAGpsRilCallbacks);
- if (sGpsGeofencingInterface)
- sGpsGeofencingInterface->init(&sGpsGeofenceCallbacks);
-
- return JNI_TRUE;
-}
-
-static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */)
-{
- if (sGpsInterface)
- sGpsInterface->cleanup();
-}
-
-static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */,
- jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy,
- jint preferred_time)
-{
- if (sGpsInterface) {
- if (sGpsInterface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
- preferred_time) == 0) {
- return JNI_TRUE;
- } else {
- return JNI_FALSE;
- }
- }
- else
- return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */)
-{
- if (sGpsInterface) {
- if (sGpsInterface->start() == 0) {
- return JNI_TRUE;
- } else {
- return JNI_FALSE;
- }
- }
- else
- return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */)
-{
- if (sGpsInterface) {
- if (sGpsInterface->stop() == 0) {
- return JNI_TRUE;
- } else {
- return JNI_FALSE;
- }
- }
- else
- return JNI_FALSE;
-}
-
-static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */,
- jobject /* obj */,
- jint flags)
-{
- if (sGpsInterface)
- sGpsInterface->delete_aiding_data(flags);
-}
-
-static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
- jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
- jfloatArray azumArray)
-{
- // this should only be called from within a call to reportSvStatus
- jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
- jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
- jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
- jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
-
- // GNSS SV info.
- for (size_t i = 0; i < sGnssSvListSize; ++i) {
- const GnssSvInfo& info = sGnssSvList[i];
- svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
- (info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
- info.flags;
- cn0s[i] = info.c_n0_dbhz;
- elev[i] = info.elevation;
- azim[i] = info.azimuth;
- }
-
- env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
- env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
- env->ReleaseFloatArrayElements(elevArray, elev, 0);
- env->ReleaseFloatArrayElements(azumArray, azim, 0);
- return (jint) sGnssSvListSize;
-}
-
-static void android_location_GnssLocationProvider_agps_set_reference_location_cellid(
- JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid)
-{
- AGpsRefLocation location;
-
- if (!sAGpsRilInterface) {
- ALOGE("no AGPS RIL interface in agps_set_reference_location_cellid");
- return;
- }
-
- switch(type) {
- case AGPS_REF_LOCATION_TYPE_GSM_CELLID:
- case AGPS_REF_LOCATION_TYPE_UMTS_CELLID:
- location.type = type;
- location.u.cellID.mcc = mcc;
- location.u.cellID.mnc = mnc;
- location.u.cellID.lac = lac;
- location.u.cellID.cid = cid;
- break;
- default:
- ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).",__FUNCTION__,__LINE__);
- return;
- break;
- }
- sAGpsRilInterface->set_ref_location(&location, sizeof(location));
-}
-
-static void android_location_GnssLocationProvider_agps_send_ni_message(JNIEnv* env,
- jobject /* obj */, jbyteArray ni_msg, jint size)
-{
- size_t sz;
-
- if (!sAGpsRilInterface) {
- ALOGE("no AGPS RIL interface in send_ni_message");
- return;
- }
- if (size < 0)
- return;
- sz = (size_t)size;
- jbyte* b = env->GetByteArrayElements(ni_msg, 0);
- sAGpsRilInterface->ni_message((uint8_t *)b,sz);
- env->ReleaseByteArrayElements(ni_msg,b,0);
-}
-
-static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
- jint type, jstring setid_string)
-{
- if (!sAGpsRilInterface) {
- ALOGE("no AGPS RIL interface in agps_set_id");
- return;
- }
-
- const char *setid = env->GetStringUTFChars(setid_string, NULL);
- sAGpsRilInterface->set_set_id(type, setid);
- env->ReleaseStringUTFChars(setid_string, setid);
-}
-
-static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
- jbyteArray nmeaArray, jint buffer_size)
-{
- // this should only be called from within a call to reportNmea
- jbyte* nmea = (jbyte *)env->GetPrimitiveArrayCritical(nmeaArray, 0);
- int length = sNmeaStringLength;
- if (length > buffer_size)
- length = buffer_size;
- memcpy(nmea, sNmeaString, length);
- env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
- return (jint) length;
-}
-
-static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
- jlong time, jlong timeReference, jint uncertainty)
-{
- if (sGpsInterface)
- sGpsInterface->inject_time(time, timeReference, uncertainty);
-}
-
-static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
- jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy)
-{
- if (sGpsInterface)
- sGpsInterface->inject_location(latitude, longitude, accuracy);
-}
-
-static jboolean android_location_GnssLocationProvider_supports_xtra(
- JNIEnv* /* env */, jobject /* obj */)
-{
- return (sGpsXtraInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
- jbyteArray data, jint length)
-{
- if (!sGpsXtraInterface) {
- ALOGE("no XTRA interface in inject_xtra_data");
- return;
- }
-
- jbyte* bytes = (jbyte *)env->GetPrimitiveArrayCritical(data, 0);
- sGpsXtraInterface->inject_xtra_data((char *)bytes, length);
- env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
-}
-
-static void android_location_GnssLocationProvider_agps_data_conn_open(
- JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType)
-{
- if (!sAGpsInterface) {
- ALOGE("no AGPS interface in agps_data_conn_open");
- return;
- }
- if (apn == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
- return;
- }
-
- const char *apnStr = env->GetStringUTFChars(apn, NULL);
-
- size_t interface_size = sAGpsInterface->size;
- if (interface_size == sizeof(AGpsInterface)) {
- sAGpsInterface->data_conn_open_with_apn_ip_type(apnStr, apnIpType);
- } else if (interface_size == sizeof(AGpsInterface_v1)) {
- sAGpsInterface->data_conn_open(apnStr);
- } else {
- ALOGE("Invalid size of AGpsInterface found: %zd.", interface_size);
- }
-
- env->ReleaseStringUTFChars(apn, apnStr);
-}
-
-static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
- jobject /* obj */)
-{
- if (!sAGpsInterface) {
- ALOGE("no AGPS interface in agps_data_conn_closed");
- return;
- }
- sAGpsInterface->data_conn_closed();
-}
-
-static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
- jobject /* obj */)
-{
- if (!sAGpsInterface) {
- ALOGE("no AGPS interface in agps_data_conn_failed");
- return;
- }
- sAGpsInterface->data_conn_failed();
-}
-
-static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
- jint type, jstring hostname, jint port)
-{
- if (!sAGpsInterface) {
- ALOGE("no AGPS interface in set_agps_server");
- return;
- }
- const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
- sAGpsInterface->set_server(type, c_hostname, port);
- env->ReleaseStringUTFChars(hostname, c_hostname);
-}
-
-static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
- jobject /* obj */, jint notifId, jint response)
-{
- if (!sGpsNiInterface) {
- ALOGE("no NI interface in send_ni_response");
- return;
- }
-
- sGpsNiInterface->respond(notifId, response);
-}
-
-static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
- jobject /* obj */) {
- jstring result = NULL;
- if (sGpsDebugInterface) {
- const size_t maxLength = 2047;
- char buffer[maxLength+1];
- size_t length = sGpsDebugInterface->get_internal_state(buffer, maxLength);
- if (length > maxLength) length = maxLength;
- buffer[length] = 0;
- result = env->NewStringUTF(buffer);
- }
- return result;
-}
-
-static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env, jobject /* obj */,
- jboolean connected, jint type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn)
-{
-
- if (sAGpsRilInterface && sAGpsRilInterface->update_network_state) {
- if (extraInfo) {
- const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL);
- sAGpsRilInterface->update_network_state(connected, type, roaming, extraInfoStr);
- env->ReleaseStringUTFChars(extraInfo, extraInfoStr);
- } else {
- sAGpsRilInterface->update_network_state(connected, type, roaming, NULL);
- }
-
- // update_network_availability callback was not included in original AGpsRilInterface
- if (sAGpsRilInterface->size >= sizeof(AGpsRilInterface)
- && sAGpsRilInterface->update_network_availability) {
- const char *c_apn = env->GetStringUTFChars(apn, NULL);
- sAGpsRilInterface->update_network_availability(available, c_apn);
- env->ReleaseStringUTFChars(apn, c_apn);
- }
- }
-}
-
-static jboolean android_location_GnssLocationProvider_is_geofence_supported(
- JNIEnv* /* env */, jobject /* obj */)
-{
- return (sGpsGeofencingInterface != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */,
- jobject /* obj */, jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius,
- jint last_transition, jint monitor_transition, jint notification_responsiveness,
- jint unknown_timer) {
- if (sGpsGeofencingInterface != NULL) {
- sGpsGeofencingInterface->add_geofence_area(geofence_id, latitude, longitude,
- radius, last_transition, monitor_transition, notification_responsiveness,
- unknown_timer);
- return JNI_TRUE;
- } else {
- ALOGE("Geofence interface not available");
- }
- return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */,
- jobject /* obj */, jint geofence_id) {
- if (sGpsGeofencingInterface != NULL) {
- sGpsGeofencingInterface->remove_geofence_area(geofence_id);
- return JNI_TRUE;
- } else {
- ALOGE("Geofence interface not available");
- }
- return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */,
- jobject /* obj */, jint geofence_id) {
- if (sGpsGeofencingInterface != NULL) {
- sGpsGeofencingInterface->pause_geofence(geofence_id);
- return JNI_TRUE;
- } else {
- ALOGE("Geofence interface not available");
- }
- return JNI_FALSE;
-}
-
-static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */,
- jobject /* obj */, jint geofence_id, jint monitor_transition) {
- if (sGpsGeofencingInterface != NULL) {
- sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition);
- return JNI_TRUE;
- } else {
- ALOGE("Geofence interface not available");
- }
- return JNI_FALSE;
-}
-
template<class T>
class JavaMethodHelper {
- public:
- // Helper function to call setter on a Java object.
- static void callJavaMethod(
+ public:
+ // Helper function to call setter on a Java object.
+ static void callJavaMethod(
JNIEnv* env,
jclass clazz,
jobject object,
const char* method_name,
T value);
- private:
+ private:
static const char *const signature_;
};
@@ -1045,20 +136,20 @@
}
class JavaObject {
- public:
- JavaObject(JNIEnv* env, const char* class_name);
- virtual ~JavaObject();
+ public:
+ JavaObject(JNIEnv* env, const char* class_name);
+ virtual ~JavaObject();
- template<class T>
- void callSetter(const char* method_name, T value);
- template<class T>
- void callSetter(const char* method_name, T* value, size_t size);
- jobject get();
+ template<class T>
+ void callSetter(const char* method_name, T value);
+ template<class T>
+ void callSetter(const char* method_name, T* value, size_t size);
+ jobject get();
- private:
- JNIEnv* env_;
- jclass clazz_;
- jobject object_;
+ private:
+ JNIEnv* env_;
+ jclass clazz_;
+ jobject object_;
};
JavaObject::JavaObject(JNIEnv* env, const char* class_name) : env_(env) {
@@ -1081,7 +172,7 @@
void JavaObject::callSetter(
const char* method_name, uint8_t* value, size_t size) {
jbyteArray array = env_->NewByteArray(size);
- env_->SetByteArrayRegion(array, 0, size, (jbyte*) value);
+ env_->SetByteArrayRegion(array, 0, size, reinterpret_cast<jbyte*>(value));
jmethodID method = env_->GetMethodID(
clazz_,
method_name,
@@ -1095,7 +186,6 @@
}
// Define Java method signatures for all known types.
-
template<>
const char *const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
template<>
@@ -1119,209 +209,460 @@
#define SET(setter, value) object.callSetter("set" # setter, (value))
-// If you want to check if a flag is not set, use SET_IF_NOT(FLAG, setter,
-// value) to do that. SET_IF(!FLAG, setter, value) won't compile.
-//
-// This macros generates compilation error if the provided 'flag' is not a
-// single token. For example, 'GNSS_CLOCK_HAS_BIAS' can be accepted, but
-// '!GNSS_CLOCK_HAS_DRIFT' will fail to compile.
-#define SET_IF(flag, setter, value) do { \
- if (flags & flag) { \
- JavaObject& name_check_##flag = object; \
- name_check_##flag.callSetter("set" # setter, (value)); \
- } \
- } while (false)
-#define SET_IF_NOT(flag, setter, value) do { \
- if (!(flags & flag)) { \
- JavaObject& name_check_##flag = object; \
- name_check_##flag.callSetter("set" # setter, (value)); \
- } \
- } while (false)
+static inline jboolean boolToJbool(bool value) {
+ return value ? JNI_TRUE : JNI_FALSE;
+}
-static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
- static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
- JavaObject object(env, "android/location/GnssClock");
- GpsClockFlags flags = clock->flags;
+static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
+ if (env->ExceptionCheck()) {
+ ALOGE("An exception was thrown by callback '%s'.", methodName);
+ LOGE_EX(env);
+ env->ExceptionClear();
+ }
+}
- SET_IF(GPS_CLOCK_HAS_LEAP_SECOND,
- LeapSecond,
- static_cast<int32_t>(clock->leap_second));
+/*
+ * GnssCallback class implements the callback methods for IGnss interface.
+ */
+struct GnssCallback : public IGnssCallback {
+ Return<void> gnssLocationCb(
+ const android::hardware::gnss::V1_0::GnssLocation& location) override;
+ Return<void> gnssStatusCb(const IGnssCallback::GnssStatusValue status) override;
+ Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override;
+ Return<void> gnssNmeaCb(int64_t timestamp, const android::hardware::hidl_string& nmea) override;
+ Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
+ Return<void> gnssAcquireWakelockCb() override;
+ Return<void> gnssReleaseWakelockCb() override;
+ Return<void> gnssRequestTimeCb() override;
+ Return<void> gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;
- // GnssClock only supports the more effective HW_CLOCK type, so type
- // handling and documentation complexity has been removed. To convert the
- // old GPS_CLOCK types (active only in a limited number of older devices),
- // the GPS time information is handled as an always discontinuous HW clock,
- // with the GPS time information put into the full_bias_ns instead - so that
- // time_ns - full_bias_ns = local estimate of GPS time. Additionally, the
- // sign of full_bias_ns and bias_ns has flipped between GpsClock &
- // GnssClock, so that is also handled below.
- switch (clock->type) {
- case GPS_CLOCK_TYPE_UNKNOWN:
- // Clock type unsupported.
- ALOGE("Unknown clock type provided.");
- break;
- case GPS_CLOCK_TYPE_LOCAL_HW_TIME:
- // Already local hardware time. No need to do anything.
- break;
- case GPS_CLOCK_TYPE_GPS_TIME:
- // GPS time, need to convert.
- flags |= GPS_CLOCK_HAS_FULL_BIAS;
- clock->full_bias_ns = clock->time_ns;
- clock->time_ns = 0;
- SET(HardwareClockDiscontinuityCount,
- discontinuity_count_to_handle_old_clock_type++);
- break;
+ static GnssSvInfo sGnssSvList[static_cast<uint32_t>(
+ android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)];
+ static size_t sGnssSvListSize;
+
+ static const char* sNmeaString;
+ static size_t sNmeaStringLength;
+};
+
+IGnssCallback::GnssSvInfo GnssCallback::sGnssSvList[static_cast<uint32_t>(
+ android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)];
+const char* GnssCallback::sNmeaString = nullptr;
+size_t GnssCallback::sNmeaStringLength = 0;
+size_t GnssCallback::sGnssSvListSize = 0;
+
+Return<void> GnssCallback::gnssLocationCb(
+ const ::android::hardware::gnss::V1_0::GnssLocation& location) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportLocation,
+ location.gnssLocationFlags,
+ static_cast<jdouble>(location.latitudeDegrees),
+ static_cast<jdouble>(location.longitudeDegrees),
+ static_cast<jdouble>(location.altitudeMeters),
+ static_cast<jfloat>(location.speedMetersPerSec),
+ static_cast<jfloat>(location.bearingDegrees),
+ static_cast<jfloat>(location.accuracyMeters),
+ static_cast<jlong>(location.timestamp));
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssCallback::gnssStatusCb(const IGnssCallback::GnssStatusValue status) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_reportStatus, status);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssCallback::gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+ sGnssSvListSize = svStatus.numSvs;
+ if (sGnssSvListSize > static_cast<uint32_t>(
+ android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)) {
+ ALOGD("Too many satellites %zd. Clamps to %u.", sGnssSvListSize,
+ static_cast<uint32_t>(android::hardware::gnss::V1_0::GnssMax::SVS_COUNT));
+ sGnssSvListSize = static_cast<uint32_t>(android::hardware::gnss::V1_0::GnssMax::SVS_COUNT);
}
- SET(TimeNanos, clock->time_ns);
- SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY,
- TimeUncertaintyNanos,
- clock->time_uncertainty_ns);
-
- // Definition of sign for full_bias_ns & bias_ns has been changed since N,
- // so flip signs here.
- SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, -(clock->full_bias_ns));
- SET_IF(GPS_CLOCK_HAS_BIAS, BiasNanos, -(clock->bias_ns));
-
- SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY,
- BiasUncertaintyNanos,
- clock->bias_uncertainty_ns);
- SET_IF(GPS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
- SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY,
- DriftUncertaintyNanosPerSecond,
- clock->drift_uncertainty_nsps);
-
- return object.get();
-}
-
-static jobject translate_gnss_clock(JNIEnv* env, GnssClock* clock) {
- JavaObject object(env, "android/location/GnssClock");
- GnssClockFlags flags = clock->flags;
-
- SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
- LeapSecond,
- static_cast<int32_t>(clock->leap_second));
- SET(TimeNanos, clock->time_ns);
- SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
- TimeUncertaintyNanos,
- clock->time_uncertainty_ns);
- SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
- SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
- SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
- BiasUncertaintyNanos,
- clock->bias_uncertainty_ns);
- SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
- SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
- DriftUncertaintyNanosPerSecond,
- clock->drift_uncertainty_nsps);
-
- SET(HardwareClockDiscontinuityCount, clock->hw_clock_discontinuity_count);
-
- return object.get();
-}
-
-static jobject translate_gps_measurement(JNIEnv* env,
- GpsMeasurement* measurement) {
- JavaObject object(env, "android/location/GnssMeasurement");
- GpsMeasurementFlags flags = measurement->flags;
- SET(Svid, static_cast<int32_t>(measurement->prn));
- if (measurement->prn >= 1 && measurement->prn <= 32) {
- SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
- } else {
- ALOGD("Unknown constellation type with Svid = %d.", measurement->prn);
- SET(ConstellationType,
- static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
+ // Copy GNSS SV info into sGnssSvList, if any.
+ if (svStatus.numSvs > 0) {
+ memcpy(sGnssSvList, svStatus.gnssSvList.data(), sizeof(GnssSvInfo) * sGnssSvListSize);
}
- SET(TimeOffsetNanos, measurement->time_offset_ns);
- SET(State, static_cast<int32_t>(measurement->state));
- SET(ReceivedSvTimeNanos, measurement->received_gps_tow_ns);
- SET(ReceivedSvTimeUncertaintyNanos,
- measurement->received_gps_tow_uncertainty_ns);
- SET(Cn0DbHz, measurement->c_n0_dbhz);
- SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
- SET(PseudorangeRateUncertaintyMetersPerSecond,
- measurement->pseudorange_rate_uncertainty_mps);
- SET(AccumulatedDeltaRangeState,
- static_cast<int32_t>(measurement->accumulated_delta_range_state));
- SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
- SET(AccumulatedDeltaRangeUncertaintyMeters,
- measurement->accumulated_delta_range_uncertainty_m);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
- CarrierFrequencyHz,
- measurement->carrier_frequency_hz);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
- CarrierCycles,
- measurement->carrier_cycles);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
- CarrierPhase,
- measurement->carrier_phase);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
- CarrierPhaseUncertainty,
- measurement->carrier_phase_uncertainty);
- SET(MultipathIndicator,
- static_cast<int32_t>(measurement->multipath_indicator));
- SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
- return object.get();
+ env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
}
-static jobject translate_gnss_measurement(JNIEnv* env,
- GnssMeasurement* measurement) {
+Return<void> GnssCallback::gnssNmeaCb(
+ int64_t timestamp, const ::android::hardware::hidl_string& nmea) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ /*
+ * The Java code will call back to read these values.
+ * We do this to avoid creating unnecessary String objects.
+ */
+ sNmeaString = nmea.c_str();
+ sNmeaStringLength = nmea.size();
+
+ env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
+ ALOGD("%s: %du\n", __func__, capabilities);
+
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssCallback::gnssAcquireWakelockCb() {
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
+ return Void();
+}
+
+Return<void> GnssCallback::gnssReleaseWakelockCb() {
+ release_wake_lock(WAKE_LOCK_NAME);
+ return Void();
+}
+
+Return<void> GnssCallback::gnssRequestTimeCb() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssCallback::gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) {
+ ALOGD("%s: yearOfHw=%d\n", __func__, info.yearOfHw);
+
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
+ info.yearOfHw);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+class GnssXtraCallback : public IGnssXtraCallback {
+ Return<void> downloadRequestCb() override;
+};
+
+/*
+ * GnssXtraCallback class implements the callback methods for the IGnssXtra
+ * interface.
+ */
+Return<void> GnssXtraCallback::downloadRequestCb() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+/*
+ * GnssGeofenceCallback class implements the callback methods for the
+ * IGnssGeofence interface.
+ */
+struct GnssGeofenceCallback : public IGnssGeofenceCallback {
+ // Methods from ::android::hardware::gps::V1_0::IGnssGeofenceCallback follow.
+ Return<void> gnssGeofenceTransitionCb(
+ int32_t geofenceId,
+ const android::hardware::gnss::V1_0::GnssLocation& location,
+ GeofenceTransition transition,
+ hardware::gnss::V1_0::GnssUtcTime timestamp) override;
+ Return<void> gnssGeofenceStatusCb(
+ GeofenceAvailability status,
+ const android::hardware::gnss::V1_0::GnssLocation& location) override;
+ Return<void> gnssGeofenceAddCb(int32_t geofenceId,
+ GeofenceStatus status) override;
+ Return<void> gnssGeofenceRemoveCb(int32_t geofenceId,
+ GeofenceStatus status) override;
+ Return<void> gnssGeofencePauseCb(int32_t geofenceId,
+ GeofenceStatus status) override;
+ Return<void> gnssGeofenceResumeCb(int32_t geofenceId,
+ GeofenceStatus status) override;
+};
+
+Return<void> GnssGeofenceCallback::gnssGeofenceTransitionCb(
+ int32_t geofenceId,
+ const android::hardware::gnss::V1_0::GnssLocation& location,
+ GeofenceTransition transition,
+ hardware::gnss::V1_0::GnssUtcTime timestamp) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportGeofenceTransition,
+ geofenceId,
+ location.gnssLocationFlags,
+ static_cast<jdouble>(location.latitudeDegrees),
+ static_cast<jdouble>(location.longitudeDegrees),
+ static_cast<jdouble>(location.altitudeMeters),
+ static_cast<jfloat>(location.speedMetersPerSec),
+ static_cast<jfloat>(location.bearingDegrees),
+ static_cast<jfloat>(location.accuracyMeters),
+ static_cast<jlong>(location.timestamp),
+ transition,
+ timestamp);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceStatusCb(
+ GeofenceAvailability status,
+ const android::hardware::gnss::V1_0::GnssLocation& location) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportGeofenceStatus,
+ status,
+ location.gnssLocationFlags,
+ static_cast<jdouble>(location.latitudeDegrees),
+ static_cast<jdouble>(location.longitudeDegrees),
+ static_cast<jdouble>(location.altitudeMeters),
+ static_cast<jfloat>(location.speedMetersPerSec),
+ static_cast<jfloat>(location.bearingDegrees),
+ static_cast<jfloat>(location.accuracyMeters),
+ static_cast<jlong>(location.timestamp));
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceAddCb(int32_t geofenceId,
+ GeofenceStatus status) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+ ALOGE("%s: Error in adding a Geofence: %d\n", __func__, status);
+ }
+
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportGeofenceAddStatus,
+ geofenceId,
+ status);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceRemoveCb(int32_t geofenceId,
+ GeofenceStatus status) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+ ALOGE("%s: Error in removing a Geofence: %d\n", __func__, status);
+ }
+
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportGeofenceRemoveStatus,
+ geofenceId, status);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofencePauseCb(int32_t geofenceId,
+ GeofenceStatus status) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+ ALOGE("%s: Error in pausing Geofence: %d\n", __func__, status);
+ }
+
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportGeofencePauseStatus,
+ geofenceId, status);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceResumeCb(int32_t geofenceId,
+ GeofenceStatus status) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+ ALOGE("%s: Error in resuming Geofence: %d\n", __func__, status);
+ }
+
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportGeofenceResumeStatus,
+ geofenceId, status);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+/*
+ * GnssNavigationMessageCallback interface implements the callback methods
+ * required by the IGnssNavigationMessage interface.
+ */
+struct GnssNavigationMessageCallback : public IGnssNavigationMessageCallback {
+ /*
+ * Methods from ::android::hardware::gps::V1_0::IGnssNavigationMessageCallback
+ * follow.
+ */
+ Return<void> gnssNavigationMessageCb(
+ const IGnssNavigationMessageCallback::GnssNavigationMessage& message) override;
+};
+
+Return<void> GnssNavigationMessageCallback::gnssNavigationMessageCb(
+ const IGnssNavigationMessageCallback::GnssNavigationMessage& message) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+ size_t dataLength = message.data.size();
+
+ std::vector<uint8_t> navigationData = message.data;
+ uint8_t* data = &(navigationData[0]);
+ if (dataLength == 0 || data == NULL) {
+ ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data,
+ dataLength);
+ return Void();
+ }
+
+ JavaObject object(env, "android/location/GnssNavigationMessage");
+ SET(Type, static_cast<int32_t>(message.type));
+ SET(Svid, static_cast<int32_t>(message.svid));
+ SET(MessageId, static_cast<int32_t>(message.messageId));
+ SET(SubmessageId, static_cast<int32_t>(message.submessageId));
+ object.callSetter("setData", data, dataLength);
+ SET(Status, static_cast<int32_t>(message.status));
+
+ jobject navigationMessage = object.get();
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportNavigationMessages,
+ navigationMessage);
+ env->DeleteLocalRef(navigationMessage);
+ return Void();
+}
+
+/*
+ * GnssMeasurementCallback implements the callback methods required for the
+ * GnssMeasurement interface.
+ */
+struct GnssMeasurementCallback : public IGnssMeasurementCallback {
+ Return<void> GnssMeasurementCb(const IGnssMeasurementCallback::GnssData& data);
+ private:
+ jobject translateGnssMeasurement(
+ JNIEnv* env, const IGnssMeasurementCallback::GnssMeasurement* measurement);
+ jobject translateGnssClock(
+ JNIEnv* env, const IGnssMeasurementCallback::GnssClock* clock);
+ jobjectArray translateGnssMeasurements(
+ JNIEnv* env,
+ const IGnssMeasurementCallback::GnssMeasurement* measurements,
+ size_t count);
+ void setMeasurementData(JNIEnv* env, jobject clock, jobjectArray measurementArray);
+};
+
+
+Return<void> GnssMeasurementCallback::GnssMeasurementCb(
+ const IGnssMeasurementCallback::GnssData& data) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+ jobject clock;
+ jobjectArray measurementArray;
+
+ clock = translateGnssClock(env, &data.clock);
+ measurementArray = translateGnssMeasurements(
+ env, data.measurements.data(), data.measurementCount);
+ setMeasurementData(env, clock, measurementArray);
+
+ env->DeleteLocalRef(clock);
+ env->DeleteLocalRef(measurementArray);
+ return Void();
+}
+
+jobject GnssMeasurementCallback::translateGnssMeasurement(
+ JNIEnv* env, const IGnssMeasurementCallback::GnssMeasurement* measurement) {
JavaObject object(env, "android/location/GnssMeasurement");
- GnssMeasurementFlags flags = measurement->flags;
+ uint32_t flags = static_cast<uint32_t>(measurement->flags);
SET(Svid, static_cast<int32_t>(measurement->svid));
SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
- SET(TimeOffsetNanos, measurement->time_offset_ns);
+ SET(TimeOffsetNanos, measurement->timeOffsetNs);
SET(State, static_cast<int32_t>(measurement->state));
- SET(ReceivedSvTimeNanos, measurement->received_sv_time_in_ns);
+ SET(ReceivedSvTimeNanos, measurement->receivedSvTimeInNs);
SET(ReceivedSvTimeUncertaintyNanos,
- measurement->received_sv_time_uncertainty_in_ns);
- SET(Cn0DbHz, measurement->c_n0_dbhz);
- SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
+ measurement->receivedSvTimeUncertaintyInNs);
+ SET(Cn0DbHz, measurement->cN0DbHz);
+ SET(PseudorangeRateMetersPerSecond, measurement->pseudorangeRateMps);
SET(PseudorangeRateUncertaintyMetersPerSecond,
- measurement->pseudorange_rate_uncertainty_mps);
+ measurement->pseudorangeRateUncertaintyMps);
SET(AccumulatedDeltaRangeState,
- static_cast<int32_t>(measurement->accumulated_delta_range_state));
- SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
+ (static_cast<int32_t>(measurement->accumulatedDeltaRangeState)));
+ SET(AccumulatedDeltaRangeMeters, measurement->accumulatedDeltaRangeM);
SET(AccumulatedDeltaRangeUncertaintyMeters,
- measurement->accumulated_delta_range_uncertainty_m);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
- CarrierFrequencyHz,
- measurement->carrier_frequency_hz);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
- CarrierCycles,
- measurement->carrier_cycles);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
- CarrierPhase,
- measurement->carrier_phase);
- SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
- CarrierPhaseUncertainty,
- measurement->carrier_phase_uncertainty);
- SET(MultipathIndicator,
- static_cast<int32_t>(measurement->multipath_indicator));
- SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
+ measurement->accumulatedDeltaRangeUncertaintyM);
+
+ if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_FREQUENCY)) {
+ SET(CarrierFrequencyHz, measurement->carrierFrequencyHz);
+ }
+
+ if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_PHASE)) {
+ SET(CarrierPhase, measurement->carrierPhase);
+ }
+
+ if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY)) {
+ SET(CarrierPhaseUncertainty, measurement->carrierPhaseUncertainty);
+ }
+
+ SET(MultipathIndicator, static_cast<int32_t>(measurement->multipathIndicator));
+
+ if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_SNR)) {
+ SET(SnrInDb, measurement->snrDb);
+ }
return object.get();
}
-static jobjectArray translate_gps_measurements(JNIEnv* env,
- GpsMeasurement* measurements,
- size_t count) {
+jobject GnssMeasurementCallback::translateGnssClock(
+ JNIEnv* env, const IGnssMeasurementCallback::GnssClock* clock) {
+ JavaObject object(env, "android/location/GnssClock");
+
+ uint32_t flags = static_cast<uint32_t>(clock->gnssClockFlags);
+ if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_LEAP_SECOND)) {
+ SET(LeapSecond, static_cast<int32_t>(clock->leapSecond));
+ }
+
+ if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_TIME_UNCERTAINTY)) {
+ SET(TimeUncertaintyNanos, clock->timeUncertaintyNs);
+ }
+
+ if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_FULL_BIAS)) {
+ SET(FullBiasNanos, clock->fullBiasNs);
+ }
+
+ if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS)) {
+ SET(BiasNanos, clock->biasNs);
+ }
+
+ if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS_UNCERTAINTY)) {
+ SET(BiasUncertaintyNanos, clock->biasUncertaintyNs);
+ }
+
+ if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT)) {
+ SET(DriftNanosPerSecond, clock->driftNsps);
+ }
+
+ if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT_UNCERTAINTY)) {
+ SET(DriftUncertaintyNanosPerSecond, clock->driftUncertaintyNsps);
+ }
+
+ SET(TimeNanos, clock->timeNs);
+ SET(HardwareClockDiscontinuityCount, clock->hwClockDiscontinuityCount);
+
+ return object.get();
+}
+
+jobjectArray GnssMeasurementCallback::translateGnssMeasurements(JNIEnv* env,
+ const IGnssMeasurementCallback::GnssMeasurement*
+ measurements, size_t count) {
if (count == 0) {
return NULL;
}
- jclass gnssMeasurementClass = env->FindClass(
- "android/location/GnssMeasurement");
+ jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
jobjectArray gnssMeasurementArray = env->NewObjectArray(
count,
gnssMeasurementClass,
NULL /* initialElement */);
for (uint16_t i = 0; i < count; ++i) {
- jobject gnssMeasurement = translate_gps_measurement(
+ jobject gnssMeasurement = translateGnssMeasurement(
env,
&measurements[i]);
env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
@@ -1332,130 +673,789 @@
return gnssMeasurementArray;
}
-static jobjectArray translate_gnss_measurements(JNIEnv* env,
- GnssMeasurement* measurements,
- size_t count) {
- if (count == 0) {
- return NULL;
- }
+void GnssMeasurementCallback::setMeasurementData(JNIEnv* env, jobject clock,
+ jobjectArray measurementArray) {
+ jclass gnssMeasurementsEventClass =
+ env->FindClass("android/location/GnssMeasurementsEvent");
+ jmethodID gnssMeasurementsEventCtor =
+ env->GetMethodID(
+ gnssMeasurementsEventClass,
+ "<init>",
+ "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
- jclass gnssMeasurementClass = env->FindClass(
- "android/location/GnssMeasurement");
- jobjectArray gnssMeasurementArray = env->NewObjectArray(
- count,
- gnssMeasurementClass,
- NULL /* initialElement */);
+ jobject gnssMeasurementsEvent = env->NewObject(gnssMeasurementsEventClass,
+ gnssMeasurementsEventCtor,
+ clock,
+ measurementArray);
- for (uint16_t i = 0; i < count; ++i) {
- jobject gnssMeasurement = translate_gnss_measurement(
- env,
- &measurements[i]);
- env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
- env->DeleteLocalRef(gnssMeasurement);
- }
-
- env->DeleteLocalRef(gnssMeasurementClass);
- return gnssMeasurementArray;
-}
-
-static void set_measurement_data(JNIEnv *env,
- jobject clock,
- jobjectArray measurementArray) {
- jclass gnssMeasurementsEventClass = env->FindClass(
- "android/location/GnssMeasurementsEvent");
- jmethodID gnssMeasurementsEventCtor = env->GetMethodID(
- gnssMeasurementsEventClass,
- "<init>",
- "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
-
- jobject gnssMeasurementsEvent = env->NewObject(
- gnssMeasurementsEventClass,
- gnssMeasurementsEventCtor,
- clock,
- measurementArray);
- env->CallVoidMethod(mCallbacksObj,
- method_reportMeasurementData,
- gnssMeasurementsEvent);
+ env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData,
+ gnssMeasurementsEvent);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
env->DeleteLocalRef(gnssMeasurementsEventClass);
env->DeleteLocalRef(gnssMeasurementsEvent);
}
-static void measurement_callback(GpsData* data) {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (data == NULL) {
- ALOGE("Invalid data provided to gps_measurement_callback");
- return;
- }
- if (data->size != sizeof(GpsData)) {
- ALOGE("Invalid GpsData size found in gps_measurement_callback, "
- "size=%zd",
- data->size);
- return;
- }
-
- jobject clock;
- jobjectArray measurementArray;
- clock = translate_gps_clock(env, &data->clock);
- measurementArray = translate_gps_measurements(
- env, data->measurements, data->measurement_count);
- set_measurement_data(env, clock, measurementArray);
-
- env->DeleteLocalRef(clock);
- env->DeleteLocalRef(measurementArray);
-}
-
-static void gnss_measurement_callback(GnssData* data) {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (data == NULL) {
- ALOGE("Invalid data provided to gps_measurement_callback");
- return;
- }
- if (data->size != sizeof(GnssData)) {
- ALOGE("Invalid GnssData size found in gnss_measurement_callback, "
- "size=%zd",
- data->size);
- return;
- }
-
- jobject clock;
- jobjectArray measurementArray;
- clock = translate_gnss_clock(env, &data->clock);
- measurementArray = translate_gnss_measurements(
- env, data->measurements, data->measurement_count);
- set_measurement_data(env, clock, measurementArray);
-
- env->DeleteLocalRef(clock);
- env->DeleteLocalRef(measurementArray);
-}
-
-GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
- sizeof(GpsMeasurementCallbacks),
- measurement_callback,
- gnss_measurement_callback,
+/*
+ * GnssNiCallback implements callback methods required by the IGnssNi interface.
+ */
+struct GnssNiCallback : public IGnssNiCallback {
+ Return<void> niNotifyCb(const IGnssNiCallback::GnssNiNotification& notification)
+ override;
};
+Return<void> GnssNiCallback::niNotifyCb(
+ const IGnssNiCallback::GnssNiNotification& notification) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ jstring requestorId = env->NewStringUTF(notification.requestorId.c_str());
+ jstring text = env->NewStringUTF(notification.notificationMessage.c_str());
+
+ if (requestorId && text) {
+ env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
+ notification.notificationId, notification.niType,
+ notification.notifyFlags, notification.timeoutSec,
+ notification.defaultResponse, requestorId, text,
+ notification.requestorIdEncoding,
+ notification.notificationIdEncoding);
+ } else {
+ ALOGE("%s: OOM Error\n", __func__);
+ }
+
+ if (requestorId) {
+ env->DeleteLocalRef(requestorId);
+ }
+
+ if (text) {
+ env->DeleteLocalRef(text);
+ }
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+/*
+ * AGnssCallback implements callback methods required by the IAGnss interface.
+ */
+struct AGnssCallback : public IAGnssCallback {
+ // Methods from ::android::hardware::gps::V1_0::IAGnssCallback follow.
+ Return<void> agnssStatusIpV6Cb(
+ const IAGnssCallback::AGnssStatusIpV6& agps_status) override;
+
+ Return<void> agnssStatusIpV4Cb(
+ const IAGnssCallback::AGnssStatusIpV4& agps_status) override;
+ private:
+ jbyteArray convertToIpV4(uint32_t ip);
+};
+
+Return<void> AGnssCallback::agnssStatusIpV6Cb(
+ const IAGnssCallback::AGnssStatusIpV6& agps_status) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ jbyteArray byteArray = NULL;
+ bool isSupported = false;
+
+ byteArray = env->NewByteArray(16);
+ if (byteArray != NULL) {
+ env->SetByteArrayRegion(byteArray, 0, 16,
+ (const jbyte*)(agps_status.ipV6Addr.data()));
+ isSupported = true;
+ } else {
+ ALOGE("Unable to allocate byte array for IPv6 address.");
+ }
+
+ IF_ALOGD() {
+ // log the IP for reference in case there is a bogus value pushed by HAL
+ char str[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, agps_status.ipV6Addr.data(), str, INET6_ADDRSTRLEN);
+ ALOGD("AGPS IP is v6: %s", str);
+ }
+
+ jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
+ ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
+ env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus,
+ agps_status.type, agps_status.status, byteArray);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+
+ if (byteArray) {
+ env->DeleteLocalRef(byteArray);
+ }
+
+ return Void();
+}
+
+Return<void> AGnssCallback::agnssStatusIpV4Cb(
+ const IAGnssCallback::AGnssStatusIpV4& agps_status) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ jbyteArray byteArray = NULL;
+
+ uint32_t ipAddr = agps_status.ipV4Addr;
+ byteArray = convertToIpV4(ipAddr);
+
+ IF_ALOGD() {
+ /*
+ * log the IP for reference in case there is a bogus value pushed by
+ * HAL.
+ */
+ char str[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN);
+ ALOGD("AGPS IP is v4: %s", str);
+ }
+
+ jsize byteArrayLength =
+ byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
+ ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
+ env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus,
+ agps_status.type, agps_status.status, byteArray);
+
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+
+ if (byteArray) {
+ env->DeleteLocalRef(byteArray);
+ }
+ return Void();
+}
+
+jbyteArray AGnssCallback::convertToIpV4(uint32_t ip) {
+ if (INADDR_NONE == ip) {
+ return NULL;
+ }
+
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ jbyteArray byteArray = env->NewByteArray(4);
+ if (byteArray == NULL) {
+ ALOGE("Unable to allocate byte array for IPv4 address");
+ return NULL;
+ }
+
+ jbyte ipv4[4];
+ ALOGV("Converting IPv4 address byte array (net_order) %x", ip);
+ memcpy(ipv4, &ip, sizeof(ipv4));
+ env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*)ipv4);
+ return byteArray;
+}
+
+/*
+ * AGnssRilCallback implements the callback methods required by the AGnssRil
+ * interface.
+ */
+struct AGnssRilCallback : IAGnssRilCallback {
+ Return<void> requestSetIdCb(IAGnssRilCallback::ID setIdFlag) override;
+ Return<void> requestRefLocCb() override;
+};
+
+Return<void> AGnssRilCallback::requestSetIdCb(IAGnssRilCallback::ID setIdFlag) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_requestSetID, setIdFlag);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+Return<void> AGnssRilCallback::requestRefLocCb() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_requestRefLocation);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
+ method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
+ method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
+ method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
+ method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
+ method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
+ method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
+ method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
+ method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
+ method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
+ "(IIIIILjava/lang/String;Ljava/lang/String;II)V");
+ method_requestRefLocation = env->GetMethodID(clazz, "requestRefLocation", "()V");
+ method_requestSetID = env->GetMethodID(clazz, "requestSetID", "(I)V");
+ method_requestUtcTime = env->GetMethodID(clazz, "requestUtcTime", "()V");
+ method_reportGeofenceTransition = env->GetMethodID(clazz, "reportGeofenceTransition",
+ "(IIDDDFFFJIJ)V");
+ method_reportGeofenceStatus = env->GetMethodID(clazz, "reportGeofenceStatus",
+ "(IIDDDFFFJ)V");
+ method_reportGeofenceAddStatus = env->GetMethodID(clazz, "reportGeofenceAddStatus",
+ "(II)V");
+ method_reportGeofenceRemoveStatus = env->GetMethodID(clazz, "reportGeofenceRemoveStatus",
+ "(II)V");
+ method_reportGeofenceResumeStatus = env->GetMethodID(clazz, "reportGeofenceResumeStatus",
+ "(II)V");
+ method_reportGeofencePauseStatus = env->GetMethodID(clazz, "reportGeofencePauseStatus",
+ "(II)V");
+ method_reportMeasurementData = env->GetMethodID(
+ clazz,
+ "reportMeasurementData",
+ "(Landroid/location/GnssMeasurementsEvent;)V");
+ method_reportNavigationMessages = env->GetMethodID(
+ clazz,
+ "reportNavigationMessage",
+ "(Landroid/location/GnssNavigationMessage;)V");
+
+ // TODO(b/31632518)
+ gnssHal = IGnss::getService("gnss");
+ if (gnssHal != nullptr) {
+ auto result = gnssHal->getExtensionXtra([](const sp<IGnssXtra>& xtraIface) {
+ gnssXtraIface = xtraIface;
+ });
+
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to Xtra");
+ }
+
+ result = gnssHal->getExtensionAGnssRil([](const sp<IAGnssRil>& rilIface) {
+ agnssRilIface = rilIface;
+ });
+
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to AGnssRil");
+ }
+
+ result = gnssHal->getExtensionAGnss([](const sp<IAGnss>& assistedGnssIface) {
+ agnssIface = assistedGnssIface;
+ });
+
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to AGnss");
+ }
+
+ result = gnssHal->getExtensionGnssNavigationMessage(
+ [](const sp<IGnssNavigationMessage>& navigationMessageIface) {
+ gnssNavigationMessageIface = navigationMessageIface;
+ });
+
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to GnssNavigationMessage");
+ }
+
+ result = gnssHal->getExtensionGnssMeasurement([](
+ const sp<IGnssMeasurement>& measurementIface) {
+ gnssMeasurementIface = measurementIface;
+ });
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to GnssMeasurement");
+ }
+
+ result = gnssHal->getExtensionGnssDebug([](const sp<IGnssDebug>& debugIface) {
+ gnssDebugIface = debugIface;
+ });
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to GnssDebug");
+ }
+
+ result = gnssHal->getExtensionGnssNi([](const sp<IGnssNi>& niIface) {
+ gnssNiIface = niIface;
+ });
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to GnssNi");
+ }
+
+ result = gnssHal->getExtensionGnssConfiguration([](const sp<IGnssConfiguration>& configIface) {
+ gnssConfigurationIface = configIface;
+ });
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to GnssConfiguration");
+ }
+
+ result = gnssHal->getExtensionGnssGeofencing([](const sp<IGnssGeofencing>& geofenceIface) {
+ gnssGeofencingIface = geofenceIface;
+ });
+ if (!result.getStatus().isOk()) {
+ ALOGD("Unable to get a handle to GnssGeofencing");
+ }
+
+ } else {
+ ALOGE("Unable to get GPS service\n");
+ }
+ ProcessState::self()->setThreadPoolMaxThreadCount(0);
+ ProcessState::self()->startThreadPool();
+}
+
+static jboolean android_location_GnssLocationProvider_is_supported(
+ JNIEnv* /* env */, jclass /* clazz */) {
+ return (gnssHal != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
+ JNIEnv* /* env */, jclass /* clazz */) {
+ return (agnssRilIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported(
+ JNIEnv* /* env */, jclass /* jclazz */) {
+ return (gnssConfigurationIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj) {
+ /*
+ * This must be set before calling into the HAL library.
+ */
+ if (!mCallbacksObj)
+ mCallbacksObj = env->NewGlobalRef(obj);
+
+ sp<IGnssCallback> gnssCbIface = new GnssCallback();
+ /*
+ * Fail if the main interface fails to initialize
+ */
+ if (gnssHal == nullptr) {
+ ALOGE("Unable to Initialize GNSS HAL\n");
+ return JNI_FALSE;
+ }
+
+ auto result = gnssHal->setCallback(gnssCbIface);
+ if ((!result) || (!result.getStatus().isOk())) {
+ ALOGE("SetCallback for Gnss Interface fails\n");
+ return JNI_FALSE;
+ }
+
+ sp<IGnssXtraCallback> gnssXtraCbIface = new GnssXtraCallback();
+ if (gnssXtraIface == nullptr) {
+ ALOGE("Unable to initialize GNSS Xtra interface\n");
+ } else {
+ result = gnssXtraIface->setCallback(gnssXtraCbIface);
+ if ((!result) || (!result.getStatus().isOk())) {
+ gnssXtraIface = nullptr;
+ ALOGE("SetCallback for Gnss Xtra Interface fails\n");
+ }
+ }
+
+ sp<IAGnssCallback> aGnssCbIface = new AGnssCallback();
+ if (agnssIface != nullptr) {
+ agnssIface->setCallback(aGnssCbIface);
+ } else {
+ ALOGE("Unable to Initialize AGnss interface\n");
+ }
+
+ sp<IGnssGeofenceCallback> gnssGeofencingCbIface = new GnssGeofenceCallback();
+ if (gnssGeofencingIface != nullptr) {
+ gnssGeofencingIface->setCallback(gnssGeofencingCbIface);
+ } else {
+ ALOGE("Unable to initialize GNSS Geofencing interface\n");
+ }
+
+ sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
+ if (gnssNiCbIface != nullptr) {
+ gnssNiIface->setCallback(gnssNiCbIface);
+ } else {
+ ALOGE("Unable to initialize GNSS NI interface\n");
+ }
+
+ return JNI_TRUE;
+}
+
+static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */) {
+ if (gnssHal != nullptr) {
+ gnssHal->cleanup();
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */,
+ jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy,
+ jint preferred_time) {
+ if (gnssHal != nullptr) {
+ auto result = gnssHal->setPositionMode(static_cast<IGnss::GnssPositionMode>(mode),
+ static_cast<IGnss::GnssPositionRecurrence>(recurrence),
+ min_interval,
+ preferred_accuracy,
+ preferred_time);
+ if (!result.getStatus().isOk()) {
+ ALOGE("%s: GNSS setPositionMode failed\n", __func__);
+ return JNI_FALSE;
+ } else {
+ return result;
+ }
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */) {
+ if (gnssHal != nullptr) {
+ auto result = gnssHal->start();
+ if (!result.getStatus().isOk()) {
+ return JNI_FALSE;
+ } else {
+ return result;
+ }
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */) {
+ if (gnssHal != nullptr) {
+ auto result = gnssHal->stop();
+ if (!result.getStatus().isOk()) {
+ return JNI_FALSE;
+ } else {
+ return result;
+ }
+ } else {
+ return JNI_FALSE;
+ }
+}
+static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */,
+ jobject /* obj */,
+ jint flags) {
+ if (gnssHal != nullptr) {
+ auto result = gnssHal->deleteAidingData(static_cast<IGnss::GnssAidingData>(flags));
+ if (!result.getStatus().isOk()) {
+ ALOGE("Error in deleting aiding data");
+ }
+ }
+}
+
+/*
+ * This enum is used by the read_sv_status method to combine the svid,
+ * constellation and svFlag fields.
+ */
+enum ShiftWidth: uint8_t {
+ SVID_SHIFT_WIDTH = 7,
+ CONSTELLATION_TYPE_SHIFT_WIDTH = 3
+};
+
+static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
+ jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
+ jfloatArray azumArray) {
+ /*
+ * This method should only be called from within a call to reportSvStatus.
+ */
+ jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
+ jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
+ jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
+ jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
+
+ /*
+ * Read GNSS SV info.
+ */
+ for (size_t i = 0; i < GnssCallback::sGnssSvListSize; ++i) {
+ const IGnssCallback::GnssSvInfo& info = GnssCallback::sGnssSvList[i];
+ svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
+ (static_cast<uint32_t>(info.constellation) << CONSTELLATION_TYPE_SHIFT_WIDTH) |
+ static_cast<uint32_t>(info.svFlag);
+ cn0s[i] = info.cN0Dbhz;
+ elev[i] = info.elevationDegrees;
+ azim[i] = info.azimuthDegrees;
+ }
+
+ env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
+ env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
+ env->ReleaseFloatArrayElements(elevArray, elev, 0);
+ env->ReleaseFloatArrayElements(azumArray, azim, 0);
+ return static_cast<jint>(GnssCallback::sGnssSvListSize);
+}
+
+static void android_location_GnssLocationProvider_agps_set_reference_location_cellid(
+ JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid) {
+ IAGnssRil::AGnssRefLocation location;
+
+ if (agnssRilIface == nullptr) {
+ ALOGE("No AGPS RIL interface in agps_set_reference_location_cellid");
+ return;
+ }
+
+ switch (static_cast<IAGnssRil::AGnssRefLocationType>(type)) {
+ case IAGnssRil::AGnssRefLocationType::GSM_CELLID:
+ case IAGnssRil::AGnssRefLocationType::UMTS_CELLID:
+ location.type = static_cast<IAGnssRil::AGnssRefLocationType>(type);
+ location.cellID.mcc = mcc;
+ location.cellID.mnc = mnc;
+ location.cellID.lac = lac;
+ location.cellID.cid = cid;
+ break;
+ default:
+ ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).", __FUNCTION__, __LINE__);
+ return;
+ break;
+ }
+
+ agnssRilIface->setRefLocation(location);
+}
+
+static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
+ jint type, jstring setid_string) {
+ if (agnssRilIface == nullptr) {
+ ALOGE("no AGPS RIL interface in agps_set_id");
+ return;
+ }
+
+ const char *setid = env->GetStringUTFChars(setid_string, NULL);
+ agnssRilIface->setSetId((IAGnssRil::SetIDType)type, setid);
+ env->ReleaseStringUTFChars(setid_string, setid);
+}
+
+static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
+ jbyteArray nmeaArray, jint buffer_size) {
+ // this should only be called from within a call to reportNmea
+ jbyte* nmea = reinterpret_cast<jbyte *>(env->GetPrimitiveArrayCritical(nmeaArray, 0));
+ int length = GnssCallback::sNmeaStringLength;
+ if (length > buffer_size)
+ length = buffer_size;
+ memcpy(nmea, GnssCallback::sNmeaString, length);
+ env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
+ return (jint) length;
+}
+
+static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
+ jlong time, jlong timeReference, jint uncertainty) {
+ if (gnssHal != nullptr) {
+ auto result = gnssHal->injectTime(time, timeReference, uncertainty);
+ if (!result || !result.getStatus().isOk()) {
+ ALOGE("%s: Gnss injectTime() failed", __func__);
+ }
+ }
+}
+
+static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
+ jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy) {
+ if (gnssHal != nullptr) {
+ auto result = gnssHal->injectLocation(latitude, longitude, accuracy);
+ if (!result || !result.getStatus().isOk()) {
+ ALOGE("%s: Gnss injectLocation() failed", __func__);
+ }
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_supports_xtra(
+ JNIEnv* /* env */, jobject /* obj */) {
+ return (gnssXtraIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
+ jbyteArray data, jint length) {
+ if (gnssXtraIface == nullptr) {
+ ALOGE("XTRA Interface not supported");
+ return;
+ }
+
+ jbyte* bytes = reinterpret_cast<jbyte *>(env->GetPrimitiveArrayCritical(data, 0));
+ gnssXtraIface->injectXtraData(std::string((const char*)bytes, length));
+ env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
+}
+
+static void android_location_GnssLocationProvider_agps_data_conn_open(
+ JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType) {
+ if (agnssIface == nullptr) {
+ ALOGE("no AGPS interface in agps_data_conn_open");
+ return;
+ }
+ if (apn == NULL) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ return;
+ }
+
+ const char *apnStr = env->GetStringUTFChars(apn, NULL);
+
+ auto result = agnssIface->dataConnOpen(apnStr, static_cast<IAGnss::ApnIpType>(apnIpType));
+ if ((!result) || (!result.getStatus().isOk())) {
+ ALOGE("%s: Failed to set APN and its IP type", __func__);
+ }
+ env->ReleaseStringUTFChars(apn, apnStr);
+}
+
+static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
+ jobject /* obj */) {
+ if (agnssIface == nullptr) {
+ ALOGE("%s: AGPS interface not supported", __func__);
+ return;
+ }
+
+ auto result = agnssIface->dataConnClosed();
+ if ((!result) || (!result.getStatus().isOk())) {
+ ALOGE("%s: Failed to close AGnss data connection", __func__);
+ }
+}
+
+static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
+ jobject /* obj */) {
+ if (agnssIface == nullptr) {
+ ALOGE("%s: AGPS interface not supported", __func__);
+ return;
+ }
+
+ auto result = agnssIface->dataConnFailed();
+ if ((!result) || (!result.getStatus().isOk())) {
+ ALOGE("%s: Failed to notify unavailability of AGnss data connection", __func__);
+ }
+}
+
+static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
+ jint type, jstring hostname, jint port) {
+ if (agnssIface == nullptr) {
+ ALOGE("no AGPS interface in set_agps_server");
+ return;
+ }
+
+ const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
+ auto result = agnssIface->setServer(static_cast<IAGnssCallback::AGnssType>(type),
+ c_hostname,
+ port);
+ if ((!result) || (!result.getStatus().isOk())) {
+ ALOGE("%s: Failed to set AGnss host name and port", __func__);
+ }
+
+ env->ReleaseStringUTFChars(hostname, c_hostname);
+}
+
+static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
+ jobject /* obj */, jint notifId, jint response) {
+ if (gnssNiIface == nullptr) {
+ ALOGE("no NI interface in send_ni_response");
+ return;
+ }
+
+ gnssNiIface->respond(notifId, static_cast<IGnssNiCallback::GnssUserResponseType>(response));
+}
+
+static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
+ jobject /* obj */) {
+ jstring result = NULL;
+ /*
+ * TODO(b/33089503) : Create a jobject to represent GnssDebug.
+ */
+ if (gnssDebugIface != nullptr) {
+ IGnssDebug::DebugData data;
+ gnssDebugIface->getDebugData([&data](const IGnssDebug::DebugData& debugData) {
+ data = debugData;
+ });
+
+ std::stringstream internalState;
+ if (data.position.valid) {
+ internalState << "Gnss Location Data:: LatitudeDegrees: " << data.position.latitudeDegrees
+ << ", LongitudeDegrees: " << data.position.longitudeDegrees
+ << ", altitudeMeters: " << data.position.altitudeMeters
+ << ", accuracyMeters: " << data.position.accuracyMeters
+ << ", ageSeconds: " << data.position.ageSeconds << std::endl;
+ }
+
+ if (data.time.valid) {
+ internalState << "Gnss Time Data:: timeEstimate: " << data.time.timeEstimate
+ << ", timeUncertaintyNs: " << data.time.timeUncertaintyNs << std::endl;
+ }
+
+ if (data.satelliteDataArray.size() != 0) {
+ internalState << "Satellite Data:: ";
+ }
+
+ for (size_t i = 0; i < data.satelliteDataArray.size(); i++) {
+ internalState << "svid: " << data.satelliteDataArray[i].svid
+ << ", constellation: "
+ << static_cast<uint32_t>(data.satelliteDataArray[i].constellation)
+ << ", ephemerisType: "
+ << static_cast<uint32_t>(data.satelliteDataArray[i].ephemerisType)
+ << ", ephemerisAgeSeconds: "
+ << data.satelliteDataArray[i].ephemerisAgeSeconds << std::endl;
+ }
+ result = env->NewStringUTF(internalState.str().c_str());
+ }
+ return result;
+}
+
+static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env,
+ jobject /* obj */,
+ jboolean connected,
+ jint type,
+ jboolean roaming,
+ jboolean available,
+ jstring extraInfo,
+ jstring apn) {
+ if (agnssRilIface != nullptr) {
+ auto result = agnssRilIface->updateNetworkState(connected,
+ static_cast<IAGnssRil::NetworkType>(type),
+ roaming);
+ if ((!result) || (!result.getStatus().isOk())) {
+ ALOGE("updateNetworkState failed");
+ }
+
+ const char *c_apn = env->GetStringUTFChars(apn, NULL);
+ result = agnssRilIface->updateNetworkAvailability(available, c_apn);
+ if ((!result) || (!result.getStatus().isOk())) {
+ ALOGE("updateNetworkAvailability failed");
+ }
+
+ env->ReleaseStringUTFChars(apn, c_apn);
+ } else {
+ ALOGE("AGnssRilInterface does not exist");
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_is_geofence_supported(
+ JNIEnv* /* env */, jobject /* obj */) {
+ return (gnssGeofencingIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */,
+ jobject /* obj */, jint geofenceId, jdouble latitude, jdouble longitude, jdouble radius,
+ jint last_transition, jint monitor_transition, jint notification_responsiveness,
+ jint unknown_timer) {
+ if (gnssGeofencingIface != nullptr) {
+ auto result = gnssGeofencingIface->addGeofence(
+ geofenceId, latitude, longitude, radius,
+ static_cast<IGnssGeofenceCallback::GeofenceTransition>(last_transition),
+ monitor_transition, notification_responsiveness, unknown_timer);
+ return boolToJbool(result.getStatus().isOk());
+ } else {
+ ALOGE("Geofence Interface not available");
+ }
+ return JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */,
+ jobject /* obj */, jint geofenceId) {
+ if (gnssGeofencingIface != nullptr) {
+ auto result = gnssGeofencingIface->removeGeofence(geofenceId);
+ return boolToJbool(result.getStatus().isOk());
+ } else {
+ ALOGE("Geofence interface not available");
+ }
+ return JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */,
+ jobject /* obj */, jint geofenceId) {
+ if (gnssGeofencingIface != nullptr) {
+ auto result = gnssGeofencingIface->pauseGeofence(geofenceId);
+ return boolToJbool(result.getStatus().isOk());
+ } else {
+ ALOGE("Geofence interface not available");
+ }
+ return JNI_FALSE;
+}
+
+static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */,
+ jobject /* obj */, jint geofenceId, jint monitor_transition) {
+ if (gnssGeofencingIface != nullptr) {
+ auto result = gnssGeofencingIface->resumeGeofence(geofenceId, monitor_transition);
+ return boolToJbool(result.getStatus().isOk());
+ } else {
+ ALOGE("Geofence interface not available");
+ }
+ return JNI_FALSE;
+}
+
static jboolean android_location_GnssLocationProvider_is_measurement_supported(
- JNIEnv* env,
- jclass clazz) {
- if (sGpsMeasurementInterface != NULL) {
+ JNIEnv* env, jclass clazz) {
+ if (gnssMeasurementIface != nullptr) {
return JNI_TRUE;
}
+
return JNI_FALSE;
}
static jboolean android_location_GnssLocationProvider_start_measurement_collection(
JNIEnv* env,
jobject obj) {
- if (sGpsMeasurementInterface == NULL) {
- ALOGE("Measurement interface is not available.");
+ if (gnssMeasurementIface == nullptr) {
+ ALOGE("GNSS Measurement interface is not available.");
return JNI_FALSE;
}
- int result = sGpsMeasurementInterface->init(&sGpsMeasurementCallbacks);
- if (result != GPS_GEOFENCE_OPERATION_SUCCESS) {
- ALOGE("An error has been found on GpsMeasurementInterface::init, status=%d", result);
+ sp<GnssMeasurementCallback> cbIface = new GnssMeasurementCallback();
+ IGnssMeasurement::GnssMeasurementStatus result = gnssMeasurementIface->setCallback(cbIface);
+ if (result != IGnssMeasurement::GnssMeasurementStatus::SUCCESS) {
+ ALOGE("An error has been found on GnssMeasurementInterface::init, status=%d",
+ static_cast<int32_t>(result));
return JNI_FALSE;
+ } else {
+ ALOGD("gnss measurement infc has been enabled");
}
return JNI_TRUE;
@@ -1464,104 +1464,19 @@
static jboolean android_location_GnssLocationProvider_stop_measurement_collection(
JNIEnv* env,
jobject obj) {
- if (sGpsMeasurementInterface == NULL) {
+ if (gnssMeasurementIface == nullptr) {
ALOGE("Measurement interface not available");
return JNI_FALSE;
}
- sGpsMeasurementInterface->close();
- return JNI_TRUE;
+ auto result = gnssMeasurementIface->close();
+ return boolToJbool(result.getStatus().isOk());
}
-static jobject translate_gps_navigation_message(JNIEnv* env, GpsNavigationMessage* message) {
- size_t dataLength = message->data_length;
- uint8_t* data = message->data;
- if (dataLength == 0 || data == NULL) {
- ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
- return NULL;
- }
- JavaObject object(env, "android/location/GnssNavigationMessage");
- SET(Svid, static_cast<int32_t>(message->prn));
- if (message->prn >=1 && message->prn <= 32) {
- SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
- // Legacy driver doesn't set the higher byte to constellation type
- // correctly. Set the higher byte to 'GPS'.
- SET(Type, static_cast<int32_t>(message->type | 0x0100));
- } else {
- ALOGD("Unknown constellation type with Svid = %d.", message->prn);
- SET(ConstellationType,
- static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
- SET(Type, static_cast<int32_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
- }
- SET(MessageId, static_cast<int32_t>(message->message_id));
- SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
- object.callSetter("setData", data, dataLength);
- SET(Status, static_cast<int32_t>(message->status));
- return object.get();
-}
-
-static jobject translate_gnss_navigation_message(
- JNIEnv* env, GnssNavigationMessage* message) {
- size_t dataLength = message->data_length;
- uint8_t* data = message->data;
- if (dataLength == 0 || data == NULL) {
- ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
- return NULL;
- }
- JavaObject object(env, "android/location/GnssNavigationMessage");
- SET(Type, static_cast<int32_t>(message->type));
- SET(Svid, static_cast<int32_t>(message->svid));
- SET(MessageId, static_cast<int32_t>(message->message_id));
- SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
- object.callSetter("setData", data, dataLength);
- SET(Status, static_cast<int32_t>(message->status));
- return object.get();
-}
-
-static void navigation_message_callback(GpsNavigationMessage* message) {
- if (message == NULL) {
- ALOGE("Invalid Navigation Message provided to callback");
- return;
- }
- if (message->size != sizeof(GpsNavigationMessage)) {
- ALOGE("Invalid GpsNavigationMessage size found: %zd", message->size);
- return;
- }
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jobject navigationMessage = translate_gps_navigation_message(env, message);
- env->CallVoidMethod(mCallbacksObj,
- method_reportNavigationMessages,
- navigationMessage);
- env->DeleteLocalRef(navigationMessage);
-}
-
-static void gnss_navigation_message_callback(GnssNavigationMessage* message) {
- if (message == NULL) {
- ALOGE("Invalid Navigation Message provided to callback");
- return;
- }
- if (message->size != sizeof(GnssNavigationMessage)) {
- ALOGE("Invalid GnssNavigationMessage size found: %zd", message->size);
- return;
- }
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jobject navigationMessage = translate_gnss_navigation_message(env, message);
- env->CallVoidMethod(mCallbacksObj,
- method_reportNavigationMessages,
- navigationMessage);
- env->DeleteLocalRef(navigationMessage);
-}
-
-GpsNavigationMessageCallbacks sGpsNavigationMessageCallbacks = {
- sizeof(GpsNavigationMessageCallbacks),
- navigation_message_callback,
- gnss_navigation_message_callback,
-};
-
static jboolean android_location_GnssLocationProvider_is_navigation_message_supported(
JNIEnv* env,
jclass clazz) {
- if(sGpsNavigationMessageInterface != NULL) {
+ if (gnssNavigationMessageIface != nullptr) {
return JNI_TRUE;
}
return JNI_FALSE;
@@ -1570,14 +1485,18 @@
static jboolean android_location_GnssLocationProvider_start_navigation_message_collection(
JNIEnv* env,
jobject obj) {
- if (sGpsNavigationMessageInterface == NULL) {
+ if (gnssNavigationMessageIface == nullptr) {
ALOGE("Navigation Message interface is not available.");
return JNI_FALSE;
}
- int result = sGpsNavigationMessageInterface->init(&sGpsNavigationMessageCallbacks);
- if (result != GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS) {
- ALOGE("An error has been found in %s: %d", __FUNCTION__, result);
+ sp<IGnssNavigationMessageCallback> gnssNavigationMessageCbIface =
+ new GnssNavigationMessageCallback();
+ IGnssNavigationMessage::GnssNavigationMessageStatus result =
+ gnssNavigationMessageIface->setCallback(gnssNavigationMessageCbIface);
+
+ if (result != IGnssNavigationMessage::GnssNavigationMessageStatus::SUCCESS) {
+ ALOGE("An error has been found in %s: %d", __FUNCTION__, static_cast<int32_t>(result));
return JNI_FALSE;
}
@@ -1587,127 +1506,255 @@
static jboolean android_location_GnssLocationProvider_stop_navigation_message_collection(
JNIEnv* env,
jobject obj) {
- if (sGpsNavigationMessageInterface == NULL) {
+ if (gnssNavigationMessageIface == nullptr) {
ALOGE("Navigation Message interface is not available.");
return JNI_FALSE;
}
- sGpsNavigationMessageInterface->close();
- return JNI_TRUE;
+ auto result = gnssNavigationMessageIface->close();
+ return boolToJbool(result.getStatus().isOk());
}
-static void android_location_GnssLocationProvider_configuration_update(JNIEnv* env, jobject obj,
- jstring config_content)
-{
- if (!sGnssConfigurationInterface) {
- ALOGE("no GPS configuration interface in configuraiton_update");
- return;
+static jboolean android_location_GnssLocationProvider_set_emergency_supl_pdn(JNIEnv*,
+ jobject,
+ jint emergencySuplPdn) {
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("no GNSS configuration interface available");
+ return JNI_FALSE;
}
- const char *data = env->GetStringUTFChars(config_content, NULL);
- ALOGD("GPS configuration:\n %s", data);
- sGnssConfigurationInterface->configuration_update(
- data, env->GetStringUTFLength(config_content));
- env->ReleaseStringUTFChars(config_content, data);
+
+ auto result = gnssConfigurationIface->setEmergencySuplPdn(emergencySuplPdn);
+ if (result.getStatus().isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_set_supl_version(JNIEnv*,
+ jobject,
+ jint version) {
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("no GNSS configuration interface available");
+ return JNI_FALSE;
+ }
+ auto result = gnssConfigurationIface->setSuplVersion(version);
+ if (result.getStatus().isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_set_supl_es(JNIEnv*,
+ jobject,
+ jint suplEs) {
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("no GNSS configuration interface available");
+ return JNI_FALSE;
+ }
+
+ auto result = gnssConfigurationIface->setSuplEs(suplEs);
+ if (result.getStatus().isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_set_supl_mode(JNIEnv*,
+ jobject,
+ jint mode) {
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("no GNSS configuration interface available");
+ return JNI_FALSE;
+ }
+
+ auto result = gnssConfigurationIface->setSuplMode(mode);
+ if (result.getStatus().isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_set_gps_lock(JNIEnv*,
+ jobject,
+ jint gpsLock) {
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("no GNSS configuration interface available");
+ return JNI_FALSE;
+ }
+
+ auto result = gnssConfigurationIface->setGpsLock(gpsLock);
+ if (result.getStatus().isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_set_lpp_profile(JNIEnv*,
+ jobject,
+ jint lppProfile) {
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("no GNSS configuration interface available");
+ return JNI_FALSE;
+ }
+
+ auto result = gnssConfigurationIface->setLppProfile(lppProfile);
+
+ if (result.getStatus().isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jboolean android_location_GnssLocationProvider_set_gnss_pos_protocol_select(JNIEnv*,
+ jobject,
+ jint gnssPosProtocol) {
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("no GNSS configuration interface available");
+ return JNI_FALSE;
+ }
+
+ auto result = gnssConfigurationIface->setGlonassPositioningProtocol(gnssPosProtocol);
+ if (result.getStatus().isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
}
static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
- {"class_init_native", "()V", (void *)android_location_GnssLocationProvider_class_init_native},
- {"native_is_supported", "()Z", (void*)android_location_GnssLocationProvider_is_supported},
+ {"class_init_native", "()V", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_class_init_native)},
+ {"native_is_supported", "()Z", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_is_supported)},
{"native_is_agps_ril_supported", "()Z",
- (void*)android_location_GnssLocationProvider_is_agps_ril_supported},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_is_agps_ril_supported)},
{"native_is_gnss_configuration_supported", "()Z",
- (void*)android_location_gpsLocationProvider_is_gnss_configuration_supported},
- {"native_init", "()Z", (void*)android_location_GnssLocationProvider_init},
- {"native_cleanup", "()V", (void*)android_location_GnssLocationProvider_cleanup},
+ reinterpret_cast<void *>(
+ android_location_gpsLocationProvider_is_gnss_configuration_supported)},
+ {"native_init", "()Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_init)},
+ {"native_cleanup", "()V", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_cleanup)},
{"native_set_position_mode",
"(IIIII)Z",
- (void*)android_location_GnssLocationProvider_set_position_mode},
- {"native_start", "()Z", (void*)android_location_GnssLocationProvider_start},
- {"native_stop", "()Z", (void*)android_location_GnssLocationProvider_stop},
+ reinterpret_cast<void*>(android_location_GnssLocationProvider_set_position_mode)},
+ {"native_start", "()Z", reinterpret_cast<void*>(android_location_GnssLocationProvider_start)},
+ {"native_stop", "()Z", reinterpret_cast<void*>(android_location_GnssLocationProvider_stop)},
{"native_delete_aiding_data",
"(I)V",
- (void*)android_location_GnssLocationProvider_delete_aiding_data},
+ reinterpret_cast<void*>(android_location_GnssLocationProvider_delete_aiding_data)},
{"native_read_sv_status",
"([I[F[F[F)I",
- (void*)android_location_GnssLocationProvider_read_sv_status},
- {"native_read_nmea", "([BI)I", (void*)android_location_GnssLocationProvider_read_nmea},
- {"native_inject_time", "(JJI)V", (void*)android_location_GnssLocationProvider_inject_time},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_read_sv_status)},
+ {"native_read_nmea", "([BI)I", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_read_nmea)},
+ {"native_inject_time", "(JJI)V", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_inject_time)},
{"native_inject_location",
"(DDF)V",
- (void*)android_location_GnssLocationProvider_inject_location},
- {"native_supports_xtra", "()Z", (void*)android_location_GnssLocationProvider_supports_xtra},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_inject_location)},
+ {"native_supports_xtra", "()Z", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_supports_xtra)},
{"native_inject_xtra_data",
"([BI)V",
- (void*)android_location_GnssLocationProvider_inject_xtra_data},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_inject_xtra_data)},
{"native_agps_data_conn_open",
"(Ljava/lang/String;I)V",
- (void*)android_location_GnssLocationProvider_agps_data_conn_open},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_open)},
{"native_agps_data_conn_closed",
"()V",
- (void*)android_location_GnssLocationProvider_agps_data_conn_closed},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_closed)},
{"native_agps_data_conn_failed",
"()V",
- (void*)android_location_GnssLocationProvider_agps_data_conn_failed},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_failed)},
{"native_agps_set_id",
"(ILjava/lang/String;)V",
- (void*)android_location_GnssLocationProvider_agps_set_id},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_set_id)},
{"native_agps_set_ref_location_cellid",
"(IIIII)V",
- (void*)android_location_GnssLocationProvider_agps_set_reference_location_cellid},
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_agps_set_reference_location_cellid)},
{"native_set_agps_server",
"(ILjava/lang/String;I)V",
- (void*)android_location_GnssLocationProvider_set_agps_server},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_agps_server)},
{"native_send_ni_response",
"(II)V",
- (void*)android_location_GnssLocationProvider_send_ni_response},
- {"native_agps_ni_message",
- "([BI)V",
- (void *)android_location_GnssLocationProvider_agps_send_ni_message},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_send_ni_response)},
{"native_get_internal_state",
"()Ljava/lang/String;",
- (void*)android_location_GnssLocationProvider_get_internal_state},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_get_internal_state)},
{"native_update_network_state",
"(ZIZZLjava/lang/String;Ljava/lang/String;)V",
- (void*)android_location_GnssLocationProvider_update_network_state },
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_update_network_state)},
{"native_is_geofence_supported",
"()Z",
- (void*) android_location_GnssLocationProvider_is_geofence_supported},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_is_geofence_supported)},
{"native_add_geofence",
"(IDDDIIII)Z",
- (void *)android_location_GnssLocationProvider_add_geofence},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_add_geofence)},
{"native_remove_geofence",
"(I)Z",
- (void *)android_location_GnssLocationProvider_remove_geofence},
- {"native_pause_geofence", "(I)Z", (void *)android_location_GnssLocationProvider_pause_geofence},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_remove_geofence)},
+ {"native_pause_geofence", "(I)Z", reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_pause_geofence)},
{"native_resume_geofence",
"(II)Z",
- (void *)android_location_GnssLocationProvider_resume_geofence},
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_resume_geofence)},
{"native_is_measurement_supported",
"()Z",
- (void*) android_location_GnssLocationProvider_is_measurement_supported},
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_is_measurement_supported)},
{"native_start_measurement_collection",
"()Z",
- (void*) android_location_GnssLocationProvider_start_measurement_collection},
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_start_measurement_collection)},
{"native_stop_measurement_collection",
"()Z",
- (void*) android_location_GnssLocationProvider_stop_measurement_collection},
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_stop_measurement_collection)},
{"native_is_navigation_message_supported",
"()Z",
- (void*) android_location_GnssLocationProvider_is_navigation_message_supported},
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_is_navigation_message_supported)},
{"native_start_navigation_message_collection",
"()Z",
- (void*) android_location_GnssLocationProvider_start_navigation_message_collection},
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_start_navigation_message_collection)},
{"native_stop_navigation_message_collection",
"()Z",
- (void*) android_location_GnssLocationProvider_stop_navigation_message_collection},
- {"native_configuration_update",
- "(Ljava/lang/String;)V",
- (void*)android_location_GnssLocationProvider_configuration_update},
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_stop_navigation_message_collection)},
+ {"native_set_supl_es",
+ "(I)Z",
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_es)},
+ {"native_set_supl_version",
+ "(I)Z",
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_version)},
+ {"native_set_supl_mode",
+ "(I)Z",
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_mode)},
+ {"native_set_lpp_profile",
+ "(I)Z",
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_lpp_profile)},
+ {"native_set_gnss_pos_protocol_select",
+ "(I)Z",
+ reinterpret_cast<void *>(
+ android_location_GnssLocationProvider_set_gnss_pos_protocol_select)},
+ {"native_set_gps_lock",
+ "(I)Z",
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_gps_lock)},
+ {"native_set_emergency_supl_pdn",
+ "(I)Z",
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_emergency_supl_pdn)},
};
-int register_android_server_location_GnssLocationProvider(JNIEnv* env)
-{
+int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
return jniRegisterNativeMethods(
env,
"com/android/server/location/GnssLocationProvider",
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a2af40c..4061036 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -17,6 +17,21 @@
package com.android.server.devicepolicy;
import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
+import static android.app.admin.DevicePolicyManager.CODE_ACCOUNTS_NOT_EMPTY;
+import static android.app.admin.DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE;
+import static android.app.admin.DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED;
+import static android.app.admin.DevicePolicyManager.CODE_HAS_DEVICE_OWNER;
+import static android.app.admin.DevicePolicyManager.CODE_HAS_PAIRED;
+import static android.app.admin.DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED;
+import static android.app.admin.DevicePolicyManager.CODE_NONSYSTEM_USER_EXISTS;
+import static android.app.admin.DevicePolicyManager.CODE_NOT_SYSTEM_USER;
+import static android.app.admin.DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT;
+import static android.app.admin.DevicePolicyManager.CODE_OK;
+import static android.app.admin.DevicePolicyManager.CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER;
+import static android.app.admin.DevicePolicyManager.CODE_SYSTEM_USER;
+import static android.app.admin.DevicePolicyManager.CODE_USER_HAS_PROFILE_OWNER;
+import static android.app.admin.DevicePolicyManager.CODE_USER_NOT_RUNNING;
+import static android.app.admin.DevicePolicyManager.CODE_USER_SETUP_COMPLETED;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
@@ -138,7 +153,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.ParcelableString;
@@ -310,21 +324,6 @@
private static final int PROFILE_KEYGUARD_FEATURES =
PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER | PROFILE_KEYGUARD_FEATURES_PROFILE_ONLY;
- private static final int CODE_OK = 0;
- private static final int CODE_HAS_DEVICE_OWNER = 1;
- private static final int CODE_USER_HAS_PROFILE_OWNER = 2;
- private static final int CODE_USER_NOT_RUNNING = 3;
- private static final int CODE_USER_SETUP_COMPLETED = 4;
- private static final int CODE_NONSYSTEM_USER_EXISTS = 5;
- private static final int CODE_ACCOUNTS_NOT_EMPTY = 6;
- private static final int CODE_NOT_SYSTEM_USER = 7;
- private static final int CODE_HAS_PAIRED = 8;
-
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({ CODE_OK, CODE_HAS_DEVICE_OWNER, CODE_USER_HAS_PROFILE_OWNER, CODE_USER_NOT_RUNNING,
- CODE_USER_SETUP_COMPLETED, CODE_NOT_SYSTEM_USER })
- private @interface DeviceOwnerPreConditionCode {}
-
private static final int DEVICE_ADMIN_DEACTIVATE_TIMEOUT = 10000;
/**
@@ -3093,6 +3092,7 @@
// If admin is a device or profile owner tidy that up first.
if (isDeviceOwner(adminReceiver, userHandle)) {
clearDeviceOwnerLocked(getDeviceOwnerAdminLocked(), userHandle);
+ clearDeviceOwnerUserRestrictionLocked(UserHandle.of(userHandle));
}
if (isProfileOwner(adminReceiver, userHandle)) {
final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver,
@@ -3108,6 +3108,15 @@
}
}
+ // It's temporary solution to clear DISALLOW_ADD_USER after CTS
+ // TODO: b/31952368 when the restriction is moved from system to the device owner,
+ // it can be removed.
+ private void clearDeviceOwnerUserRestrictionLocked(UserHandle userHandle) {
+ if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER, userHandle)) {
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false, userHandle);
+ }
+ }
+
/**
* Return if a given package has testOnly="true", in which case we'll relax certain rules
* for CTS.
@@ -4796,6 +4805,20 @@
long ident = mInjector.binderClearCallingIdentity();
try {
+ final String restriction;
+ if (userHandle == UserHandle.USER_SYSTEM) {
+ restriction = UserManager.DISALLOW_FACTORY_RESET;
+ } else if (isManagedProfile(userHandle)) {
+ restriction = UserManager.DISALLOW_REMOVE_MANAGED_PROFILE;
+ } else {
+ restriction = UserManager.DISALLOW_REMOVE_USER;
+ }
+ if (isAdminAffectedByRestriction(
+ admin.info.getComponent(), restriction, userHandle)) {
+ throw new SecurityException("Cannot wipe data. " + restriction
+ + " restriction is set for user " + userHandle);
+ }
+
if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) {
if (!isDeviceOwner(admin.info.getComponent(), userHandle)) {
throw new SecurityException(
@@ -4807,34 +4830,21 @@
manager.wipe();
}
}
+
boolean wipeExtRequested = (flags & WIPE_EXTERNAL_STORAGE) != 0;
- // If the admin is the only one who has set the restriction: force wipe, even if
- // {@link UserManager.DISALLOW_FACTORY_RESET} is set. Reason is that the admin
- // could remove this user restriction anyway.
- boolean force = (userHandle == UserHandle.USER_SYSTEM)
- && isAdminOnlyOneWhoSetRestriction(admin,
- UserManager.DISALLOW_FACTORY_RESET, UserHandle.USER_SYSTEM);
wipeDeviceOrUserLocked(wipeExtRequested, userHandle,
- "DevicePolicyManager.wipeData() from " + source, force);
+ "DevicePolicyManager.wipeData() from " + source, /*force=*/ true);
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
}
}
- private boolean isAdminOnlyOneWhoSetRestriction(ActiveAdmin admin, String userRestriction,
- int userId) {
- int source = mUserManager.getUserRestrictionSource(userRestriction, UserHandle.of(userId));
- if (isDeviceOwner(admin.info.getComponent(), userId)) {
- return source == UserManager.RESTRICTION_SOURCE_DEVICE_OWNER;
- } else if (isProfileOwner(admin.info.getComponent(), userId)) {
- return source == UserManager.RESTRICTION_SOURCE_PROFILE_OWNER;
- }
- return false;
- }
-
- private void wipeDeviceOrUserLocked(boolean wipeExtRequested, final int userHandle,
- String reason, boolean force) {
+ private void wipeDeviceOrUserLocked(
+ boolean wipeExtRequested, final int userHandle, String reason, boolean force) {
+ // TODO If split user is enabled and the device owner is set in the primary user (rather
+ // than system), we should probably trigger factory reset. Current code just remove
+ // that user (but still clears FRP...)
if (userHandle == UserHandle.USER_SYSTEM) {
wipeDataLocked(wipeExtRequested, reason, force);
} else {
@@ -4847,10 +4857,12 @@
am.switchUser(UserHandle.USER_SYSTEM);
}
- boolean isManagedProfile = isManagedProfile(userHandle);
- if (!mUserManager.removeUser(userHandle)) {
+ boolean userRemoved = force
+ ? mUserManagerInternal.removeUserEvenWhenDisallowed(userHandle)
+ : mUserManager.removeUser(userHandle);
+ if (!userRemoved) {
Slog.w(LOG_TAG, "Couldn't remove user " + userHandle);
- } else if (isManagedProfile) {
+ } else if (isManagedProfile(userHandle)) {
sendWipeProfileNotification();
}
} catch (RemoteException re) {
@@ -5938,7 +5950,8 @@
}
synchronized (this) {
enforceCanSetDeviceOwnerLocked(admin, userId);
- if (getActiveAdminUncheckedLocked(admin, userId) == null
+ final ActiveAdmin activeAdmin = getActiveAdminUncheckedLocked(admin, userId);
+ if (activeAdmin == null
|| getUserData(userId).mRemovingAdmins.contains(admin)) {
throw new IllegalArgumentException("Not active admin: " + admin);
}
@@ -5965,12 +5978,23 @@
mOwners.writeDeviceOwner();
updateDeviceOwnerLocked();
setDeviceOwnerSystemPropertyLocked();
- Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED);
+
+ // STOPSHIP(b/31952368) Also set this restriction for existing DOs on OTA to Android OC.
+ final Set<String> restrictions =
+ UserRestrictionsUtils.getDefaultEnabledForDeviceOwner();
+ if (!restrictions.isEmpty()) {
+ for (String restriction : restrictions) {
+ activeAdmin.ensureUserRestrictions().putBoolean(restriction, true);
+ }
+ saveUserRestrictionsLocked(userId);
+ }
ident = mInjector.binderClearCallingIdentity();
try {
// TODO Send to system too?
- mContext.sendBroadcastAsUser(intent, new UserHandle(userId));
+ mContext.sendBroadcastAsUser(
+ new Intent(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED),
+ UserHandle.of(userId));
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
@@ -6166,6 +6190,7 @@
mOwners.setProfileOwner(who, ownerName, userHandle);
mOwners.writeProfileOwner(userHandle);
Slog.i(LOG_TAG, "Profile owner set: " + who + " on user " + userHandle);
+
return true;
}
}
@@ -6526,7 +6551,7 @@
enforceCanManageProfileAndDeviceOwners();
}
- final int code = checkSetDeviceOwnerPreConditionLocked(owner, userId, isAdb());
+ final int code = checkDeviceOwnerProvisioningPreConditionLocked(owner, userId, isAdb());
switch (code) {
case CODE_OK:
return;
@@ -6553,7 +6578,7 @@
throw new IllegalStateException("Not allowed to set the device owner because this "
+ "device has already paired");
default:
- throw new IllegalStateException("Unknown @DeviceOwnerPreConditionCode " + code);
+ throw new IllegalStateException("Unexpected @ProvisioningPreCondition " + code);
}
}
@@ -7476,28 +7501,41 @@
@Override
public boolean removeUser(ComponentName who, UserHandle userHandle) {
Preconditions.checkNotNull(who, "ComponentName is null");
- UserHandle callingUserHandle = mInjector.binderGetCallingUserHandle();
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
+
+ final int callingUserId = mInjector.userHandleGetCallingUserId();
final long id = mInjector.binderClearCallingIdentity();
try {
- int restrictionSource = mUserManager.getUserRestrictionSource(
- UserManager.DISALLOW_REMOVE_USER, callingUserHandle);
- if (restrictionSource != UserManager.RESTRICTION_NOT_SET
- && restrictionSource != UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) {
+ String restriction = isManagedProfile(userHandle.getIdentifier())
+ ? UserManager.DISALLOW_REMOVE_MANAGED_PROFILE
+ : UserManager.DISALLOW_REMOVE_USER;
+ if (isAdminAffectedByRestriction(who, restriction, callingUserId)) {
Log.w(LOG_TAG, "The device owner cannot remove a user because "
- + "DISALLOW_REMOVE_USER is enabled, and was not set by the device "
- + "owner");
+ + restriction + " is enabled, and was not set by the device owner");
return false;
}
- return mUserManagerInternal.removeUserEvenWhenDisallowed(
- userHandle.getIdentifier());
+ return mUserManagerInternal.removeUserEvenWhenDisallowed(userHandle.getIdentifier());
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
}
+ private boolean isAdminAffectedByRestriction(
+ ComponentName admin, String userRestriction, int userId) {
+ switch(mUserManager.getUserRestrictionSource(userRestriction, UserHandle.of(userId))) {
+ case UserManager.RESTRICTION_NOT_SET:
+ return false;
+ case UserManager.RESTRICTION_SOURCE_DEVICE_OWNER:
+ return !isDeviceOwner(admin, userId);
+ case UserManager.RESTRICTION_SOURCE_PROFILE_OWNER:
+ return !isProfileOwner(admin, userId);
+ default:
+ return true;
+ }
+ }
+
@Override
public boolean switchUser(ComponentName who, UserHandle userHandle) {
Preconditions.checkNotNull(who, "ComponentName is null");
@@ -7603,14 +7641,16 @@
// Save the restriction to ActiveAdmin.
activeAdmin.ensureUserRestrictions().putBoolean(key, enabledFromThisOwner);
- saveSettingsLocked(userHandle);
-
- pushUserRestrictions(userHandle);
-
- sendChangedNotification(userHandle);
+ saveUserRestrictionsLocked(userHandle);
}
}
+ private void saveUserRestrictionsLocked(int userId) {
+ saveSettingsLocked(userId);
+ pushUserRestrictions(userId);
+ sendChangedNotification(userId);
+ }
+
private void pushUserRestrictions(int userId) {
synchronized (this) {
final Bundle global;
@@ -8761,79 +8801,42 @@
@Override
public boolean isProvisioningAllowed(String action) {
+ return checkProvisioningPreConditionSkipPermission(action) == CODE_OK;
+ }
+
+ @Override
+ public int checkProvisioningPreCondition(String action) {
+ enforceCanManageProfileAndDeviceOwners();
+ return checkProvisioningPreConditionSkipPermission(action);
+ }
+
+ private int checkProvisioningPreConditionSkipPermission(String action) {
if (!mHasFeature) {
- return false;
+ return CODE_DEVICE_ADMIN_NOT_SUPPORTED;
}
final int callingUserId = mInjector.userHandleGetCallingUserId();
- if (DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE.equals(action)) {
- if (!hasFeatureManagedUsers()) {
- return false;
+ if (action != null) {
+ switch (action) {
+ case DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE:
+ return checkManagedProfileProvisioningPreCondition(callingUserId);
+ case DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE:
+ return checkDeviceOwnerProvisioningPreCondition(callingUserId);
+ case DevicePolicyManager.ACTION_PROVISION_MANAGED_USER:
+ return checkManagedUserProvisioningPreCondition(callingUserId);
+ case DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE:
+ return checkManagedShareableDeviceProvisioningPreCondition(callingUserId);
}
- synchronized (this) {
- if (mOwners.hasDeviceOwner()) {
- // STOPSHIP Only allow creating a managed profile if allowed by the device
- // owner. http://b/31952368
- if (mInjector.userManagerIsSplitSystemUser()) {
- if (callingUserId == UserHandle.USER_SYSTEM) {
- // Managed-profiles cannot be setup on the system user.
- return false;
- }
- }
- }
- }
- if (getProfileOwner(callingUserId) != null) {
- // Managed user cannot have a managed profile.
- return false;
- }
- boolean canRemoveProfile
- = !mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER);
- final long ident = mInjector.binderClearCallingIdentity();
- try {
- if (!mUserManager.canAddMoreManagedProfiles(callingUserId, canRemoveProfile)) {
- return false;
- }
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
- return true;
- } else if (DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE.equals(action)) {
- return isDeviceOwnerProvisioningAllowed(callingUserId);
- } else if (DevicePolicyManager.ACTION_PROVISION_MANAGED_USER.equals(action)) {
- if (!hasFeatureManagedUsers()) {
- return false;
- }
- if (!mInjector.userManagerIsSplitSystemUser()) {
- // ACTION_PROVISION_MANAGED_USER only supported on split-user systems.
- return false;
- }
- if (callingUserId == UserHandle.USER_SYSTEM) {
- // System user cannot be a managed user.
- return false;
- }
- if (hasUserSetupCompleted(callingUserId)) {
- return false;
- }
- if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) {
- return false;
- }
- return true;
- } else if (DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE.equals(action)) {
- if (!mInjector.userManagerIsSplitSystemUser()) {
- // ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE only supported on split-user systems.
- return false;
- }
- return isDeviceOwnerProvisioningAllowed(callingUserId);
}
throw new IllegalArgumentException("Unknown provisioning action " + action);
}
- /*
+ /**
* The device owner can only be set before the setup phase of the primary user has completed,
* except for adb command if no accounts or additional users are present on the device.
*/
- private synchronized @DeviceOwnerPreConditionCode int checkSetDeviceOwnerPreConditionLocked(
- @Nullable ComponentName owner, int deviceOwnerUserId, boolean isAdb) {
+ private int checkDeviceOwnerProvisioningPreConditionLocked(@Nullable ComponentName owner,
+ int deviceOwnerUserId, boolean isAdb) {
if (mOwners.hasDeviceOwner()) {
return CODE_HAS_DEVICE_OWNER;
}
@@ -8878,13 +8881,82 @@
}
}
- private boolean isDeviceOwnerProvisioningAllowed(int deviceOwnerUserId) {
+ private int checkDeviceOwnerProvisioningPreCondition(int deviceOwnerUserId) {
synchronized (this) {
- return CODE_OK == checkSetDeviceOwnerPreConditionLocked(
- /* owner unknown */ null, deviceOwnerUserId, /* isAdb */ false);
+ return checkDeviceOwnerProvisioningPreConditionLocked(/* owner unknown */ null,
+ deviceOwnerUserId, /* isAdb= */ false);
}
}
+ private int checkManagedProfileProvisioningPreCondition(int callingUserId) {
+ if (!hasFeatureManagedUsers()) {
+ return CODE_MANAGED_USERS_NOT_SUPPORTED;
+ }
+ if (callingUserId == UserHandle.USER_SYSTEM
+ && mInjector.userManagerIsSplitSystemUser()) {
+ // Managed-profiles cannot be setup on the system user.
+ return CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER;
+ }
+ if (getProfileOwner(callingUserId) != null) {
+ // Managed user cannot have a managed profile.
+ return CODE_USER_HAS_PROFILE_OWNER;
+ }
+ final long ident = mInjector.binderClearCallingIdentity();
+ try {
+ /* STOPSHIP(b/31952368) Reinstate a check similar to this once ManagedProvisioning
+ uses checkProvisioningPreCondition (see ag/1607846) and passes the packageName
+ there. In isProvisioningAllowed we should check isCallerDeviceOwner, but for
+ managed provisioning we need to check the package that is going to be set as PO
+ if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE)) {
+ if (!isCallerDeviceOwner(callingUid)
+ || isAdminAffectedByRestriction(mOwners.getDeviceOwnerComponent(),
+ UserManager.DISALLOW_ADD_MANAGED_PROFILE, callingUserId)) {
+ // Caller is not DO or the restriction was set by the system.
+ return false;
+ }
+ } */
+ // TODO: Allow it if the caller is the DO? DO could just call removeUser() before
+ // provisioning, so not strictly required...
+ boolean canRemoveProfile = !mUserManager.hasUserRestriction(
+ UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, UserHandle.of(callingUserId));
+ if (!mUserManager.canAddMoreManagedProfiles(callingUserId, canRemoveProfile)) {
+ return CODE_CANNOT_ADD_MANAGED_PROFILE;
+ }
+ } finally {
+ mInjector.binderRestoreCallingIdentity(ident);
+ }
+ return CODE_OK;
+ }
+
+ private int checkManagedUserProvisioningPreCondition(int callingUserId) {
+ if (!hasFeatureManagedUsers()) {
+ return CODE_MANAGED_USERS_NOT_SUPPORTED;
+ }
+ if (!mInjector.userManagerIsSplitSystemUser()) {
+ // ACTION_PROVISION_MANAGED_USER only supported on split-user systems.
+ return CODE_NOT_SYSTEM_USER_SPLIT;
+ }
+ if (callingUserId == UserHandle.USER_SYSTEM) {
+ // System user cannot be a managed user.
+ return CODE_SYSTEM_USER;
+ }
+ if (hasUserSetupCompleted(callingUserId)) {
+ return CODE_USER_SETUP_COMPLETED;
+ }
+ if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) {
+ return CODE_HAS_PAIRED;
+ }
+ return CODE_OK;
+ }
+
+ private int checkManagedShareableDeviceProvisioningPreCondition(int callingUserId) {
+ if (!mInjector.userManagerIsSplitSystemUser()) {
+ // ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE only supported on split-user systems.
+ return CODE_NOT_SYSTEM_USER_SPLIT;
+ }
+ return checkDeviceOwnerProvisioningPreCondition(callingUserId);
+ }
+
private boolean hasFeatureManagedUsers() {
try {
return mIPackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0);
@@ -9831,9 +9903,8 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkNotNull(admin);
synchronized (this) {
- getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+ enforceDeviceOwnerOrManageUsers();
return isNetworkLoggingEnabledInternalLocked();
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 1fc4378..6ec25c5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -114,6 +114,7 @@
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
+import java.util.concurrent.CountDownLatch;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -272,7 +273,7 @@
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);
// Also report when first stage of init has started
- long initStartNs = SystemProperties.getLong("init.start", -1);
+ long initStartNs = SystemProperties.getLong("ro.boottime.init", -1);
if (initStartNs >= 0) {
MetricsLogger.histogram(null, "boot_android_init", (int)(initStartNs / 1000000));
}
@@ -1484,8 +1485,10 @@
@Override
public void run() {
Slog.i(TAG, "Making services ready");
+ traceBeginAndSlog("StartActivityManagerReadyPhase");
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
+ traceEnd();
traceBeginAndSlog("PhaseActivityManagerReady");
traceBeginAndSlog("StartObservingNativeCrashes");
@@ -1523,6 +1526,11 @@
} catch (Throwable e) {
reportWtf("making Network Managment Service ready", e);
}
+ CountDownLatch networkPolicyInitReadySignal = null;
+ if (networkPolicyF != null) {
+ networkPolicyInitReadySignal = networkPolicyF
+ .networkScoreAndNetworkManagementServiceReady();
+ }
traceEnd();
traceBeginAndSlog("MakeNetworkStatsServiceReady");
try {
@@ -1531,13 +1539,6 @@
reportWtf("making Network Stats Service ready", e);
}
traceEnd();
- traceBeginAndSlog("MakeNetworkPolicyServiceReady");
- try {
- if (networkPolicyF != null) networkPolicyF.systemReady();
- } catch (Throwable e) {
- reportWtf("making Network Policy Service ready", e);
- }
- traceEnd();
traceBeginAndSlog("MakeConnectivityServiceReady");
try {
if (connectivityF != null) connectivityF.systemReady();
@@ -1545,6 +1546,15 @@
reportWtf("making Connectivity Service ready", e);
}
traceEnd();
+ traceBeginAndSlog("MakeNetworkPolicyServiceReady");
+ try {
+ if (networkPolicyF != null) {
+ networkPolicyF.systemReady(networkPolicyInitReadySignal);
+ }
+ } catch (Throwable e) {
+ reportWtf("making Network Policy Service ready", e);
+ }
+ traceEnd();
traceBeginAndSlog("StartWatchdog");
Watchdog.getInstance().start();
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index a8356dc..83001df 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -194,8 +194,10 @@
{ (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
- private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
+ private static final int ICMP6_ROUTER_SOLICITATION = 133;
private static final int ICMP6_ROUTER_ADVERTISEMENT = 134;
+ private static final int ICMP6_NEIGHBOR_SOLICITATION = 135;
+ private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
// NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT
private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 2;
@@ -805,6 +807,8 @@
// if it's multicast and we're dropping multicast:
// drop
// pass
+ // if it's ICMPv6 RS to any:
+ // drop
// if it's ICMPv6 NA to ff02::1:
// drop
@@ -829,10 +833,12 @@
// Add unsolicited multicast neighbor announcements filter
String skipUnsolicitedMulticastNALabel = "skipUnsolicitedMulticastNA";
- // If not neighbor announcements, skip unsolicited multicast NA filter
gen.addLoad8(Register.R0, ICMP6_TYPE_OFFSET);
+ // Drop all router solicitations (b/32833400)
+ gen.addJumpIfR0Equals(ICMP6_ROUTER_SOLICITATION, gen.DROP_LABEL);
+ // If not neighbor announcements, skip filter.
gen.addJumpIfR0NotEquals(ICMP6_NEIGHBOR_ANNOUNCEMENT, skipUnsolicitedMulticastNALabel);
- // If to ff02::1, drop
+ // If to ff02::1, drop.
// TODO: Drop only if they don't contain the address of on-link neighbours.
gen.addLoadImmediate(Register.R0, IPV6_DEST_ADDR_OFFSET);
gen.addJumpIfBytesNotEqual(Register.R0, IPV6_ALL_NODES_ADDRESS,
@@ -852,6 +858,7 @@
* <li>Pass all non-ICMPv6 IPv6 packets,
* <li>Pass all non-IPv4 and non-IPv6 packets,
* <li>Drop IPv6 ICMPv6 NAs to ff02::1.
+ * <li>Drop IPv6 ICMPv6 RSs.
* <li>Let execution continue off the end of the program for IPv6 ICMPv6 packets. This allows
* insertion of RA filters here, or if there aren't any, just passes the packets.
* </ul>
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index ef4bc02..96c8e9f 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -7,6 +7,7 @@
import android.os.Build;
import android.os.SystemProperties;
import android.system.OsConstants;
+import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
import java.io.UnsupportedEncodingException;
@@ -629,7 +630,8 @@
protected void addCommonClientTlvs(ByteBuffer buf) {
addTlv(buf, DHCP_MAX_MESSAGE_SIZE, (short) MAX_LENGTH);
addTlv(buf, DHCP_VENDOR_CLASS_ID, getVendorId());
- addTlv(buf, DHCP_HOST_NAME, getHostname());
+ final String hn = getHostname();
+ if (!TextUtils.isEmpty(hn)) addTlv(buf, DHCP_HOST_NAME, hn);
}
/**
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 39f14e5..58b2dec 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -438,6 +438,9 @@
mCallback = new LoggingCallbackWrapper(callback);
mNwService = nwService;
+ mLocalLog = new LocalLog(MAX_LOG_RECORDS);
+ mMsgStateLogger = new MessageHandlingLogger();
+
mNetlinkTracker = new NetlinkTracker(
mInterfaceName,
new NetlinkTracker.Callback() {
@@ -451,48 +454,79 @@
super.interfaceAdded(iface);
if (mClatInterfaceName.equals(iface)) {
mCallback.setNeighborDiscoveryOffload(false);
+ } else if (!mInterfaceName.equals(iface)) {
+ return;
}
+
+ final String msg = "interfaceAdded(" + iface +")";
+ logMsg(msg);
}
@Override
public void interfaceRemoved(String iface) {
super.interfaceRemoved(iface);
+ // TODO: Also observe mInterfaceName going down and take some
+ // kind of appropriate action.
if (mClatInterfaceName.equals(iface)) {
// TODO: consider sending a message to the IpManager main
// StateMachine thread, in case "NDO enabled" state becomes
// tied to more things that 464xlat operation.
mCallback.setNeighborDiscoveryOffload(true);
+ } else if (!mInterfaceName.equals(iface)) {
+ return;
}
+
+ final String msg = "interfaceRemoved(" + iface +")";
+ logMsg(msg);
+ }
+
+ private void logMsg(String msg) {
+ Log.d(mTag, msg);
+ getHandler().post(() -> { mLocalLog.log("OBSERVED " + msg); });
}
};
- try {
- mNwService.registerObserver(mNetlinkTracker);
- } catch (RemoteException e) {
- Log.e(mTag, "Couldn't register NetlinkTracker: " + e.toString());
- }
+ mLinkProperties = new LinkProperties();
+ mLinkProperties.setInterfaceName(mInterfaceName);
- mAvoidBadWifiTracker = new AvoidBadWifiTracker(mContext, getHandler());
-
- resetLinkProperties();
+ mAvoidBadWifiTracker = new AvoidBadWifiTracker(mContext, getHandler(),
+ () -> { mLocalLog.log("OBSERVED AvoidBadWifi changed"); });
mProvisioningTimeoutAlarm = new WakeupMessage(mContext, getHandler(),
mTag + ".EVENT_PROVISIONING_TIMEOUT", EVENT_PROVISIONING_TIMEOUT);
mDhcpActionTimeoutAlarm = new WakeupMessage(mContext, getHandler(),
mTag + ".EVENT_DHCPACTION_TIMEOUT", EVENT_DHCPACTION_TIMEOUT);
- // Super simple StateMachine.
+ // Anything the StateMachine may access must have been instantiated
+ // before this point.
+ configureAndStartStateMachine();
+
+ // Anything that may send messages to the StateMachine must only be
+ // configured to do so after the StateMachine has started (above).
+ startStateMachineUpdaters();
+ }
+
+ private void configureAndStartStateMachine() {
addState(mStoppedState);
addState(mStartedState);
addState(mRunningState, mStartedState);
addState(mStoppingState);
setInitialState(mStoppedState);
- mLocalLog = new LocalLog(MAX_LOG_RECORDS);
- mMsgStateLogger = new MessageHandlingLogger();
+
super.start();
}
+ private void startStateMachineUpdaters() {
+ try {
+ mNwService.registerObserver(mNetlinkTracker);
+ } catch (RemoteException e) {
+ Log.e(mTag, "Couldn't register NetlinkTracker: " + e.toString());
+ }
+
+ mAvoidBadWifiTracker.start();
+ }
+
@Override
protected void onQuitting() {
mCallback.onQuit();
@@ -501,6 +535,7 @@
// Shut down this IpManager instance altogether.
public void shutdown() {
stop();
+ mAvoidBadWifiTracker.shutdown();
quit();
}
diff --git a/services/net/java/android/net/util/AvoidBadWifiTracker.java b/services/net/java/android/net/util/AvoidBadWifiTracker.java
index c14e811..2abaeb1 100644
--- a/services/net/java/android/net/util/AvoidBadWifiTracker.java
+++ b/services/net/java/android/net/util/AvoidBadWifiTracker.java
@@ -57,7 +57,11 @@
private final Context mContext;
private final Handler mHandler;
private final Runnable mReevaluateRunnable;
+ private final Uri mUri;
+ private final ContentResolver mResolver;
private final SettingObserver mSettingObserver;
+ private final BroadcastReceiver mBroadcastReceiver;
+
private volatile boolean mAvoidBadWifi = true;
public AvoidBadWifiTracker(Context ctx, Handler handler) {
@@ -68,19 +72,36 @@
mContext = ctx;
mHandler = handler;
mReevaluateRunnable = () -> { if (update() && cb != null) cb.run(); };
+ mUri = Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI);
+ mResolver = mContext.getContentResolver();
mSettingObserver = new SettingObserver();
-
- final IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
- mContext.registerReceiverAsUser(new BroadcastReceiver() {
+ mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
public void onReceive(Context context, Intent intent) {
reevaluate();
}
- }, UserHandle.ALL, intentFilter, null, null);
+ };
update();
}
+ public void start() {
+ mResolver.registerContentObserver(mUri, false, mSettingObserver);
+
+ final IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+ mContext.registerReceiverAsUser(
+ mBroadcastReceiver, UserHandle.ALL, intentFilter, null, null);
+
+ reevaluate();
+ }
+
+ public void shutdown() {
+ mResolver.unregisterContentObserver(mSettingObserver);
+
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ }
+
public boolean currentValue() {
return mAvoidBadWifi;
}
@@ -100,8 +121,7 @@
}
public String getSettingsValue() {
- final ContentResolver resolver = mContext.getContentResolver();
- return Settings.Global.getString(resolver, NETWORK_AVOID_BAD_WIFI);
+ return Settings.Global.getString(mResolver, NETWORK_AVOID_BAD_WIFI);
}
@VisibleForTesting
@@ -117,12 +137,8 @@
}
private class SettingObserver extends ContentObserver {
- private final Uri mUri = Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI);
-
public SettingObserver() {
super(null);
- final ContentResolver resolver = mContext.getContentResolver();
- resolver.registerContentObserver(mUri, false, this);
}
@Override
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationListenerServiceTest.java
new file mode 100644
index 0000000..b6166f6
--- /dev/null
+++ b/services/tests/notification/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.NotificationChannel;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationRankingUpdate;
+import android.service.notification.SnoozeCriterion;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationListenerServiceTest {
+
+ private String[] mKeys = new String[] { "key", "key1", "key2", "key3"};
+
+ @Test
+ public void testRanking() throws Exception {
+ TestListenerService service = new TestListenerService();
+ service.applyUpdateLocked(generateUpdate());
+ for (int i = 0; i < mKeys.length; i++) {
+ String key = mKeys[i];
+ Ranking ranking = new Ranking();
+ service.getCurrentRanking().getRanking(key, ranking);
+ assertEquals(getVisibilityOverride(i), ranking.getVisibilityOverride());
+ assertEquals(getOverrideGroupKey(key), ranking.getOverrideGroupKey());
+ assertEquals(!isIntercepted(i), ranking.matchesInterruptionFilter());
+ assertEquals(getSuppressedVisualEffects(i), ranking.getSuppressedVisualEffects());
+ assertEquals(getImportance(i), ranking.getImportance());
+ assertEquals(getExplanation(key), ranking.getImportanceExplanation());
+ assertEquals(getChannel(key, i), ranking.getChannel());
+ assertEquals(getPeople(key, i), ranking.getAdditionalPeople());
+ assertEquals(getSnoozeCriteria(key, i), ranking.getSnoozeCriteria());
+ }
+ }
+
+ private NotificationRankingUpdate generateUpdate() {
+ List<String> interceptedKeys = new ArrayList<>();
+ Bundle visibilityOverrides = new Bundle();
+ Bundle overrideGroupKeys = new Bundle();
+ Bundle suppressedVisualEffects = new Bundle();
+ Bundle explanation = new Bundle();
+ Bundle overrideChannels = new Bundle();
+ Bundle overridePeople = new Bundle();
+ Bundle snoozeCriteria = new Bundle();
+ int[] importance = new int[mKeys.length];
+
+ for (int i = 0; i < mKeys.length; i++) {
+ String key = mKeys[i];
+ visibilityOverrides.putInt(key, getVisibilityOverride(i));
+ overrideGroupKeys.putString(key, getOverrideGroupKey(key));
+ if (isIntercepted(i)) {
+ interceptedKeys.add(key);
+ }
+ suppressedVisualEffects.putInt(key, getSuppressedVisualEffects(i));
+ importance[i] = getImportance(i);
+ explanation.putString(key, getExplanation(key));
+ overrideChannels.putParcelable(key, getChannel(key, i));
+ overridePeople.putStringArrayList(key, getPeople(key, i));
+ snoozeCriteria.putParcelableArrayList(key, getSnoozeCriteria(key, i));
+ }
+ NotificationRankingUpdate update = new NotificationRankingUpdate(mKeys,
+ interceptedKeys.toArray(new String[0]), visibilityOverrides,
+ suppressedVisualEffects, importance, explanation, overrideGroupKeys,
+ overrideChannels, overridePeople, snoozeCriteria);
+ return update;
+ }
+
+ private int getVisibilityOverride(int index) {
+ return index * 9;
+ }
+
+ private String getOverrideGroupKey(String key) {
+ return key + key;
+ }
+
+ private boolean isIntercepted(int index) {
+ return index % 2 == 0;
+ }
+
+ private int getSuppressedVisualEffects(int index) {
+ return index * 2;
+ }
+
+ private int getImportance(int index) {
+ return index;
+ }
+
+ private String getExplanation(String key) {
+ return key + "explain";
+ }
+
+ private NotificationChannel getChannel(String key, int index) {
+ return new NotificationChannel(key, key, getImportance(index));
+ }
+
+ private ArrayList<String> getPeople(String key, int index) {
+ ArrayList<String> people = new ArrayList<>();
+ for (int i = 0; i < index; i++) {
+ people.add(i + key);
+ }
+ return people;
+ }
+
+ private ArrayList<SnoozeCriterion> getSnoozeCriteria(String key, int index) {
+ ArrayList<SnoozeCriterion> snooze = new ArrayList<>();
+ for (int i = 0; i < index; i++) {
+ snooze.add(new SnoozeCriterion(key + i, getExplanation(key), key));
+ }
+ return snooze;
+ }
+
+ public static class TestListenerService extends NotificationListenerService {
+ private final IBinder binder = new LocalBinder();
+
+ public TestListenerService() {
+
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ super.onBind(intent);
+ return binder;
+ }
+
+ public class LocalBinder extends Binder {
+ TestListenerService getService() {
+ return TestListenerService.this;
+ }
+ }
+ }
+}
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index e4a355f..80c4cce 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -57,8 +57,6 @@
when(mockPackageManager.getApplicationInfo(any(), anyInt(), anyInt()))
.thenReturn(applicationInfo);
mNotificationManagerService.setPackageManager(mockPackageManager);
-
- mNotificationManagerService.setRankingHelper(mock(RankingHelper.class));
mNotificationManagerService.setHandler(new Handler(context.getMainLooper()));
// Tests call directly into the Binder.
@@ -69,6 +67,7 @@
public void testCreateNotificationChannel_SuccessCallsListener() throws Exception {
final NotificationChannel channel =
new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
+ mNotificationManagerService.setRankingHelper(mock(RankingHelper.class));
final CountDownLatch latch = new CountDownLatch(1);
mBinderService.createNotificationChannel("test_pkg", channel,
new IOnNotificationChannelCreatedListener.Stub() {
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index a7d2c04..fc94271f 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -59,7 +59,7 @@
@Mock PackageManager mPm;
private final String pkg = "com.android.server.notification";
- private final int uid = 0;
+ private final int uid = 9583;
private final String pkg2 = "pkg2";
private final int uid2 = 1111111;
private final int id1 = 1;
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index 16d0a75..e6afe76 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -375,7 +375,7 @@
final NotificationChannel channel2 =
new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
- mHelper.updateNotificationChannelFromRanker(pkg, uid, channel2);
+ mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
// no fields should be changed
assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
@@ -396,7 +396,7 @@
new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
- mHelper.updateNotificationChannelFromRanker(pkg, uid, channel2);
+ mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
// no fields should be changed
assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
@@ -418,7 +418,7 @@
channel2.enableVibration(true);
channel2.setVibrationPattern(new long[] {100});
- mHelper.updateNotificationChannelFromRanker(pkg, uid, channel2);
+ mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
// no fields should be changed
assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
@@ -439,7 +439,7 @@
new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
channel2.setLights(true);
- mHelper.updateNotificationChannelFromRanker(pkg, uid, channel2);
+ mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
// no fields should be changed
assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
@@ -460,7 +460,7 @@
new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
channel2.setBypassDnd(false);
- mHelper.updateNotificationChannelFromRanker(pkg, uid, channel2);
+ mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
// no fields should be changed
assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
@@ -481,7 +481,7 @@
new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
channel2.setSound(new Uri.Builder().scheme("test2").build());
- mHelper.updateNotificationChannelFromRanker(pkg, uid, channel2);
+ mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
// no fields should be changed
assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 3114f3f..796284d 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -43,12 +43,12 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
+import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
@@ -77,7 +77,6 @@
import android.net.INetworkStatsService;
import android.net.LinkProperties;
import android.net.NetworkInfo;
-import android.net.NetworkPolicyManager;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkPolicy;
import android.net.NetworkState;
@@ -141,6 +140,15 @@
/**
* Tests for {@link NetworkPolicyManagerService}.
+ *
+ * <p>Typical usage:
+ *
+ * <pre><code>
+ m -j32 FrameworksServicesTests && adb install -r -g \
+ ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && \
+ adb shell am instrument -e class "com.android.server.NetworkPolicyManagerServiceTest" -w \
+ "com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner"
+ * </code></pre>
*/
@RunWith(AndroidJUnit4.class)
@MediumTest
@@ -247,7 +255,7 @@
return null;
}
}).when(mActivityManager).registerUidObserver(any(), anyInt(),
- ActivityManager.PROCESS_STATE_UNKNOWN, null);
+ eq(ActivityManager.PROCESS_STATE_UNKNOWN), isNull(String.class));
mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
mNetworkManager, mIpm, mTime, mPolicyDir, true);
@@ -282,7 +290,7 @@
expectCurrentTime();
// Prepare NPMS.
- mService.systemReady();
+ mService.systemReady(mService.networkScoreAndNetworkManagementServiceReady());
// catch INetworkManagementEventObserver during systemReady()
final ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
new file mode 100644
index 0000000..50911cb
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static android.net.NetworkScoreManager.CACHE_FILTER_NONE;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyListOf;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.Manifest.permission;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.net.INetworkScoreCache;
+import android.net.NetworkKey;
+import android.net.NetworkScoreManager;
+import android.net.NetworkScorerAppManager;
+import android.net.NetworkScorerAppManager.NetworkScorerAppData;
+import android.net.ScoredNetwork;
+import android.net.WifiKey;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.R;
+import com.android.server.devicepolicy.MockUtils;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link NetworkScoreService}.
+ */
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class NetworkScoreServiceTest {
+ private static final ScoredNetwork SCORED_NETWORK =
+ new ScoredNetwork(new NetworkKey(new WifiKey("\"ssid\"", "00:00:00:00:00:00")),
+ null /* rssiCurve*/);
+ private static final NetworkScorerAppData PREV_SCORER = new NetworkScorerAppData(
+ "prevPackageName", 0, "prevScorerName", null /* configurationActivityClassName */,
+ "prevScoringServiceClass");
+ private static final NetworkScorerAppData NEW_SCORER = new NetworkScorerAppData(
+ "newPackageName", 1, "newScorerName", null /* configurationActivityClassName */,
+ "newScoringServiceClass");
+
+ @Mock private PackageManager mPackageManager;
+ @Mock private NetworkScorerAppManager mNetworkScorerAppManager;
+ @Mock private Context mContext;
+ @Mock private Resources mResources;
+ @Mock private INetworkScoreCache.Stub mNetworkScoreCache, mNetworkScoreCache2;
+ @Mock private IBinder mIBinder, mIBinder2;
+ @Captor private ArgumentCaptor<List<ScoredNetwork>> mScoredNetworkCaptor;
+
+ private ContentResolver mContentResolver;
+ private NetworkScoreService mNetworkScoreService;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mNetworkScoreCache.asBinder()).thenReturn(mIBinder);
+ when(mNetworkScoreCache2.asBinder()).thenReturn(mIBinder2);
+ mContentResolver = InstrumentationRegistry.getContext().getContentResolver();
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getResources()).thenReturn(mResources);
+ mNetworkScoreService = new NetworkScoreService(mContext, mNetworkScorerAppManager);
+ }
+
+ @Test
+ public void testSystemReady_networkScorerProvisioned() throws Exception {
+ Settings.Global.putInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED, 1);
+
+ mNetworkScoreService.systemReady();
+
+ verify(mNetworkScorerAppManager, never()).setActiveScorer(anyString());
+ }
+
+ @Test
+ public void testSystemReady_networkScorerNotProvisioned_defaultScorer() throws Exception {
+ Settings.Global.putInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED, 0);
+
+ when(mResources.getString(R.string.config_defaultNetworkScorerPackageName))
+ .thenReturn(NEW_SCORER.mPackageName);
+
+ mNetworkScoreService.systemReady();
+
+ verify(mNetworkScorerAppManager).setActiveScorer(NEW_SCORER.mPackageName);
+ assertEquals(1,
+ Settings.Global.getInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED));
+
+ }
+
+ @Test
+ public void testSystemReady_networkScorerNotProvisioned_noDefaultScorer() throws Exception {
+ Settings.Global.putInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED, 0);
+
+ when(mResources.getString(R.string.config_defaultNetworkScorerPackageName))
+ .thenReturn(null);
+
+ mNetworkScoreService.systemReady();
+
+ verify(mNetworkScorerAppManager, never()).setActiveScorer(anyString());
+ assertEquals(1,
+ Settings.Global.getInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED));
+ }
+
+ @Test
+ public void testSystemRunning() {
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
+
+ mNetworkScoreService.systemRunning();
+
+ verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent(
+ new ComponentName(NEW_SCORER.mPackageName, NEW_SCORER.mScoringServiceClassName))),
+ any(ServiceConnection.class),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.SYSTEM));
+ }
+
+ @Test
+ public void testUpdateScores_notActiveScorer() {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+
+ try {
+ mNetworkScoreService.updateScores(new ScoredNetwork[0]);
+ fail("SecurityException expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testUpdateScores_oneRegisteredCache() throws RemoteException {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
+ mNetworkScoreCache, CACHE_FILTER_NONE);
+
+ mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
+
+ verify(mNetworkScoreCache).updateScores(mScoredNetworkCaptor.capture());
+
+ assertEquals(1, mScoredNetworkCaptor.getValue().size());
+ assertEquals(SCORED_NETWORK, mScoredNetworkCaptor.getValue().get(0));
+ }
+
+ @Test
+ public void testUpdateScores_twoRegisteredCaches() throws RemoteException {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
+ mNetworkScoreCache, CACHE_FILTER_NONE);
+ mNetworkScoreService.registerNetworkScoreCache(
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache2, CACHE_FILTER_NONE);
+
+ // updateScores should update both caches
+ mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
+
+ verify(mNetworkScoreCache).updateScores(anyListOf(ScoredNetwork.class));
+ verify(mNetworkScoreCache2).updateScores(anyListOf(ScoredNetwork.class));
+
+ mNetworkScoreService.unregisterNetworkScoreCache(
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache2);
+
+ // updateScores should only update the first cache since the 2nd has been unregistered
+ mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
+
+ verify(mNetworkScoreCache, times(2)).updateScores(anyListOf(ScoredNetwork.class));
+
+ mNetworkScoreService.unregisterNetworkScoreCache(
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache);
+
+ // updateScores should not update any caches since they are both unregistered
+ mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
+
+ // The register and unregister calls grab the binder from the score cache.
+ verify(mNetworkScoreCache, atLeastOnce()).asBinder();
+ verify(mNetworkScoreCache2, atLeastOnce()).asBinder();
+ verifyNoMoreInteractions(mNetworkScoreCache, mNetworkScoreCache2);
+ }
+
+ @Test
+ public void testClearScores_notActiveScorer_noBroadcastNetworkPermission() {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+ when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+ try {
+ mNetworkScoreService.clearScores();
+ fail("SecurityException expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testClearScores_activeScorer_noBroadcastNetworkPermission() {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+ when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+
+ mNetworkScoreService.clearScores();
+ }
+
+ @Test
+ public void testClearScores_activeScorer() throws RemoteException {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
+ CACHE_FILTER_NONE);
+ mNetworkScoreService.clearScores();
+
+ verify(mNetworkScoreCache).clearScores();
+ }
+
+ @Test
+ public void testClearScores_notActiveScorer_hasBroadcastNetworkPermission()
+ throws RemoteException {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+ when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
+ CACHE_FILTER_NONE);
+ mNetworkScoreService.clearScores();
+
+ verify(mNetworkScoreCache).clearScores();
+ }
+
+ @Test
+ public void testSetActiveScorer_noScoreNetworksPermission() {
+ doThrow(new SecurityException()).when(mContext)
+ .enforceCallingOrSelfPermission(eq(permission.SCORE_NETWORKS), anyString());
+
+ try {
+ mNetworkScoreService.setActiveScorer(null);
+ fail("SecurityException expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testSetActiveScorer_failure() throws RemoteException {
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER);
+ when(mNetworkScorerAppManager.setActiveScorer(NEW_SCORER.mPackageName)).thenReturn(false);
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
+ CACHE_FILTER_NONE);
+
+ boolean success = mNetworkScoreService.setActiveScorer(NEW_SCORER.mPackageName);
+
+ assertFalse(success);
+ verify(mNetworkScoreCache).clearScores();
+ verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent(
+ new ComponentName(PREV_SCORER.mPackageName, PREV_SCORER.mScoringServiceClassName))),
+ any(ServiceConnection.class),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.SYSTEM));
+ }
+
+ @Test
+ public void testSetActiveScorer_success() throws RemoteException {
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER, NEW_SCORER);
+ when(mNetworkScorerAppManager.setActiveScorer(NEW_SCORER.mPackageName)).thenReturn(true);
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
+ CACHE_FILTER_NONE);
+
+ boolean success = mNetworkScoreService.setActiveScorer(NEW_SCORER.mPackageName);
+
+ assertTrue(success);
+ verify(mNetworkScoreCache).clearScores();
+ verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent(
+ new ComponentName(NEW_SCORER.mPackageName, NEW_SCORER.mScoringServiceClassName))),
+ any(ServiceConnection.class),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.SYSTEM));
+ verify(mContext, times(2)).sendBroadcastAsUser(
+ MockUtils.checkIntentAction(NetworkScoreManager.ACTION_SCORER_CHANGED),
+ eq(UserHandle.SYSTEM));
+ }
+
+ @Test
+ public void testDisableScoring_notActiveScorer_noBroadcastNetworkPermission() {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+ when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+
+ try {
+ mNetworkScoreService.disableScoring();
+ fail("SecurityException expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+
+ }
+
+ @Test
+ public void testDisableScoring_activeScorer() throws RemoteException {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER, null);
+ when(mNetworkScorerAppManager.setActiveScorer(null)).thenReturn(true);
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
+ CACHE_FILTER_NONE);
+
+ mNetworkScoreService.disableScoring();
+
+ verify(mNetworkScoreCache).clearScores();
+ verify(mContext).sendBroadcastAsUser(
+ MockUtils.checkIntent(new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED)
+ .setPackage(PREV_SCORER.mPackageName)),
+ eq(UserHandle.SYSTEM));
+ verify(mContext, never()).bindServiceAsUser(any(Intent.class),
+ any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+ }
+
+ @Test
+ public void testDisableScoring_notActiveScorer_hasBroadcastNetworkPermission()
+ throws RemoteException {
+ when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+ when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER, null);
+ when(mNetworkScorerAppManager.setActiveScorer(null)).thenReturn(true);
+ mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
+ CACHE_FILTER_NONE);
+
+ mNetworkScoreService.disableScoring();
+
+ verify(mNetworkScoreCache).clearScores();
+ verify(mContext).sendBroadcastAsUser(
+ MockUtils.checkIntent(new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED)
+ .setPackage(PREV_SCORER.mPackageName)),
+ eq(UserHandle.SYSTEM));
+ verify(mContext, never()).bindServiceAsUser(any(Intent.class),
+ any(ServiceConnection.class), anyInt(), any(UserHandle.class));
+ }
+
+ @Test
+ public void testRegisterNetworkScoreCache_noBroadcastNetworkPermission() {
+ doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
+ eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString());
+
+ try {
+ mNetworkScoreService.registerNetworkScoreCache(
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache, CACHE_FILTER_NONE);
+ fail("SecurityException expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testUnregisterNetworkScoreCache_noBroadcastNetworkPermission() {
+ doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
+ eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString());
+
+ try {
+ mNetworkScoreService.unregisterNetworkScoreCache(
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache);
+ fail("SecurityException expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testDump_noDumpPermission() {
+ doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
+ eq(permission.DUMP), anyString());
+
+ try {
+ mNetworkScoreService.dump(
+ new FileDescriptor(), new PrintWriter(new StringWriter()), new String[0]);
+ fail("SecurityException expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testDump_doesNotCrash() {
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
+ StringWriter stringWriter = new StringWriter();
+
+ mNetworkScoreService.dump(
+ new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
+
+ assertFalse(stringWriter.toString().isEmpty());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/GestureDescriptionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/GestureDescriptionTest.java
new file mode 100644
index 0000000..b876a5f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/GestureDescriptionTest.java
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility;
+
+import static android.accessibilityservice.GestureDescription.StrokeDescription.INVALID_STROKE_ID;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.everyItem;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import android.accessibilityservice.GestureDescription;
+import android.accessibilityservice.GestureDescription.GestureStep;
+import android.accessibilityservice.GestureDescription.MotionEventGenerator;
+import android.accessibilityservice.GestureDescription.StrokeDescription;
+import android.graphics.Path;
+import android.graphics.PointF;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Test;
+
+import java.util.List;
+
+import static junit.framework.TestCase.assertEquals;
+
+/**
+ * Tests for GestureDescription
+ */
+public class GestureDescriptionTest {
+ @Test
+ public void testGestureShorterThanSampleRate_producesStartAndEnd() {
+ PointF click = new PointF(10, 20);
+ Path clickPath = new Path();
+ clickPath.moveTo(click.x, click.y);
+ StrokeDescription clickStroke = new StrokeDescription(clickPath, 0, 10);
+ GestureDescription.Builder clickBuilder = new GestureDescription.Builder();
+ clickBuilder.addStroke(clickStroke);
+ GestureDescription clickGesture = clickBuilder.build();
+
+ List<GestureStep> clickGestureSteps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(clickGesture, 100);
+
+ assertEquals(2, clickGestureSteps.size());
+ assertThat(clickGestureSteps.get(0), allOf(numTouchPointsIs(1), numStartsOfStroke(1),
+ numEndsOfStroke(0), hasPoint(click)));
+ assertThat(clickGestureSteps.get(1), allOf(numTouchPointsIs(1), numStartsOfStroke(0),
+ numEndsOfStroke(1), hasPoint(click)));
+ }
+
+ @Test
+ public void testSwipe_shouldContainEvenlySpacedPoints() {
+ int samplePeriod = 10;
+ int numSamples = 5;
+ float stepX = 2;
+ float stepY = 3;
+ PointF start = new PointF(10, 20);
+ PointF end = new PointF(10 + numSamples * stepX, 20 + numSamples * stepY);
+
+ GestureDescription swipe =
+ createSwipe(start.x, start.y, end.x, end.y, numSamples * samplePeriod);
+ List<GestureStep> swipeGestureSteps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(swipe, samplePeriod);
+ assertEquals(numSamples + 1, swipeGestureSteps.size());
+
+ assertThat(swipeGestureSteps.get(0), allOf(numTouchPointsIs(1), numStartsOfStroke(1),
+ numEndsOfStroke(0), hasPoint(start)));
+ assertThat(swipeGestureSteps.get(numSamples), allOf(numTouchPointsIs(1),
+ numStartsOfStroke(0), numEndsOfStroke(1), hasPoint(end)));
+
+ for (int i = 1; i < numSamples; ++i) {
+ PointF interpPoint = new PointF(start.x + stepX * i, start.y + stepY * i);
+ assertThat(swipeGestureSteps.get(i), allOf(numTouchPointsIs(1),
+ numStartsOfStroke(0), numEndsOfStroke(0), hasPoint(interpPoint)));
+ }
+ }
+
+ @Test
+ public void testSwipeWithNonIntegerValues_shouldRound() {
+ int strokeTime = 10;
+
+ GestureDescription swipe = createSwipe(10.1f, 20.6f, 11.9f, 22.1f, strokeTime);
+ List<GestureStep> swipeGestureSteps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(swipe, strokeTime);
+ assertEquals(2, swipeGestureSteps.size());
+ assertThat(swipeGestureSteps.get(0), hasPoint(new PointF(10, 21)));
+ assertThat(swipeGestureSteps.get(1), hasPoint(new PointF(12, 22)));
+ }
+
+ @Test
+ public void testPathsWithOverlappingTiming_produceCorrectSteps() {
+ // There are 4 paths
+ // 0: an L-shaped path that starts first
+ // 1: a swipe that starts in the middle of the L-shaped path and ends when the L ends
+ // 2: a swipe that starts at the same time as #1 but extends past the end of the L
+ // 3: a swipe that starts when #3 ends
+ PointF path0Start = new PointF(100, 150);
+ PointF path0Turn = new PointF(100, 200);
+ PointF path0End = new PointF(250, 200);
+ int path0StartTime = 0;
+ int path0EndTime = 100;
+ int path0Duration = path0EndTime - path0StartTime;
+ Path path0 = new Path();
+ path0.moveTo(path0Start.x, path0Start.y);
+ path0.lineTo(path0Turn.x, path0Turn.y);
+ path0.lineTo(path0End.x, path0End.y);
+ StrokeDescription path0Stroke = new StrokeDescription(path0, path0StartTime, path0Duration);
+
+ PointF path1Start = new PointF(300, 350);
+ PointF path1End = new PointF(300, 400);
+ int path1StartTime = 50;
+ int path1EndTime = path0EndTime;
+ StrokeDescription path1Stroke = createSwipeStroke(
+ path1Start.x, path1Start.y, path1End.x, path1End.y, path1StartTime, path1EndTime);
+
+ PointF path2Start = new PointF(400, 450);
+ PointF path2End = new PointF(400, 500);
+ int path2StartTime = 50;
+ int path2EndTime = 150;
+ StrokeDescription path2Stroke = createSwipeStroke(
+ path2Start.x, path2Start.y, path2End.x, path2End.y, path2StartTime, path2EndTime);
+
+ PointF path3Start = new PointF(500, 550);
+ PointF path3End = new PointF(500, 600);
+ int path3StartTime = path2EndTime;
+ int path3EndTime = 200;
+ StrokeDescription path3Stroke = createSwipeStroke(
+ path3Start.x, path3Start.y, path3End.x, path3End.y, path3StartTime, path3EndTime);
+
+ int deltaT = 12; // Force samples to happen on extra boundaries
+ GestureDescription.Builder builder = new GestureDescription.Builder();
+ builder.addStroke(path0Stroke);
+ builder.addStroke(path1Stroke);
+ builder.addStroke(path2Stroke);
+ builder.addStroke(path3Stroke);
+ List<GestureStep> steps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(builder.build(), deltaT);
+
+ long start = 0;
+ assertThat(steps.get(0), allOf(numStartsOfStroke(1), numEndsOfStroke(0), isAtTime(start),
+ numTouchPointsIs(1), hasPoint(path0Start)));
+ assertThat(steps.get(1), allOf(numTouchPointsIs(1), noStartsOrEnds(),
+ isAtTime(start + deltaT)));
+ assertThat(steps.get(2), allOf(numTouchPointsIs(1), isAtTime(start + deltaT * 2)));
+ assertThat(steps.get(3), allOf(numTouchPointsIs(1), isAtTime(start + deltaT * 3)));
+ assertThat(steps.get(4), allOf(numTouchPointsIs(1), isAtTime(start + deltaT * 4)));
+
+ assertThat(steps.get(5), allOf(numTouchPointsIs(3), numStartsOfStroke(2),
+ numEndsOfStroke(0), isAtTime(path1StartTime), hasPoint(path1Start),
+ hasPoint(path2Start)));
+
+ start = path1StartTime;
+ assertThat(steps.get(6), allOf(numTouchPointsIs(3), isAtTime(start + deltaT * 1)));
+ assertThat(steps.get(7), allOf(noStartsOrEnds(), isAtTime(start + deltaT * 2)));
+ assertThat(steps.get(8), allOf(numTouchPointsIs(3), isAtTime(start + deltaT * 3)));
+ assertThat(steps.get(9), allOf(noStartsOrEnds(), isAtTime(start + deltaT * 4)));
+
+ assertThat(steps.get(10), allOf(numTouchPointsIs(3), numStartsOfStroke(0),
+ numEndsOfStroke(2), isAtTime(path0EndTime), hasPoint(path0End),
+ hasPoint(path1End)));
+
+ start = path0EndTime;
+ assertThat(steps.get(11), allOf(numTouchPointsIs(1), isAtTime(start + deltaT * 1)));
+ assertThat(steps.get(12), allOf(noStartsOrEnds(), isAtTime(start + deltaT * 2)));
+ assertThat(steps.get(13), allOf(numTouchPointsIs(1), isAtTime(start + deltaT * 3)));
+ assertThat(steps.get(14), allOf(noStartsOrEnds(), isAtTime(start + deltaT * 4)));
+
+ assertThat(steps.get(15), allOf(numTouchPointsIs(2), numStartsOfStroke(1),
+ numEndsOfStroke(1), isAtTime(path2EndTime), hasPoint(path2End),
+ hasPoint(path3Start)));
+
+ start = path2EndTime;
+ assertThat(steps.get(16), allOf(numTouchPointsIs(1), isAtTime(start + deltaT * 1)));
+ assertThat(steps.get(17), allOf(noStartsOrEnds(), isAtTime(start + deltaT * 2)));
+ assertThat(steps.get(18), allOf(numTouchPointsIs(1), isAtTime(start + deltaT * 3)));
+ assertThat(steps.get(19), allOf(noStartsOrEnds(), isAtTime(start + deltaT * 4)));
+
+ assertThat(steps.get(20), allOf(numTouchPointsIs(1), numStartsOfStroke(0),
+ numEndsOfStroke(1), isAtTime(path3EndTime), hasPoint(path3End)));
+ }
+
+ @Test
+ public void testMaxTouchpoints_shouldHaveValidCoords() {
+ GestureDescription.Builder maxPointBuilder = new GestureDescription.Builder();
+ PointF baseStartPoint = new PointF(100, 100);
+ PointF baseEndPoint = new PointF(100, 200);
+ int xStep = 10;
+ int samplePeriod = 15;
+ int numSamples = 2;
+ int numPoints = GestureDescription.getMaxStrokeCount();
+ for (int i = 0; i < numPoints; i++) {
+ Path path = new Path();
+ path.moveTo(baseStartPoint.x + i * xStep, baseStartPoint.y);
+ path.lineTo(baseEndPoint.x + i * xStep, baseEndPoint.y);
+ maxPointBuilder.addStroke(new StrokeDescription(path, 0, samplePeriod * numSamples));
+ }
+
+ List<GestureStep> steps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(maxPointBuilder.build(), samplePeriod);
+ assertEquals(3, steps.size());
+
+ assertThat(steps.get(0), allOf(numTouchPointsIs(numPoints), numStartsOfStroke(numPoints),
+ numEndsOfStroke(0), isAtTime(0)));
+ assertThat(steps.get(1), allOf(numTouchPointsIs(numPoints), numStartsOfStroke(0),
+ numEndsOfStroke(0), isAtTime(samplePeriod)));
+ assertThat(steps.get(2), allOf(numTouchPointsIs(numPoints), numStartsOfStroke(0),
+ numEndsOfStroke(numPoints), isAtTime(samplePeriod * 2)));
+
+ PointF baseMidPoint = new PointF((baseStartPoint.x + baseEndPoint.x) / 2,
+ (baseStartPoint.y + baseEndPoint.y) / 2);
+ for (int i = 0; i < numPoints; i++) {
+ assertThat(steps.get(0),
+ hasPoint(new PointF(baseStartPoint.x + i * xStep, baseStartPoint.y)));
+ assertThat(steps.get(1),
+ hasPoint(new PointF(baseMidPoint.x + i * xStep, baseMidPoint.y)));
+ assertThat(steps.get(2),
+ hasPoint(new PointF(baseEndPoint.x + i * xStep, baseEndPoint.y)));
+ }
+ }
+
+ @Test
+ public void testGetGestureSteps_touchPointsHaveStrokeId() {
+ StrokeDescription swipeStroke = createSwipeStroke(10, 20, 30, 40, 0, 100);
+ GestureDescription swipe = new GestureDescription.Builder().addStroke(swipeStroke).build();
+ List<GestureStep> swipeGestureSteps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(swipe, 10);
+
+ assertThat(swipeGestureSteps, everyItem(hasStrokeId(swipeStroke.getId())));
+ }
+
+ @Test
+ public void testGetGestureSteps_continuedStroke_hasNoEndPoint() {
+ Path swipePath = new Path();
+ swipePath.moveTo(10, 20);
+ swipePath.lineTo(30, 40);
+ StrokeDescription stroke1 =
+ new StrokeDescription(swipePath, 0, 100, 0, true);
+ GestureDescription gesture = new GestureDescription.Builder().addStroke(stroke1).build();
+ List<GestureStep> steps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(gesture, 10);
+
+ assertThat(steps, everyItem(numEndsOfStroke(0)));
+ }
+
+ @Test
+ public void testGetGestureSteps_continuingStroke_hasNoStartPointAndHasContinuedId() {
+ Path swipePath = new Path();
+ swipePath.moveTo(10, 20);
+ swipePath.lineTo(30, 40);
+ StrokeDescription stroke1 =
+ new StrokeDescription(swipePath, 0, 100, INVALID_STROKE_ID, true);
+ StrokeDescription stroke2 =
+ new StrokeDescription(swipePath, 0, 100, stroke1.getId(), false);
+ GestureDescription gesture = new GestureDescription.Builder().addStroke(stroke2).build();
+ List<GestureStep> steps = MotionEventGenerator
+ .getGestureStepsFromGestureDescription(gesture, 10);
+
+ assertThat(steps, everyItem(
+ allOf(continuesStrokeId(stroke1.getId()), numStartsOfStroke(0))));
+ }
+
+ private GestureDescription createSwipe(
+ float startX, float startY, float endX, float endY, long duration) {
+ GestureDescription.Builder swipeBuilder = new GestureDescription.Builder();
+ swipeBuilder.addStroke(createSwipeStroke(startX, startY, endX, endY, 0, duration));
+ return swipeBuilder.build();
+ }
+
+ private StrokeDescription createSwipeStroke(
+ float startX, float startY, float endX, float endY, long startTime, long endTime) {
+ Path swipePath = new Path();
+ swipePath.moveTo(startX, startY);
+ swipePath.lineTo(endX, endY);
+ StrokeDescription swipeStroke =
+ new StrokeDescription(swipePath, startTime, endTime - startTime);
+ return swipeStroke;
+ }
+
+ Matcher<GestureStep> numTouchPointsIs(final int numTouchPoints) {
+ return new TypeSafeMatcher<GestureStep>() {
+ @Override
+ protected boolean matchesSafely(GestureStep gestureStep) {
+ return gestureStep.numTouchPoints == numTouchPoints;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Has " + numTouchPoints + " touch point(s)");
+ }
+ };
+ }
+
+ Matcher<GestureStep> numStartsOfStroke(final int numStarts) {
+ return new TypeSafeMatcher<GestureStep>() {
+ @Override
+ protected boolean matchesSafely(GestureStep gestureStep) {
+ int numStartsFound = 0;
+ for (int i = 0; i < gestureStep.numTouchPoints; i++) {
+ if (gestureStep.touchPoints[i].mIsStartOfPath) {
+ numStartsFound++;
+ }
+ }
+ return numStartsFound == numStarts;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Starts " + numStarts + " stroke(s)");
+ }
+ };
+ }
+
+ Matcher<GestureStep> numEndsOfStroke(final int numEnds) {
+ return new TypeSafeMatcher<GestureStep>() {
+ @Override
+ protected boolean matchesSafely(GestureStep gestureStep) {
+ int numEndsFound = 0;
+ for (int i = 0; i < gestureStep.numTouchPoints; i++) {
+ if (gestureStep.touchPoints[i].mIsEndOfPath) {
+ numEndsFound++;
+ }
+ }
+ return numEndsFound == numEnds;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Ends " + numEnds + " stroke(s)");
+ }
+ };
+ }
+
+ Matcher<GestureStep> hasPoint(final PointF point) {
+ return new TypeSafeMatcher<GestureStep>() {
+ @Override
+ protected boolean matchesSafely(GestureStep gestureStep) {
+ for (int i = 0; i < gestureStep.numTouchPoints; i++) {
+ if ((gestureStep.touchPoints[i].mX == point.x)
+ && (gestureStep.touchPoints[i].mY == point.y)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Has at least one point at " + point);
+ }
+ };
+ }
+
+ Matcher<GestureStep> hasStrokeId(final int strokeId) {
+ return new TypeSafeMatcher<GestureStep>() {
+ @Override
+ protected boolean matchesSafely(GestureStep gestureStep) {
+ for (int i = 0; i < gestureStep.numTouchPoints; i++) {
+ if (gestureStep.touchPoints[i].mStrokeId == strokeId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Has at least one point with stroke id " + strokeId);
+ }
+ };
+ }
+
+ Matcher<GestureStep> continuesStrokeId(final int strokeId) {
+ return new TypeSafeMatcher<GestureStep>() {
+ @Override
+ protected boolean matchesSafely(GestureStep gestureStep) {
+ for (int i = 0; i < gestureStep.numTouchPoints; i++) {
+ if (gestureStep.touchPoints[i].mContinuedStrokeId == strokeId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Continues stroke id " + strokeId);
+ }
+ };
+ }
+
+ Matcher<GestureStep> isAtTime(final long time) {
+ return new TypeSafeMatcher<GestureStep>() {
+ @Override
+ protected boolean matchesSafely(GestureStep gestureStep) {
+ return gestureStep.timeSinceGestureStart == time;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Is at time " + time);
+ }
+ };
+ }
+
+ Matcher<GestureStep> noStartsOrEnds() {
+ return allOf(numStartsOfStroke(0), numEndsOfStroke(0));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
index d5305d9..73344e0 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
@@ -16,9 +16,17 @@
package com.android.server.accessibility;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_UP;
+import static android.view.WindowManagerPolicy.FLAG_PASS_TO_USER;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.anyOf;
+import static org.hamcrest.CoreMatchers.everyItem;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
@@ -29,7 +37,10 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
+import android.accessibilityservice.GestureDescription.GestureStep;
+import android.accessibilityservice.GestureDescription.TouchPoint;
import android.accessibilityservice.IAccessibilityServiceClient;
+import android.graphics.Point;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -40,11 +51,15 @@
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
-import android.view.WindowManagerPolicy;
+
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import android.view.accessibility.AccessibilityEvent;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -58,30 +73,59 @@
@RunWith(AndroidJUnit4.class)
public class MotionEventInjectorTest {
private static final String LOG_TAG = "MotionEventInjectorTest";
- private static final int CLICK_X = 100;
- private static final int CLICK_Y_START = 200;
- private static final int CLICK_Y_END = 201;
- private static final int CLICK_DURATION = 10;
- private static final int SEQUENCE = 50;
+ private static final Matcher<MotionEvent> IS_ACTION_DOWN =
+ new MotionEventActionMatcher(ACTION_DOWN);
+ private static final Matcher<MotionEvent> IS_ACTION_POINTER_DOWN =
+ new MotionEventActionMatcher(MotionEvent.ACTION_POINTER_DOWN);
+ private static final Matcher<MotionEvent> IS_ACTION_UP =
+ new MotionEventActionMatcher(ACTION_UP);
+ private static final Matcher<MotionEvent> IS_ACTION_POINTER_UP =
+ new MotionEventActionMatcher(MotionEvent.ACTION_POINTER_UP);
+ private static final Matcher<MotionEvent> IS_ACTION_CANCEL =
+ new MotionEventActionMatcher(MotionEvent.ACTION_CANCEL);
+ private static final Matcher<MotionEvent> IS_ACTION_MOVE =
+ new MotionEventActionMatcher(MotionEvent.ACTION_MOVE);
- private static final int SECOND_CLICK_X = 1000;
- private static final int SECOND_CLICK_Y = 2000;
- private static final int SECOND_SEQUENCE = 51;
+ private static final Point LINE_START = new Point(100, 200);
+ private static final Point LINE_END = new Point(100, 300);
+ private static final int LINE_DURATION = 100;
+ private static final int LINE_SEQUENCE = 50;
+
+ private static final Point CLICK_POINT = new Point(1000, 2000);
+ private static final int CLICK_DURATION = 10;
+ private static final int CLICK_SEQUENCE = 51;
private static final int MOTION_EVENT_SOURCE = InputDevice.SOURCE_TOUCHSCREEN;
private static final int OTHER_EVENT_SOURCE = InputDevice.SOURCE_MOUSE;
+ private static final Point CONTINUED_LINE_START = new Point(500, 300);
+ private static final Point CONTINUED_LINE_MID1 = new Point(500, 400);
+ private static final Point CONTINUED_LINE_MID2 = new Point(600, 300);
+ private static final Point CONTINUED_LINE_END = new Point(600, 400);
+ private static final int CONTINUED_LINE_STROKE_ID_1 = 100;
+ private static final int CONTINUED_LINE_STROKE_ID_2 = 101;
+ private static final int CONTINUED_LINE_INTERVAL = 100;
+ private static final int CONTINUED_LINE_SEQUENCE_1 = 52;
+ private static final int CONTINUED_LINE_SEQUENCE_2 = 53;
+
MotionEventInjector mMotionEventInjector;
IAccessibilityServiceClient mServiceInterface;
- List<MotionEvent> mClickList = new ArrayList<>();
- List<MotionEvent> mSecondClickList = new ArrayList<>();
+ List<GestureStep> mLineList = new ArrayList<>();
+ List<GestureStep> mClickList = new ArrayList<>();
+ List<GestureStep> mContinuedLineList1 = new ArrayList<>();
+ List<GestureStep> mContinuedLineList2 = new ArrayList<>();
+
+ MotionEvent mClickDownEvent;
+ MotionEvent mClickUpEvent;
+
ArgumentCaptor<MotionEvent> mCaptor1 = ArgumentCaptor.forClass(MotionEvent.class);
ArgumentCaptor<MotionEvent> mCaptor2 = ArgumentCaptor.forClass(MotionEvent.class);
MessageCapturingHandler mMessageCapturingHandler;
- MotionEventMatcher mClickEvent0Matcher;
- MotionEventMatcher mClickEvent1Matcher;
- MotionEventMatcher mClickEvent2Matcher;
- MotionEventMatcher mSecondClickEvent0Matcher;
+ Matcher<MotionEvent> mIsLineStart;
+ Matcher<MotionEvent> mIsLineMiddle;
+ Matcher<MotionEvent> mIsLineEnd;
+ Matcher<MotionEvent> mIsClickDown;
+ Matcher<MotionEvent> mIsClickUp;
@BeforeClass
public static void oneTimeInitialization() {
@@ -99,226 +143,191 @@
}
});
mMotionEventInjector = new MotionEventInjector(mMessageCapturingHandler);
- mClickList.add(
- MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, CLICK_X, CLICK_Y_START, 0));
- mClickList.add(MotionEvent.obtain(
- 0, CLICK_DURATION, MotionEvent.ACTION_MOVE, CLICK_X, CLICK_Y_END, 0));
- mClickList.add(MotionEvent.obtain(
- 0, CLICK_DURATION, MotionEvent.ACTION_UP, CLICK_X, CLICK_Y_END, 0));
- for (int i = 0; i < mClickList.size(); i++) {
- mClickList.get(i).setSource(MOTION_EVENT_SOURCE);
- }
-
- mClickEvent0Matcher = new MotionEventMatcher(mClickList.get(0));
- mClickEvent1Matcher = new MotionEventMatcher(mClickList.get(1));
- mClickEvent2Matcher = new MotionEventMatcher(mClickList.get(2));
-
- mSecondClickList.add(MotionEvent.obtain(
- 0, 0, MotionEvent.ACTION_DOWN, SECOND_CLICK_X, SECOND_CLICK_Y, 0));
- mSecondClickList.add(MotionEvent.obtain(
- 0, CLICK_DURATION, MotionEvent.ACTION_MOVE, SECOND_CLICK_X, CLICK_Y_END, 0));
- mSecondClickList.add(MotionEvent.obtain(
- 0, CLICK_DURATION, MotionEvent.ACTION_UP, SECOND_CLICK_X, CLICK_Y_END, 0));
- for (int i = 0; i < mSecondClickList.size(); i++) {
- mSecondClickList.get(i).setSource(MOTION_EVENT_SOURCE);
- }
-
- mSecondClickEvent0Matcher = new MotionEventMatcher(mSecondClickList.get(0));
-
mServiceInterface = mock(IAccessibilityServiceClient.class);
+
+ mLineList = createSimpleGestureFromPoints(0, 0, false, LINE_DURATION, LINE_START, LINE_END);
+ mClickList = createSimpleGestureFromPoints(
+ 0, 0, false, CLICK_DURATION, CLICK_POINT, CLICK_POINT);
+ mContinuedLineList1 = createSimpleGestureFromPoints(CONTINUED_LINE_STROKE_ID_1, 0, true,
+ CONTINUED_LINE_INTERVAL, CONTINUED_LINE_START, CONTINUED_LINE_MID1);
+ mContinuedLineList2 = createSimpleGestureFromPoints(CONTINUED_LINE_STROKE_ID_2,
+ CONTINUED_LINE_STROKE_ID_1, false, CONTINUED_LINE_INTERVAL, CONTINUED_LINE_MID1,
+ CONTINUED_LINE_MID2, CONTINUED_LINE_END);
+
+ mClickDownEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, CLICK_POINT.x, CLICK_POINT.y, 0);
+ mClickDownEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ mClickUpEvent = MotionEvent.obtain(0, CLICK_DURATION, ACTION_UP, CLICK_POINT.x,
+ CLICK_POINT.y, 0);
+ mClickUpEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+
+ mIsLineStart = allOf(IS_ACTION_DOWN, isAtPoint(LINE_START), hasStandardInitialization(),
+ hasTimeFromDown(0));
+ mIsLineMiddle = allOf(IS_ACTION_MOVE, isAtPoint(LINE_END), hasStandardInitialization(),
+ hasTimeFromDown(LINE_DURATION));
+ mIsLineEnd = allOf(IS_ACTION_UP, isAtPoint(LINE_END), hasStandardInitialization(),
+ hasTimeFromDown(LINE_DURATION));
+ mIsClickDown = allOf(IS_ACTION_DOWN, isAtPoint(CLICK_POINT), hasStandardInitialization(),
+ hasTimeFromDown(0));
+ mIsClickUp = allOf(IS_ACTION_UP, isAtPoint(CLICK_POINT), hasStandardInitialization(),
+ hasTimeFromDown(CLICK_DURATION));
}
@Test
public void testInjectEvents_shouldEmergeInOrderWithCorrectTiming() throws RemoteException {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
verifyNoMoreInteractions(next);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(),
- eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
- long gestureStart = mCaptor1.getValue().getDownTime();
- mClickEvent0Matcher.offsetTimesBy(gestureStart);
- mClickEvent1Matcher.offsetTimesBy(gestureStart);
- mClickEvent2Matcher.offsetTimesBy(gestureStart);
-
- verify(next).onMotionEvent(argThat(mClickEvent0Matcher), argThat(mClickEvent0Matcher),
- eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
+ verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), eq(FLAG_PASS_TO_USER));
+ verify(next).onMotionEvent(argThat(mIsLineStart), argThat(mIsLineStart),
+ eq(FLAG_PASS_TO_USER));
verifyNoMoreInteractions(next);
reset(next);
+ Matcher<MotionEvent> hasRightDownTime = hasDownTime(mCaptor1.getValue().getDownTime());
+
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- verify(next).onMotionEvent(argThat(mClickEvent1Matcher), argThat(mClickEvent1Matcher),
- eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
+ verify(next).onMotionEvent(argThat(allOf(mIsLineMiddle, hasRightDownTime)),
+ argThat(allOf(mIsLineMiddle, hasRightDownTime)), eq(FLAG_PASS_TO_USER));
verifyNoMoreInteractions(next);
reset(next);
verifyZeroInteractions(mServiceInterface);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- verify(next).onMotionEvent(argThat(mClickEvent2Matcher), argThat(mClickEvent2Matcher),
- eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
+ verify(next).onMotionEvent(argThat(allOf(mIsLineEnd, hasRightDownTime)),
+ argThat(allOf(mIsLineEnd, hasRightDownTime)), eq(FLAG_PASS_TO_USER));
verifyNoMoreInteractions(next);
- reset(next);
- verify(mServiceInterface).onPerformGestureResult(SEQUENCE, true);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true);
verifyNoMoreInteractions(mServiceInterface);
}
@Test
- public void testInjectEvents_eventWithManyPointers_shouldNotCrash() {
- int manyPointersCount = 20;
- MotionEvent.PointerCoords[] pointerCoords =
- new MotionEvent.PointerCoords[manyPointersCount];
- MotionEvent.PointerProperties[] pointerProperties =
- new MotionEvent.PointerProperties[manyPointersCount];
- for (int i = 0; i < manyPointersCount; i++) {
- pointerProperties[i] = new MotionEvent.PointerProperties();
- pointerProperties[i].id = i;
- pointerProperties[i].toolType = MotionEvent.TOOL_TYPE_UNKNOWN;
- pointerCoords[i] = new MotionEvent.PointerCoords();
- pointerCoords[i].clear();
- pointerCoords[i].pressure = 1.0f;
- pointerCoords[i].size = 1.0f;
- pointerCoords[i].x = i;
- pointerCoords[i].y = i;
+ public void testInjectEvents_gestureWithTooManyPoints_shouldNotCrash() throws Exception {
+ int tooManyPointsCount = 20;
+ TouchPoint[] startTouchPoints = new TouchPoint[tooManyPointsCount];
+ TouchPoint[] endTouchPoints = new TouchPoint[tooManyPointsCount];
+ for (int i = 0; i < tooManyPointsCount; i++) {
+ startTouchPoints[i] = new TouchPoint();
+ startTouchPoints[i].mIsStartOfPath = true;
+ startTouchPoints[i].mX = i;
+ startTouchPoints[i].mY = i;
+ endTouchPoints[i] = new TouchPoint();
+ endTouchPoints[i].mIsEndOfPath = true;
+ endTouchPoints[i].mX = i;
+ endTouchPoints[i].mY = i;
}
- List<MotionEvent> events = new ArrayList<>();
- events.add(MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, manyPointersCount,
- pointerProperties, pointerCoords, 0, 0,
- 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0));
- events.add(MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, manyPointersCount,
- pointerProperties, pointerCoords, 0, 0,
- 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0));
- EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.injectEvents(events, mServiceInterface, SEQUENCE);
+ List<GestureStep> events = Arrays.asList(
+ new GestureStep(0, tooManyPointsCount, startTouchPoints),
+ new GestureStep(CLICK_DURATION, tooManyPointsCount, endTouchPoints));
+ attachMockNext(mMotionEventInjector);
+ injectEventsSync(events, mServiceInterface, CLICK_SEQUENCE);
mMessageCapturingHandler.sendAllMessages();
- verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- assertEquals(MotionEvent.ACTION_DOWN, mCaptor1.getAllValues().get(0).getActionMasked());
- assertEquals(MotionEvent.ACTION_UP, mCaptor1.getAllValues().get(1).getActionMasked());
+ verify(mServiceInterface).onPerformGestureResult(eq(CLICK_SEQUENCE), anyBoolean());
}
@Test
public void testRegularEvent_afterGestureComplete_shouldPassToNext() {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
mMessageCapturingHandler.sendAllMessages(); // Send all motion events
reset(next);
- mMotionEventInjector.onMotionEvent(mSecondClickList.get(0), mClickList.get(0), 0);
- verify(next).onMotionEvent(argThat(mSecondClickEvent0Matcher),
- argThat(mClickEvent0Matcher), eq(0));
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
+ verify(next).onMotionEvent(argThat(mIsClickDown), argThat(mIsClickDown), eq(0));
}
@Test
public void testInjectEvents_withRealGestureUnderway_shouldCancelRealAndPassInjected() {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0);
- mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- assertEquals(MotionEvent.ACTION_CANCEL, mCaptor1.getAllValues().get(1).getActionMasked());
+ assertThat(mCaptor1.getAllValues().get(0), mIsClickDown);
+ assertThat(mCaptor1.getAllValues().get(1), IS_ACTION_CANCEL);
reset(next);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(),
- eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
- long gestureStart = mCaptor1.getValue().getDownTime();
- mSecondClickEvent0Matcher.offsetTimesBy(gestureStart);
-
- verify(next).onMotionEvent(argThat(mSecondClickEvent0Matcher),
- argThat(mSecondClickEvent0Matcher), eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
+ verify(next).onMotionEvent(
+ argThat(mIsLineStart), argThat(mIsLineStart), eq(FLAG_PASS_TO_USER));
}
@Test
public void testInjectEvents_withRealMouseGestureUnderway_shouldContinueRealAndPassInjected() {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- MotionEvent mouseEvent = MotionEvent.obtain(mClickList.get(0));
+ MotionEvent mouseEvent = MotionEvent.obtain(mClickDownEvent);
mouseEvent.setSource(InputDevice.SOURCE_MOUSE);
- MotionEventMatcher mouseEventMatcher = new MotionEventMatcher(mouseEvent);
+ MotionEventMatcher isMouseEvent = new MotionEventMatcher(mouseEvent);
mMotionEventInjector.onMotionEvent(mouseEvent, mouseEvent, 0);
- mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- assertTrue(mouseEventMatcher.matches(mCaptor1.getAllValues().get(0)));
- mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(1).getDownTime());
- assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(1)));
+ assertThat(mCaptor1.getAllValues().get(0), isMouseEvent);
+ assertThat(mCaptor1.getAllValues().get(1), mIsLineStart);
}
@Test
public void testInjectEvents_withRealGestureFinished_shouldJustPassInjected() {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0);
- mMotionEventInjector.onMotionEvent(mClickList.get(1), mClickList.get(1), 0);
- mMotionEventInjector.onMotionEvent(mClickList.get(2), mClickList.get(2), 0);
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
+ mMotionEventInjector.onMotionEvent(mClickUpEvent, mClickUpEvent, 0);
- mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
- verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
-
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- assertTrue(mClickEvent1Matcher.matches(mCaptor1.getAllValues().get(1)));
- assertTrue(mClickEvent2Matcher.matches(mCaptor1.getAllValues().get(2)));
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
+ verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ assertThat(mCaptor1.getAllValues().get(0), mIsClickDown);
+ assertThat(mCaptor1.getAllValues().get(1), mIsClickUp);
reset(next);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(),
- eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
- mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getValue().getDownTime());
- verify(next).onMotionEvent(argThat(mSecondClickEvent0Matcher),
- argThat(mSecondClickEvent0Matcher), eq(WindowManagerPolicy.FLAG_PASS_TO_USER));
+ verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), eq(FLAG_PASS_TO_USER));
+ verify(next).onMotionEvent(
+ argThat(mIsLineStart), argThat(mIsLineStart), eq(FLAG_PASS_TO_USER));
}
@Test
public void testOnMotionEvents_openInjectedGestureInProgress_shouldCancelAndNotifyAndPassReal()
throws RemoteException {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
-
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- mMotionEventInjector.onMotionEvent(mSecondClickList.get(0), mSecondClickList.get(0), 0);
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- mClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(0).getDownTime());
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- assertEquals(MotionEvent.ACTION_CANCEL, mCaptor1.getAllValues().get(1).getActionMasked());
- assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(2)));
- verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false);
+ assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
+ assertThat(mCaptor1.getAllValues().get(1), IS_ACTION_CANCEL);
+ assertThat(mCaptor1.getAllValues().get(2), mIsClickDown);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
}
@Test
public void testOnMotionEvents_closedInjectedGestureInProgress_shouldOnlyNotifyAndPassReal()
throws RemoteException {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mClickList.add(MotionEvent.obtain(2 * CLICK_DURATION, 2 * CLICK_DURATION,
- MotionEvent.ACTION_DOWN, CLICK_X, CLICK_Y_START, 0));
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ // Tack a click down to the end of the line
+ TouchPoint clickTouchPoint = new TouchPoint();
+ clickTouchPoint.mIsStartOfPath = true;
+ clickTouchPoint.mX = CLICK_POINT.x;
+ clickTouchPoint.mY = CLICK_POINT.y;
+ mLineList.add(new GestureStep(0, 1, new TouchPoint[] {clickTouchPoint}));
+
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
// Send 3 motion events, leaving the extra down in the queue
mMessageCapturingHandler.sendOneMessage();
mMessageCapturingHandler.sendOneMessage();
mMessageCapturingHandler.sendOneMessage();
- mMotionEventInjector.onMotionEvent(mSecondClickList.get(0), mClickList.get(0), 0);
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
verify(next, times(4)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- long gestureStart = mCaptor1.getAllValues().get(0).getDownTime();
- mClickEvent0Matcher.offsetTimesBy(gestureStart);
- mClickEvent1Matcher.offsetTimesBy(gestureStart);
- mClickEvent2Matcher.offsetTimesBy(gestureStart);
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- assertTrue(mClickEvent1Matcher.matches(mCaptor1.getAllValues().get(1)));
- assertTrue(mClickEvent2Matcher.matches(mCaptor1.getAllValues().get(2)));
- assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(3)));
-
- verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false);
+ assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
+ assertThat(mCaptor1.getAllValues().get(1), mIsLineMiddle);
+ assertThat(mCaptor1.getAllValues().get(2), mIsLineEnd);
+ assertThat(mCaptor1.getAllValues().get(3), mIsClickDown);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
assertFalse(mMessageCapturingHandler.hasMessages());
}
@@ -326,105 +335,327 @@
public void testInjectEvents_openInjectedGestureInProgress_shouldCancelAndNotifyAndPassNew()
throws RemoteException {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SECOND_SEQUENCE);
- mMessageCapturingHandler.sendLastMessage(); // Process the second event injection
+ injectEventsSync(mClickList, mServiceInterface, CLICK_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- verify(mServiceInterface, times(1)).onPerformGestureResult(SEQUENCE, false);
+ verify(mServiceInterface, times(1)).onPerformGestureResult(LINE_SEQUENCE, false);
verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- mClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(0).getDownTime());
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- assertEquals(MotionEvent.ACTION_CANCEL, mCaptor1.getAllValues().get(1).getActionMasked());
- mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(2).getDownTime());
- assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(2)));
+ assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
+ assertThat(mCaptor1.getAllValues().get(1), IS_ACTION_CANCEL);
+ assertThat(mCaptor1.getAllValues().get(2), mIsClickDown);
}
@Test
public void testInjectEvents_closedInjectedGestureInProgress_shouldOnlyNotifyAndPassNew()
throws RemoteException {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- MotionEvent newEvent = MotionEvent.obtain(2 * CLICK_DURATION, 2 * CLICK_DURATION,
- MotionEvent.ACTION_DOWN, CLICK_X, CLICK_Y_START, 0);
- newEvent.setSource(mClickList.get(0).getSource());
- mClickList.add(newEvent);
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ // Tack a click down to the end of the line
+ TouchPoint clickTouchPoint = new TouchPoint();
+ clickTouchPoint.mIsStartOfPath = true;
+ clickTouchPoint.mX = CLICK_POINT.x;
+ clickTouchPoint.mY = CLICK_POINT.y;
+ mLineList.add(new GestureStep(0, 1, new TouchPoint[] {clickTouchPoint}));
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
// Send 3 motion events, leaving newEvent in the queue
mMessageCapturingHandler.sendOneMessage();
mMessageCapturingHandler.sendOneMessage();
mMessageCapturingHandler.sendOneMessage();
- mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SECOND_SEQUENCE);
- mMessageCapturingHandler.sendLastMessage(); // Process the event injection
+ injectEventsSync(mClickList, mServiceInterface, CLICK_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
- verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
verify(next, times(4)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- long gestureStart = mCaptor1.getAllValues().get(0).getDownTime();
- mClickEvent0Matcher.offsetTimesBy(gestureStart);
- mClickEvent1Matcher.offsetTimesBy(gestureStart);
- mClickEvent2Matcher.offsetTimesBy(gestureStart);
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- assertTrue(mClickEvent1Matcher.matches(mCaptor1.getAllValues().get(1)));
- assertTrue(mClickEvent2Matcher.matches(mCaptor1.getAllValues().get(2)));
- mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(3).getDownTime());
- assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(3)));
+ assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
+ assertThat(mCaptor1.getAllValues().get(1), mIsLineMiddle);
+ assertThat(mCaptor1.getAllValues().get(2), mIsLineEnd);
+ assertThat(mCaptor1.getAllValues().get(3), mIsClickDown);
+ }
+
+ @Test
+ public void testContinuedGesture_continuationArrivesAfterDispatched_gestureCompletes()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
+ injectEventsSync(mContinuedLineList2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, true);
+ verify(next, times(5)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ long downTime = events.get(0).getDownTime();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN,
+ hasEventTime(downTime)));
+ assertThat(events, everyItem(hasDownTime(downTime)));
+ assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL)));
+ // Timing will restart when the gesture continues
+ long secondSequenceStart = events.get(2).getEventTime();
+ assertTrue(secondSequenceStart > events.get(1).getEventTime());
+ assertThat(events.get(2), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_MOVE));
+ assertThat(events.get(3), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_MOVE,
+ hasEventTime(secondSequenceStart + CONTINUED_LINE_INTERVAL)));
+ assertThat(events.get(4), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_UP,
+ hasEventTime(secondSequenceStart + CONTINUED_LINE_INTERVAL)));
+ }
+
+ @Test
+ public void testContinuedGesture_withTwoTouchPoints_gestureCompletes()
+ throws Exception {
+ // Run one point through the continued line backwards
+ int backLineId1 = 30;
+ int backLineId2 = 30;
+ List<GestureStep> continuedBackLineList1 = createSimpleGestureFromPoints(backLineId1, 0,
+ true, CONTINUED_LINE_INTERVAL, CONTINUED_LINE_END, CONTINUED_LINE_MID2);
+ List<GestureStep> continuedBackLineList2 = createSimpleGestureFromPoints(backLineId2,
+ backLineId1, false, CONTINUED_LINE_INTERVAL, CONTINUED_LINE_MID2,
+ CONTINUED_LINE_MID1, CONTINUED_LINE_START);
+ List<GestureStep> combinedLines1 = combineGestureSteps(
+ mContinuedLineList1, continuedBackLineList1);
+ List<GestureStep> combinedLines2 = combineGestureSteps(
+ mContinuedLineList2, continuedBackLineList2);
+
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(combinedLines1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ injectEventsSync(combinedLines2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, true);
+ verify(next, times(7)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ long downTime = events.get(0).getDownTime();
+ assertThat(events.get(0), allOf(
+ anyOf(isAtPoint(CONTINUED_LINE_END), isAtPoint(CONTINUED_LINE_START)),
+ IS_ACTION_DOWN, hasEventTime(downTime)));
+ assertThat(events, everyItem(hasDownTime(downTime)));
+ assertThat(events.get(1), allOf(containsPoints(CONTINUED_LINE_START, CONTINUED_LINE_END),
+ IS_ACTION_POINTER_DOWN, hasEventTime(downTime)));
+ assertThat(events.get(2), allOf(containsPoints(CONTINUED_LINE_MID1, CONTINUED_LINE_MID2),
+ IS_ACTION_MOVE, hasEventTime(downTime + CONTINUED_LINE_INTERVAL)));
+ assertThat(events.get(3), allOf(containsPoints(CONTINUED_LINE_MID1, CONTINUED_LINE_MID2),
+ IS_ACTION_MOVE, hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 2)));
+ assertThat(events.get(4), allOf(containsPoints(CONTINUED_LINE_START, CONTINUED_LINE_END),
+ IS_ACTION_MOVE, hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
+ assertThat(events.get(5), allOf(containsPoints(CONTINUED_LINE_START, CONTINUED_LINE_END),
+ IS_ACTION_POINTER_UP, hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
+ assertThat(events.get(6), allOf(
+ anyOf(isAtPoint(CONTINUED_LINE_END), isAtPoint(CONTINUED_LINE_START)),
+ IS_ACTION_UP, hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
+ }
+
+
+ @Test
+ public void testContinuedGesture_continuationArrivesWhileDispatching_gestureCompletes()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ mMessageCapturingHandler.sendOneMessage(); // Send a motion event
+ injectEventsSync(mContinuedLineList2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, true);
+ verify(next, times(5)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ long downTime = events.get(0).getDownTime();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN,
+ hasEventTime(downTime)));
+ assertThat(events, everyItem(hasDownTime(downTime)));
+ assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL)));
+ assertThat(events.get(2), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 2)));
+ assertThat(events.get(3), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
+ assertThat(events.get(4), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_UP,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
+ }
+
+ @Test
+ public void testContinuedGesture_twoContinuationsArriveWhileDispatching_gestureCompletes()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ // Continue line again
+ List<GestureStep> continuedLineList2 = createSimpleGestureFromPoints(
+ CONTINUED_LINE_STROKE_ID_2, CONTINUED_LINE_STROKE_ID_1, true,
+ CONTINUED_LINE_INTERVAL, CONTINUED_LINE_MID1,
+ CONTINUED_LINE_MID2, CONTINUED_LINE_END);
+ // Finish line by backtracking
+ int strokeId3 = CONTINUED_LINE_STROKE_ID_2 + 1;
+ int sequence3 = CONTINUED_LINE_SEQUENCE_2 + 1;
+ List<GestureStep> continuedLineList3 = createSimpleGestureFromPoints(strokeId3,
+ CONTINUED_LINE_STROKE_ID_2, false, CONTINUED_LINE_INTERVAL, CONTINUED_LINE_END,
+ CONTINUED_LINE_MID2);
+
+ mMessageCapturingHandler.sendOneMessage(); // Send a motion event
+ injectEventsSync(continuedLineList2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
+ injectEventsSync(continuedLineList3, mServiceInterface, sequence3);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, true);
+ verify(mServiceInterface).onPerformGestureResult(sequence3, true);
+ verify(next, times(6)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ long downTime = events.get(0).getDownTime();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN,
+ hasEventTime(downTime)));
+ assertThat(events, everyItem(hasDownTime(downTime)));
+ assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL)));
+ assertThat(events.get(2), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 2)));
+ assertThat(events.get(3), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
+ assertThat(events.get(4), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_MOVE,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 4)));
+ assertThat(events.get(5), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_UP,
+ hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 4)));
+ }
+
+ @Test
+ public void testContinuedGesture_nonContinuingGestureArrivesDuringDispatch_gestureCanceled()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ mMessageCapturingHandler.sendOneMessage(); // Send a motion event
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, false);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true);
+ verify(next, times(5)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
+ assertThat(events.get(1), IS_ACTION_CANCEL);
+ assertThat(events.get(2), allOf(isAtPoint(LINE_START), IS_ACTION_DOWN));
+ assertThat(events.get(3), allOf(isAtPoint(LINE_END), IS_ACTION_MOVE));
+ assertThat(events.get(4), allOf(isAtPoint(LINE_END), IS_ACTION_UP));
+ }
+
+ @Test
+ public void testContinuedGesture_nonContinuingGestureArrivesAfterDispatch_gestureCanceled()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true);
+ verify(next, times(6)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
+ assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE));
+ assertThat(events.get(2), IS_ACTION_CANCEL);
+ assertThat(events.get(3), allOf(isAtPoint(LINE_START), IS_ACTION_DOWN));
+ assertThat(events.get(4), allOf(isAtPoint(LINE_END), IS_ACTION_MOVE));
+ assertThat(events.get(5), allOf(isAtPoint(LINE_END), IS_ACTION_UP));
+ }
+
+ @Test
+ public void testContinuedGesture_misMatchedContinuationArrives_bothGesturesCanceled()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
+ List<GestureStep> discontinuousGesture = mContinuedLineList2
+ .subList(1, mContinuedLineList2.size());
+ injectEventsSync(discontinuousGesture, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, false);
+ verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
+ assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE));
+ assertThat(events.get(2), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_CANCEL));
+ }
+
+ @Test
+ public void testContinuedGesture_continuationArrivesFromOtherService_bothGesturesCanceled()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ IAccessibilityServiceClient otherService = mock(IAccessibilityServiceClient.class);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ mMessageCapturingHandler.sendOneMessage(); // Send a motion events
+ injectEventsSync(mContinuedLineList2, otherService, CONTINUED_LINE_SEQUENCE_2);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, false);
+ verify(otherService).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, false);
+ verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
+ assertThat(events.get(1), IS_ACTION_CANCEL);
+ }
+
+ @Test
+ public void testContinuedGesture_realGestureArrivesInBetween_getsCanceled()
+ throws Exception {
+ EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+ injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
+
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
+
+ injectEventsSync(mContinuedLineList2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
+ mMessageCapturingHandler.sendAllMessages(); // Send all motion events
+ verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, false);
+ verify(next, times(4)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+ List<MotionEvent> events = mCaptor1.getAllValues();
+ assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
+ assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE));
+ assertThat(events.get(2), IS_ACTION_CANCEL);
+ assertThat(events.get(3), allOf(isAtPoint(CLICK_POINT), IS_ACTION_DOWN));
}
@Test
public void testClearEvents_realGestureInProgress_shouldForgetAboutGesture() {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0);
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
mMotionEventInjector.clearEvents(MOTION_EVENT_SOURCE);
- mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(1).getDownTime());
- assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(1)));
+ assertThat(mCaptor1.getAllValues().get(0), mIsClickDown);
+ assertThat(mCaptor1.getAllValues().get(1), mIsLineStart);
}
@Test
public void testClearEventsOnOtherSource_realGestureInProgress_shouldNotForgetAboutGesture() {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
- mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0);
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
mMotionEventInjector.clearEvents(OTHER_EVENT_SOURCE);
- mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SECOND_SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
- assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0)));
- assertEquals(MotionEvent.ACTION_CANCEL, mCaptor1.getAllValues().get(1).getActionMasked());
- mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(2).getDownTime());
- assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(2)));
+ assertThat(mCaptor1.getAllValues().get(0), mIsClickDown);
+ assertThat(mCaptor1.getAllValues().get(1), IS_ACTION_CANCEL);
+ assertThat(mCaptor1.getAllValues().get(2), mIsLineStart);
}
@Test
public void testOnDestroy_shouldCancelGestures() throws RemoteException {
mMotionEventInjector.onDestroy();
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
- verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false);
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
}
@Test
public void testInjectEvents_withNoNext_shouldCancel() throws RemoteException {
- mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE);
- mMessageCapturingHandler.sendOneMessage(); // Process the event injection
- verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false);
+ injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
+ verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
}
@Test
public void testOnMotionEvent_withNoNext_shouldNotCrash() {
- mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0);
+ mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
}
@Test
@@ -455,6 +686,52 @@
mMotionEventInjector.onAccessibilityEvent(event);
}
+ private void injectEventsSync(List<GestureStep> gestureSteps,
+ IAccessibilityServiceClient serviceInterface, int sequence) {
+ mMotionEventInjector.injectEvents(gestureSteps, serviceInterface, sequence);
+ // Dispatch the message sent by the injector. Our simple handler doesn't guarantee stuff
+ // happens in order.
+ mMessageCapturingHandler.sendLastMessage();
+ }
+
+ private List<GestureStep> createSimpleGestureFromPoints(int strokeId, int continuedStrokeId,
+ boolean continued, long interval, Point... points) {
+ List<GestureStep> gesture = new ArrayList<>(points.length);
+ TouchPoint[] touchPoints = new TouchPoint[1];
+ touchPoints[0] = new TouchPoint();
+ for (int i = 0; i < points.length; i++) {
+ touchPoints[0].mX = points[i].x;
+ touchPoints[0].mY = points[i].y;
+ touchPoints[0].mIsStartOfPath = ((i == 0) && (continuedStrokeId <= 0));
+ touchPoints[0].mContinuedStrokeId = continuedStrokeId;
+ touchPoints[0].mStrokeId = strokeId;
+ touchPoints[0].mIsEndOfPath = ((i == points.length - 1) && !continued);
+ gesture.add(new GestureStep(interval * i, 1, touchPoints));
+ }
+ return gesture;
+ }
+
+ List<GestureStep> combineGestureSteps(List<GestureStep> list1, List<GestureStep> list2) {
+ assertEquals(list1.size(), list2.size());
+ List<GestureStep> gesture = new ArrayList<>(list1.size());
+ for (int i = 0; i < list1.size(); i++) {
+ int numPoints1 = list1.get(i).numTouchPoints;
+ int numPoints2 = list2.get(i).numTouchPoints;
+ TouchPoint[] touchPoints = new TouchPoint[numPoints1 + numPoints2];
+ for (int j = 0; j < numPoints1; j++) {
+ touchPoints[j] = new TouchPoint();
+ touchPoints[j].copyFrom(list1.get(i).touchPoints[j]);
+ }
+ for (int j = 0; j < numPoints2; j++) {
+ touchPoints[numPoints1 + j] = new TouchPoint();
+ touchPoints[numPoints1 + j].copyFrom(list2.get(i).touchPoints[j]);
+ }
+ gesture.add(new GestureStep(list1.get(i).timeSinceGestureStart,
+ numPoints1 + numPoints2, touchPoints));
+ }
+ return gesture;
+ }
+
private EventStreamTransformation attachMockNext(MotionEventInjector motionEventInjector) {
EventStreamTransformation next = mock(EventStreamTransformation.class);
motionEventInjector.setNext(next);
@@ -506,4 +783,126 @@
return false;
}
}
+
+ private static class MotionEventActionMatcher extends TypeSafeMatcher<MotionEvent> {
+ int mAction;
+
+ MotionEventActionMatcher(int action) {
+ super();
+ mAction = action;
+ }
+
+ @Override
+ protected boolean matchesSafely(MotionEvent motionEvent) {
+ return motionEvent.getActionMasked() == mAction;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Matching to action " + mAction);
+ }
+ }
+
+ private static TypeSafeMatcher<MotionEvent> isAtPoint(final Point point) {
+ return new TypeSafeMatcher<MotionEvent>() {
+ @Override
+ protected boolean matchesSafely(MotionEvent event) {
+ return ((event.getX() == point.x) && (event.getY() == point.y));
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Is at point " + point);
+ }
+ };
+ }
+
+ private static TypeSafeMatcher<MotionEvent> containsPoints(final Point... points) {
+ return new TypeSafeMatcher<MotionEvent>() {
+ @Override
+ protected boolean matchesSafely(MotionEvent event) {
+ MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
+ for (int i = 0; i < points.length; i++) {
+ boolean havePoint = false;
+ for (int j = 0; j < points.length; j++) {
+ event.getPointerCoords(j, coords);
+ if ((points[i].x == coords.x) && (points[i].y == coords.y)) {
+ havePoint = true;
+ }
+ }
+ if (!havePoint) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Contains points " + points);
+ }
+ };
+ }
+
+ private static TypeSafeMatcher<MotionEvent> hasDownTime(final long downTime) {
+ return new TypeSafeMatcher<MotionEvent>() {
+ @Override
+ protected boolean matchesSafely(MotionEvent event) {
+ return event.getDownTime() == downTime;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Down time = " + downTime);
+ }
+ };
+ }
+
+ private static TypeSafeMatcher<MotionEvent> hasEventTime(final long eventTime) {
+ return new TypeSafeMatcher<MotionEvent>() {
+ @Override
+ protected boolean matchesSafely(MotionEvent event) {
+ return event.getEventTime() == eventTime;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Event time = " + eventTime);
+ }
+ };
+ }
+
+ private static TypeSafeMatcher<MotionEvent> hasTimeFromDown(final long timeFromDown) {
+ return new TypeSafeMatcher<MotionEvent>() {
+ @Override
+ protected boolean matchesSafely(MotionEvent event) {
+ return (event.getEventTime() - event.getDownTime()) == timeFromDown;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Time from down to event times = " + timeFromDown);
+ }
+ };
+ }
+
+ private static TypeSafeMatcher<MotionEvent> hasStandardInitialization() {
+ return new TypeSafeMatcher<MotionEvent>() {
+ @Override
+ protected boolean matchesSafely(MotionEvent event) {
+ return (0 == event.getActionIndex()) && (0 == event.getDeviceId())
+ && (0 == event.getEdgeFlags()) && (0 == event.getFlags())
+ && (0 == event.getMetaState()) && (0F == event.getOrientation())
+ && (0F == event.getTouchMajor()) && (0F == event.getTouchMinor())
+ && (1F == event.getXPrecision()) && (1F == event.getYPrecision())
+ && (1 == event.getPointerCount()) && (1F == event.getPressure())
+ && (InputDevice.SOURCE_TOUCHSCREEN == event.getSource());
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Has standard values for all parameters");
+ }
+ };
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 9c241d7..c74cda6 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -254,11 +254,11 @@
// Unlock the user and verify that db has been updated
ams2.onUserUnlocked(newIntentForUser(UserHandle.USER_SYSTEM));
- accountsNumber = readNumberOfAccountsFromDbFile(originalContext, ceDatabaseName);
- assertEquals("CE database should now have 1 account", 2, accountsNumber);
accounts = ams2.getAccounts(UserHandle.USER_SYSTEM, mContext.getOpPackageName());
assertEquals(1, accounts.length);
assertEquals("Only a2 should be returned", a2, accounts[0]);
+ accountsNumber = readNumberOfAccountsFromDbFile(originalContext, ceDatabaseName);
+ assertEquals("CE database should now have 1 account", 1, accountsNumber);
}
@SmallTest
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 3ad40758..5b6d31b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -49,6 +49,7 @@
import com.android.internal.R;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.pm.UserRestrictionsUtils;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -1190,6 +1191,22 @@
assertTrue(dpm.setDeviceOwner(admin1, "owner-name",
UserHandle.USER_SYSTEM));
+ // Check that the user restrictions that are enabled by default are set. Then unset them.
+ String[] defaultRestrictions = UserRestrictionsUtils
+ .getDefaultEnabledForDeviceOwner().toArray(new String[0]);
+ DpmTestUtils.assertRestrictions(
+ DpmTestUtils.newRestrictions(defaultRestrictions),
+ dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
+ );
+ DpmTestUtils.assertRestrictions(
+ DpmTestUtils.newRestrictions(defaultRestrictions),
+ dpm.getUserRestrictions(admin1)
+ );
+
+ for (String restriction : defaultRestrictions) {
+ dpm.clearUserRestriction(admin1, restriction);
+ }
+
DpmTestUtils.assertRestrictions(
DpmTestUtils.newRestrictions(),
dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
@@ -1993,7 +2010,7 @@
// UnfinishedVerificationException.
}
- public void testIsProvisioningAllowed_DeviceAdminFeatureOff() throws Exception {
+ public void setup_DeviceAdminFeatureOff() throws Exception {
when(mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN))
.thenReturn(false);
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
@@ -2005,7 +2022,10 @@
setUserSetupCompleteForUser(false, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ }
+ public void testIsProvisioningAllowed_DeviceAdminFeatureOff() throws Exception {
+ setup_DeviceAdminFeatureOff();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, false);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
@@ -2013,7 +2033,21 @@
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, false);
}
- public void testIsProvisioningAllowed_ManagedProfileFeatureOff() throws Exception {
+ public void testCheckProvisioningPreCondition_DeviceAdminFeatureOff() throws Exception {
+ setup_DeviceAdminFeatureOff();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED);
+ }
+
+ public void setup_ManagedProfileFeatureOff() throws Exception {
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(false);
initializeDpms();
@@ -2023,7 +2057,10 @@
setUserSetupCompleteForUser(false, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ }
+ public void testIsProvisioningAllowed_ManagedProfileFeatureOff() throws Exception {
+ setup_ManagedProfileFeatureOff();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
@@ -2039,7 +2076,33 @@
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, false);
}
- public void testIsProvisioningAllowed_nonSplitUser_firstBoot_primaryUser() throws Exception {
+ public void testCheckProvisioningPreCondition_ManagedProfileFeatureOff() throws Exception {
+ setup_ManagedProfileFeatureOff();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED);
+
+ // Test again when split user is on
+ when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED);
+ }
+
+ public void setup_nonSplitUser_firstBoot_primaryUser() throws Exception {
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(true);
when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(false);
@@ -2048,7 +2111,10 @@
setUserSetupCompleteForUser(false, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ }
+ public void testIsProvisioningAllowed_nonSplitUser_firstBoot_primaryUser() throws Exception {
+ setup_nonSplitUser_firstBoot_primaryUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
@@ -2057,8 +2123,22 @@
false /* because of non-split user */);
}
- public void testIsProvisioningAllowed_nonSplitUser_afterDeviceSetup_primaryUser()
+ public void testCheckProvisioningPreCondition_nonSplitUser_firstBoot_primaryUser()
throws Exception {
+ setup_nonSplitUser_firstBoot_primaryUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT);
+ }
+
+ public void setup_nonSplitUser_afterDeviceSetup_primaryUser() throws Exception {
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(true);
when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(false);
@@ -2067,7 +2147,11 @@
setUserSetupCompleteForUser(true, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ }
+ public void testIsProvisioningAllowed_nonSplitUser_afterDeviceSetup_primaryUser()
+ throws Exception {
+ setup_nonSplitUser_afterDeviceSetup_primaryUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
false/* because of completed device setup */);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
@@ -2077,7 +2161,22 @@
false/* because of non-split user */);
}
- public void testIsProvisioningAllowed_splitUser_firstBoot_systemUser() throws Exception {
+ public void testCheckProvisioningPreCondition_nonSplitUser_afterDeviceSetup_primaryUser()
+ throws Exception {
+ setup_nonSplitUser_afterDeviceSetup_primaryUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_USER_SETUP_COMPLETED);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT);
+ }
+
+ public void setup_splitUser_firstBoot_systemUser() throws Exception {
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(true);
when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
@@ -2086,7 +2185,10 @@
setUserSetupCompleteForUser(false, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ }
+ public void testIsProvisioningAllowed_splitUser_firstBoot_systemUser() throws Exception {
+ setup_splitUser_firstBoot_systemUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
false /* because canAddMoreManagedProfiles returns false */);
@@ -2094,10 +2196,24 @@
true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
false/* because calling uid is system user */);
-
}
- public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_systemUser() throws Exception {
+ public void testCheckProvisioningPreCondition_splitUser_firstBoot_systemUser()
+ throws Exception {
+ setup_splitUser_firstBoot_systemUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_SYSTEM_USER);
+ }
+
+ public void setup_splitUser_afterDeviceSetup_systemUser() throws Exception {
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(true);
when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
@@ -2106,7 +2222,10 @@
setUserSetupCompleteForUser(true, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ }
+ public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_systemUser() throws Exception {
+ setup_splitUser_afterDeviceSetup_systemUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
true/* it's undefined behavior. Can be changed into false in the future */);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
@@ -2117,7 +2236,22 @@
false/* because calling uid is system user */);
}
- public void testIsProvisioningAllowed_splitUser_firstBoot_primaryUser() throws Exception {
+ public void testCheckProvisioningPreCondition_splitUser_afterDeviceSetup_systemUser()
+ throws Exception {
+ setup_splitUser_afterDeviceSetup_systemUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_SYSTEM_USER);
+ }
+
+ public void setup_splitUser_firstBoot_primaryUser() throws Exception {
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(true);
when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
@@ -2126,17 +2260,33 @@
setUserSetupCompleteForUser(false, DpmMockContext.CALLER_USER_HANDLE);
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ }
+ public void testIsProvisioningAllowed_splitUser_firstBoot_primaryUser() throws Exception {
+ setup_splitUser_firstBoot_primaryUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
true);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, true);
-
}
- public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_primaryUser()
+ public void testCheckProvisioningPreCondition_splitUser_firstBoot_primaryUser()
throws Exception {
+ setup_splitUser_firstBoot_primaryUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_OK);
+ }
+
+ public void setup_splitUser_afterDeviceSetup_primaryUser() throws Exception {
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(true);
when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
@@ -2145,7 +2295,11 @@
setUserSetupCompleteForUser(true, DpmMockContext.CALLER_USER_HANDLE);
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ }
+ public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_primaryUser()
+ throws Exception {
+ setup_splitUser_afterDeviceSetup_primaryUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
true/* it's undefined behavior. Can be changed into false in the future */);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
@@ -2155,8 +2309,22 @@
false/* because user setup completed */);
}
- public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_systemUser()
+ public void testCheckProvisioningPreCondition_splitUser_afterDeviceSetup_primaryUser()
throws Exception {
+ setup_splitUser_afterDeviceSetup_primaryUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(
+ DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE,
+ DevicePolicyManager.CODE_OK);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER,
+ DevicePolicyManager.CODE_USER_SETUP_COMPLETED);
+ }
+
+ public void setup_provisionManagedProfileWithDeviceOwner_systemUser() throws Exception {
setDeviceOwner();
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
@@ -2167,13 +2335,24 @@
setUserSetupCompleteForUser(true, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ }
+ public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_systemUser()
+ throws Exception {
+ setup_provisionManagedProfileWithDeviceOwner_systemUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
false /* can't provision managed profile on system user */);
}
- public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_primaryUser()
+ public void testCheckProvisioningPreCondition_provisionManagedProfileWithDeviceOwner_systemUser()
throws Exception {
+ setup_provisionManagedProfileWithDeviceOwner_systemUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER);
+ }
+
+ private void setup_provisionManagedProfileWithDeviceOwner_primaryUser() throws Exception {
setDeviceOwner();
when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
@@ -2184,30 +2363,64 @@
setUserSetupCompleteForUser(false, DpmMockContext.CALLER_USER_HANDLE);
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ }
+ public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_primaryUser()
+ throws Exception {
+ setup_provisionManagedProfileWithDeviceOwner_primaryUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
}
+ public void testCheckProvisioningPreCondition_provisionManagedProfileWithDeviceOwner_primaryUser()
+ throws Exception {
+ setup_provisionManagedProfileWithDeviceOwner_primaryUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_OK);
+ }
+
+ private void setup_provisionManagedProfileCantRemoveUser_primaryUser() throws Exception {
+ setDeviceOwner();
+
+ when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
+ .thenReturn(true);
+ when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
+ when(mContext.userManager.hasUserRestriction(
+ UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
+ UserHandle.of(DpmMockContext.CALLER_USER_HANDLE)))
+ .thenReturn(true);
+ when(mContext.userManager.canAddMoreManagedProfiles(DpmMockContext.CALLER_USER_HANDLE,
+ false /* we can't remove a managed profile */)).thenReturn(false);
+ when(mContext.userManager.canAddMoreManagedProfiles(DpmMockContext.CALLER_USER_HANDLE,
+ true)).thenReturn(true);
+ setUserSetupCompleteForUser(false, DpmMockContext.CALLER_USER_HANDLE);
+
+ mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ }
+
public void testIsProvisioningAllowed_provisionManagedProfileCantRemoveUser_primaryUser()
throws Exception {
- setDeviceOwner();
-
- when(mContext.ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
- .thenReturn(true);
- when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
- when(mContext.userManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER))
- .thenReturn(true);
- when(mContext.userManager.canAddMoreManagedProfiles(DpmMockContext.CALLER_USER_HANDLE,
- false /* we can't remove a managed profile*/)).thenReturn(false);
- when(mContext.userManager.canAddMoreManagedProfiles(DpmMockContext.CALLER_USER_HANDLE,
- true)).thenReturn(true);
- setUserSetupCompleteForUser(false, DpmMockContext.CALLER_USER_HANDLE);
-
- mContext.binder.callingUid = DpmMockContext.CALLER_UID;
-
+ setup_provisionManagedProfileCantRemoveUser_primaryUser();
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
}
+ public void testCheckProvisioningPreCondition_provisionManagedProfileCantRemoveUser_primaryUser()
+ throws Exception {
+ setup_provisionManagedProfileCantRemoveUser_primaryUser();
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
+ }
+
+ public void testCheckProvisioningPreCondition_permission() {
+ // GIVEN the permission MANAGE_PROFILE_AND_DEVICE_OWNERS is not granted
+ try {
+ dpm.checkProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE);
+ fail("Didn't throw SecurityException");
+ } catch (SecurityException expected) {
+ }
+ }
+
public void testForceUpdateUserSetupComplete_permission() {
// GIVEN the permission MANAGE_PROFILE_AND_DEVICE_OWNERS is not granted
try {
@@ -2568,6 +2781,11 @@
dpm.isProvisioningAllowed(action));
}
+ private void assertCheckProvisioningPreCondition(String action, int provisioningCondition) {
+ assertEquals("checkProvisioningPreCondition(" + action + ") returning unexpected result",
+ provisioningCondition, dpm.checkProvisioningPreCondition(action));
+ }
+
/**
* Setup a managed profile with the specified admin and its uid.
* @param admin ComponentName that's visible to the test code, which doesn't have to exist.
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
index 58db192..3806da6 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
@@ -82,6 +82,21 @@
return Mockito.argThat(m);
}
+ public static Intent checkIntent(final Intent intent) {
+ final Matcher<Intent> m = new BaseMatcher<Intent>() {
+ @Override
+ public boolean matches(Object item) {
+ if (item == null) return false;
+ return intent.filterEquals((Intent) item);
+ }
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(intent.toString());
+ }
+ };
+ return Mockito.argThat(m);
+ }
+
public static Bundle checkUserRestrictions(String... keys) {
final Bundle expected = DpmTestUtils.newRestrictions(Preconditions.checkNotNull(keys));
final Matcher<Bundle> m = new BaseMatcher<Bundle>() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 9f01773..99af9e8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -376,6 +376,7 @@
@Override
boolean injectIsActivityEnabledAndExported(ComponentName activity, @UserIdInt int userId) {
+ assertNotNull(activity);
return mEnabledActivityChecker.test(activity, userId);
}
@@ -416,6 +417,11 @@
// During tests, WTF is fatal.
fail(message + " exception: " + th + "\n" + Log.getStackTraceString(th));
}
+
+ @Override
+ void verifyError() {
+ fail("Verify error");
+ }
}
/** ShortcutManager with injection override methods. */
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java
index f773c15..5c552a2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java
@@ -27,12 +27,16 @@
import android.util.ArraySet;
import com.android.internal.os.RoSystemProperties;
+import com.android.internal.util.ArrayUtils;
import com.android.server.SystemConfig;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.List;
+
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static junit.framework.Assert.assertTrue;
@@ -53,27 +57,34 @@
}
/**
- * <p>This test ensures that all signature|privileged permissions are granted to core apps like
- * systemui/settings. If CONTROL_PRIVAPP_PERMISSIONS is set, the test also verifies that
+ * <p>This test ensures that all signature|privileged permissions are granted to priv-apps.
+ * If CONTROL_PRIVAPP_PERMISSIONS_ENFORCE is set, the test also verifies that
* granted permissions are whitelisted in {@link SystemConfig}
*/
@Test
@SmallTest
@Presubmit
public void testPrivAppPermissions() throws PackageManager.NameNotFoundException {
- String[] testPackages = {"com.android.settings", "com.android.shell",
- "com.android.systemui"};
- for (String testPackage : testPackages) {
- testPackagePrivAppPermission(testPackage);
+ List<PackageInfo> installedPackages = mPackageManager
+ .getInstalledPackages(PackageManager.MATCH_UNINSTALLED_PACKAGES | GET_PERMISSIONS);
+ for (PackageInfo packageInfo : installedPackages) {
+ if (!packageInfo.applicationInfo.isPrivilegedApp()
+ || PackageManagerService.PLATFORM_PACKAGE_NAME.equals(packageInfo.packageName)) {
+ continue;
+ }
+ testPackagePrivAppPermission(packageInfo);
}
+
}
- private void testPackagePrivAppPermission(String testPackage)
+ private void testPackagePrivAppPermission(PackageInfo packageInfo)
throws PackageManager.NameNotFoundException {
- PackageInfo packageInfo = mPackageManager.getPackageInfo(testPackage,
- PackageManager.GET_PERMISSIONS);
+ String packageName = packageInfo.packageName;
ArraySet<String> privAppPermissions = SystemConfig.getInstance()
- .getPrivAppPermissions(testPackage);
+ .getPrivAppPermissions(packageName);
+ if (ArrayUtils.isEmpty(packageInfo.requestedPermissions)) {
+ return;
+ }
for (int i = 0; i < packageInfo.requestedPermissions.length; i++) {
String pName = packageInfo.requestedPermissions[i];
int protectionLevel;
@@ -89,15 +100,17 @@
if ((protectionLevel & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) {
boolean granted = (packageInfo.requestedPermissionsFlags[i]
& PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
- assertTrue("Permission " + pName + " should be granted to " + testPackage, granted);
// if privapp permissions are enforced, platform permissions must be whitelisted
// in SystemConfig
if (platformPermission && RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
assertTrue("Permission " + pName
- + " should be declared in the xml file for package "
- + testPackage,
+ + " should be declared in "
+ + "/etc/permissions/privapp-permissions-platform.xml "
+ + "or privapp-permissions-<device>.xml file for package "
+ + packageName,
privAppPermissions.contains(pName));
}
+ assertTrue("Permission " + pName + " should be granted to " + packageName, granted);
}
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
new file mode 100644
index 0000000..84bb4e8
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.pm;
+
+import android.content.pm.PackageParser;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import libcore.io.IoUtils;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class PackageParserTest {
+ private File mTmpDir;
+ private static final File FRAMEWORK = new File("/system/framework/framework-res.apk");
+
+ @Before
+ public void setUp() {
+ // Create a new temporary directory for each of our tests.
+ mTmpDir = IoUtils.createTemporaryDirectory("PackageParserTest");
+ }
+
+ @Test
+ public void testParse_noCache() throws Exception {
+ PackageParser pp = new CachePackageNameParser();
+ PackageParser.Package pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
+ false /* useCaches */);
+ assertNotNull(pkg);
+
+ pp.setCacheDir(mTmpDir);
+ pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
+ false /* useCaches */);
+ assertNotNull(pkg);
+
+ // Make sure that we always write out a cache entry for future reference,
+ // whether or not we're asked to use caches.
+ assertEquals(1, mTmpDir.list().length);
+ }
+
+ @Test
+ public void testParse_withCache() throws Exception {
+ PackageParser pp = new CachePackageNameParser();
+
+ pp.setCacheDir(mTmpDir);
+ // The first parse will write this package to the cache.
+ pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */);
+
+ // Now attempt to parse the package again, should return the
+ // cached result.
+ PackageParser.Package pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
+ true /* useCaches */);
+ assertEquals("cache_android", pkg.packageName);
+
+ // Try again, with useCaches == false, shouldn't return the parsed
+ // result.
+ pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */);
+ assertEquals("android", pkg.packageName);
+
+ // We haven't set a cache directory here : the parse should still succeed,
+ // just not using the cached results.
+ pp = new CachePackageNameParser();
+ pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */);
+ assertEquals("android", pkg.packageName);
+
+ pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */);
+ assertEquals("android", pkg.packageName);
+ }
+
+ /**
+ * A trivial subclass of package parser that only caches the package name, and throws away
+ * all other information.
+ */
+ public static class CachePackageNameParser extends PackageParser {
+ @Override
+ public byte[] toCacheEntry(Package pkg) {
+ return ("cache_" + pkg.packageName).getBytes(StandardCharsets.UTF_8);
+ }
+
+ @Override
+ public Package fromCacheEntry(byte[] cacheEntry) {
+ return new Package(new String(cacheEntry, StandardCharsets.UTF_8));
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 74c1ca5..97bcaf0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -1292,7 +1292,43 @@
/* activity =*/ null, /* flags */ 0), getCallingUser());
});
- // TODO More tests: pinned but dynamic.
+ // Make sure floating shortcuts don't match with an activity.
+ // At this point, s1 is dynamic and pinned, so it still has a target activity.
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ assertWith(mLauncherApps.getShortcuts(buildQuery(
+ /* time =*/ 0,
+ CALLING_PACKAGE_2,
+ /* activity =*/ new ComponentName(CALLING_PACKAGE_2,
+ ShortcutActivity2.class.getName()),
+ ShortcutQuery.FLAG_GET_PINNED),
+ getCallingUser()))
+ .haveIds("s3")
+ .areAllPinned()
+ .areAllDynamic()
+ .areAllWithActivity(new ComponentName(CALLING_PACKAGE_2,
+ ShortcutActivity2.class.getName()));
+ });
+
+ // Now remove as a dynamic, making it floating.
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ mManager.removeDynamicShortcuts(list("s3"));
+ assertWith(mManager.getPinnedShortcuts())
+ .selectFloating()
+ .areAllWithNoActivity();
+ });
+
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ // This shouldn't match now.
+ assertWith(mLauncherApps.getShortcuts(buildQuery(
+ /* time =*/ 0,
+ CALLING_PACKAGE_2,
+ /* activity =*/ new ComponentName(CALLING_PACKAGE_2,
+ ShortcutActivity2.class.getName()),
+ ShortcutQuery.FLAG_GET_PINNED),
+ getCallingUser()))
+ .isEmpty();
+ });
+
}
public void testGetShortcuts_shortcutKinds() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index d25923c..7486858 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -1052,7 +1052,7 @@
assertEquals(CALLING_PACKAGE_1, si.getPackage());
assertEquals("id", si.getId());
- assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
+ assertNull(si.getActivity()); // It's now floating, so no target activity.
assertEquals(null, si.getIcon());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
@@ -1116,7 +1116,7 @@
assertEquals(CALLING_PACKAGE_1, si.getPackage());
assertEquals("id", si.getId());
- assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
+ assertNull(si.getActivity()); // It's now floating, so no target activity.
assertEquals(null, si.getIcon());
assertEquals(10, si.getTitleResId());
assertEquals("r10", si.getTitleResName());
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 40d8ac0..9b2c94e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -241,15 +241,14 @@
}
}
- // Make sure createProfile would fail if we have DISALLOW_ADD_USER.
+ // Make sure createUser would fail if we have DISALLOW_ADD_USER.
@MediumTest
- public void testCreateProfileForUser_disallowAddUser() throws Exception {
+ public void testCreateUser_disallowAddUser() throws Exception {
final int primaryUserId = mUserManager.getPrimaryUser().id;
final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, primaryUserHandle);
try {
- UserInfo userInfo = createProfileForUser("Managed",
- UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+ UserInfo userInfo = createUser("SecondaryUser", /*flags=*/ 0);
assertNull(userInfo);
} finally {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false,
@@ -257,17 +256,51 @@
}
}
- // Make sure createProfileEvenWhenDisallowedForUser bypass DISALLOW_ADD_USER.
+ // Make sure createProfile would fail if we have DISALLOW_ADD_MANAGED_PROFILE.
+ @MediumTest
+ public void testCreateProfileForUser_disallowAddManagedProfile() throws Exception {
+ final int primaryUserId = mUserManager.getPrimaryUser().id;
+ final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, true,
+ primaryUserHandle);
+ try {
+ UserInfo userInfo = createProfileForUser("Managed",
+ UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+ assertNull(userInfo);
+ } finally {
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, false,
+ primaryUserHandle);
+ }
+ }
+
+ // Make sure createProfileEvenWhenDisallowedForUser bypass DISALLOW_ADD_MANAGED_PROFILE.
@MediumTest
public void testCreateProfileForUserEvenWhenDisallowed() throws Exception {
final int primaryUserId = mUserManager.getPrimaryUser().id;
final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
- mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, primaryUserHandle);
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, true,
+ primaryUserHandle);
try {
UserInfo userInfo = createProfileEvenWhenDisallowedForUser("Managed",
UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
assertNotNull(userInfo);
} finally {
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, false,
+ primaryUserHandle);
+ }
+ }
+
+ // createProfile succeeds even if DISALLOW_ADD_USER is set
+ @MediumTest
+ public void testCreateProfileForUser_disallowAddUser() throws Exception {
+ final int primaryUserId = mUserManager.getPrimaryUser().id;
+ final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, primaryUserHandle);
+ try {
+ UserInfo userInfo = createProfileForUser("Managed",
+ UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+ assertNotNull(userInfo);
+ } finally {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false,
primaryUserHandle);
}
diff --git a/services/tests/servicestests/src/com/android/server/twilight/TwilightServiceTest.java b/services/tests/servicestests/src/com/android/server/twilight/TwilightServiceTest.java
new file mode 100644
index 0000000..751e4b5
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/twilight/TwilightServiceTest.java
@@ -0,0 +1,71 @@
+package com.android.server.twilight;
+
+/*
+ * 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.
+ */
+
+import android.app.AlarmManager;
+import android.content.Context;
+import android.location.Location;
+import android.test.AndroidTestCase;
+
+public class TwilightServiceTest extends AndroidTestCase {
+
+ private TwilightService mTwilightService;
+ private Location mInitialLocation;
+
+ @Override
+ protected void setUp() throws Exception {
+ final Context context = getContext();
+ mTwilightService = new TwilightService(context);
+ mTwilightService.mAlarmManager =
+ (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+
+ mInitialLocation = createMockLocation(10.0, 10.0);
+ mTwilightService.onLocationChanged(mInitialLocation);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mTwilightService = null;
+ mInitialLocation = null;
+ }
+
+ public void testValidLocation_updatedLocation() {
+ final TwilightState priorState = mTwilightService.mLastTwilightState;
+ final Location validLocation = createMockLocation(35.0, 35.0);
+ mTwilightService.onLocationChanged(validLocation);
+ assertEquals(mTwilightService.mLastLocation, validLocation);
+ assertNotSame(priorState, mTwilightService.mLastTwilightState);
+ }
+
+ public void testInvalidLocation_ignoreLocationUpdate() {
+ final TwilightState priorState = mTwilightService.mLastTwilightState;
+ final Location invalidLocation = createMockLocation(0.0, 0.0);
+ mTwilightService.onLocationChanged(invalidLocation);
+ assertEquals(mTwilightService.mLastLocation, mInitialLocation);
+ assertEquals(priorState, mTwilightService.mLastTwilightState);
+ }
+
+ private Location createMockLocation(double latitude, double longitude) {
+ // There's no empty constructor, so we initialize with a string and quickly reset it.
+ final Location location = new Location("");
+ location.reset();
+ location.setLatitude(latitude);
+ location.setLongitude(longitude);
+ return location;
+ }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index 207939f..06837d3 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -16,17 +16,12 @@
package com.android.server.wm;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import android.content.Context;
import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.IWindow;
-import android.view.WindowManager;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -49,7 +44,7 @@
@Test
public void testAddWindow_Order() throws Exception {
- final TestAppWindowToken token = new TestAppWindowToken();
+ final TestAppWindowToken token = new TestAppWindowToken(sDisplayContent);
assertEquals(0, token.getWindowsCount());
@@ -59,11 +54,6 @@
final WindowState baseWin = createWindow(null, TYPE_BASE_APPLICATION, token, "baseWin");
final WindowState win4 = createWindow(null, TYPE_APPLICATION, token, "win4");
- token.addWindow(win1);
- token.addWindow(startingWin);
- token.addWindow(baseWin);
- token.addWindow(win4);
-
// Should not contain the windows that were added above.
assertEquals(4, token.getWindowsCount());
assertTrue(token.hasWindow(win1));
@@ -80,43 +70,17 @@
@Test
public void testFindMainWindow() throws Exception {
- final TestAppWindowToken token = new TestAppWindowToken();
+ final TestAppWindowToken token = new TestAppWindowToken(sDisplayContent);
assertNull(token.findMainWindow());
final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, token, "window1");
final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token, "window11");
final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token, "window12");
- token.addWindow(window1);
assertEquals(window1, token.findMainWindow());
window1.mAnimatingExit = true;
assertEquals(window1, token.findMainWindow());
final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, token, "window2");
- token.addWindow(window2);
assertEquals(window2, token.findMainWindow());
}
-
- /* Used so we can gain access to some protected members of the {@link AppWindowToken} class */
- private class TestAppWindowToken extends AppWindowToken {
-
- TestAppWindowToken() {
- super(sWm, null, false, sWm.getDefaultDisplayContentLocked());
- }
-
- int getWindowsCount() {
- return mChildren.size();
- }
-
- boolean hasWindow(WindowState w) {
- return mChildren.contains(w);
- }
-
- WindowState getFirstChild() {
- return mChildren.getFirst();
- }
-
- WindowState getLastChild() {
- return mChildren.getLast();
- }
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 0801a88..01808cb 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -25,14 +25,8 @@
import java.util.ArrayList;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static org.junit.Assert.assertEquals;
/**
@@ -48,21 +42,8 @@
@Test
public void testForAllWindows() throws Exception {
- final DisplayContent dc = new DisplayContent(mDisplay, sWm, null, null);
- final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, dc, "wallpaper");
- final WindowState imeWindow = createWindow(null, TYPE_INPUT_METHOD, dc, "ime");
- final WindowState imeDialogWindow = createWindow(null, TYPE_INPUT_METHOD_DIALOG, dc,
- "ime dialog");
- final WindowState statusBarWindow = createWindow(null, TYPE_STATUS_BAR, dc, "status bar");
- final WindowState navBarWindow = createWindow(null, TYPE_NAVIGATION_BAR,
- statusBarWindow.mToken, "nav bar");
- final WindowState appWindow = createWindow(null, TYPE_BASE_APPLICATION, dc, "app");
- final WindowState negChildAppWindow = createWindow(appWindow, TYPE_APPLICATION_MEDIA,
- appWindow.mToken, "negative app child");
- final WindowState posChildAppWindow = createWindow(appWindow,
- TYPE_APPLICATION_ATTACHED_DIALOG, appWindow.mToken, "positive app child");
- final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION, dc,
- "exiting app");
+ final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
+ sDisplayContent, "exiting app");
final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
exitingAppToken.mIsExiting = true;
exitingAppToken.mTask.mStack.mExitingAppTokens.add(exitingAppToken);
@@ -70,30 +51,156 @@
final ArrayList<WindowState> windows = new ArrayList();
// Test forward traversal.
- dc.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
+ sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
- assertEquals(wallpaperWindow, windows.get(0));
+ assertEquals(sWallpaperWindow, windows.get(0));
assertEquals(exitingAppWindow, windows.get(1));
- assertEquals(negChildAppWindow, windows.get(2));
- assertEquals(appWindow, windows.get(3));
- assertEquals(posChildAppWindow, windows.get(4));
- assertEquals(statusBarWindow, windows.get(5));
- assertEquals(navBarWindow, windows.get(6));
- assertEquals(imeWindow, windows.get(7));
- assertEquals(imeDialogWindow, windows.get(8));
+ assertEquals(sChildAppWindowBelow, windows.get(2));
+ assertEquals(sAppWindow, windows.get(3));
+ assertEquals(sChildAppWindowAbove, windows.get(4));
+ assertEquals(sDockedDividerWindow, windows.get(5));
+ assertEquals(sStatusBarWindow, windows.get(6));
+ assertEquals(sNavBarWindow, windows.get(7));
+ assertEquals(sImeWindow, windows.get(8));
+ assertEquals(sImeDialogWindow, windows.get(9));
// Test backward traversal.
windows.clear();
- dc.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);
+ sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);
- assertEquals(wallpaperWindow, windows.get(8));
- assertEquals(exitingAppWindow, windows.get(7));
- assertEquals(negChildAppWindow, windows.get(6));
- assertEquals(appWindow, windows.get(5));
- assertEquals(posChildAppWindow, windows.get(4));
- assertEquals(statusBarWindow, windows.get(3));
- assertEquals(navBarWindow, windows.get(2));
- assertEquals(imeWindow, windows.get(1));
- assertEquals(imeDialogWindow, windows.get(0));
+ assertEquals(sWallpaperWindow, windows.get(9));
+ assertEquals(exitingAppWindow, windows.get(8));
+ assertEquals(sChildAppWindowBelow, windows.get(7));
+ assertEquals(sAppWindow, windows.get(6));
+ assertEquals(sChildAppWindowAbove, windows.get(5));
+ assertEquals(sDockedDividerWindow, windows.get(4));
+ assertEquals(sStatusBarWindow, windows.get(3));
+ assertEquals(sNavBarWindow, windows.get(2));
+ assertEquals(sImeWindow, windows.get(1));
+ assertEquals(sImeDialogWindow, windows.get(0));
+
+ exitingAppWindow.removeImmediately();
+ }
+
+ @Test
+ public void testForAllWindows_WithAppImeTarget() throws Exception {
+ final WindowState imeAppTarget =
+ createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "imeAppTarget");
+
+ sWm.mInputMethodTarget = imeAppTarget;
+
+ final ArrayList<WindowState> windows = new ArrayList();
+
+ // Test forward traversal.
+ sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
+
+ assertEquals(sWallpaperWindow, windows.get(0));
+ assertEquals(sChildAppWindowBelow, windows.get(1));
+ assertEquals(sAppWindow, windows.get(2));
+ assertEquals(sChildAppWindowAbove, windows.get(3));
+ assertEquals(imeAppTarget, windows.get(4));
+ assertEquals(sImeWindow, windows.get(5));
+ assertEquals(sImeDialogWindow, windows.get(6));
+ assertEquals(sDockedDividerWindow, windows.get(7));
+ assertEquals(sStatusBarWindow, windows.get(8));
+ assertEquals(sNavBarWindow, windows.get(9));
+
+ // Test backward traversal.
+ windows.clear();
+ sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);
+
+ assertEquals(sWallpaperWindow, windows.get(9));
+ assertEquals(sChildAppWindowBelow, windows.get(8));
+ assertEquals(sAppWindow, windows.get(7));
+ assertEquals(sChildAppWindowAbove, windows.get(6));
+ assertEquals(imeAppTarget, windows.get(5));
+ assertEquals(sImeWindow, windows.get(4));
+ assertEquals(sImeDialogWindow, windows.get(3));
+ assertEquals(sDockedDividerWindow, windows.get(2));
+ assertEquals(sStatusBarWindow, windows.get(1));
+ assertEquals(sNavBarWindow, windows.get(0));
+
+ // Clean-up
+ sWm.mInputMethodTarget = null;
+ imeAppTarget.removeImmediately();
+ }
+
+ @Test
+ public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
+
+ sWm.mInputMethodTarget = sStatusBarWindow;
+
+ final ArrayList<WindowState> windows = new ArrayList();
+
+ // Test forward traversal.
+ sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
+
+ assertEquals(sWallpaperWindow, windows.get(0));
+ assertEquals(sChildAppWindowBelow, windows.get(1));
+ assertEquals(sAppWindow, windows.get(2));
+ assertEquals(sChildAppWindowAbove, windows.get(3));
+ assertEquals(sDockedDividerWindow, windows.get(4));
+ assertEquals(sStatusBarWindow, windows.get(5));
+ assertEquals(sImeWindow, windows.get(6));
+ assertEquals(sImeDialogWindow, windows.get(7));
+ assertEquals(sNavBarWindow, windows.get(8));
+
+ // Test backward traversal.
+ windows.clear();
+ sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);
+
+ assertEquals(sWallpaperWindow, windows.get(8));
+ assertEquals(sChildAppWindowBelow, windows.get(7));
+ assertEquals(sAppWindow, windows.get(6));
+ assertEquals(sChildAppWindowAbove, windows.get(5));
+ assertEquals(sDockedDividerWindow, windows.get(4));
+ assertEquals(sStatusBarWindow, windows.get(3));
+ assertEquals(sImeWindow, windows.get(2));
+ assertEquals(sImeDialogWindow, windows.get(1));
+ assertEquals(sNavBarWindow, windows.get(0));
+
+ // Clean-up
+ sWm.mInputMethodTarget = null;
+ }
+
+ @Test
+ public void testForAllWindows_WithInBetweenWindowToken() throws Exception {
+ // This window is set-up to be z-ordered between some windows that go in the same token like
+ // the nav bar and status bar.
+ final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
+ sDisplayContent, "voiceInteractionWindow");
+
+ final ArrayList<WindowState> windows = new ArrayList();
+
+ // Test forward traversal.
+ sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
+
+ assertEquals(sWallpaperWindow, windows.get(0));
+ assertEquals(sChildAppWindowBelow, windows.get(1));
+ assertEquals(sAppWindow, windows.get(2));
+ assertEquals(sChildAppWindowAbove, windows.get(3));
+ assertEquals(sDockedDividerWindow, windows.get(4));
+ assertEquals(voiceInteractionWindow, windows.get(5));
+ assertEquals(sStatusBarWindow, windows.get(6));
+ assertEquals(sNavBarWindow, windows.get(7));
+ assertEquals(sImeWindow, windows.get(8));
+ assertEquals(sImeDialogWindow, windows.get(9));
+
+ // Test backward traversal.
+ windows.clear();
+ sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);
+
+ assertEquals(sWallpaperWindow, windows.get(9));
+ assertEquals(sChildAppWindowBelow, windows.get(8));
+ assertEquals(sAppWindow, windows.get(7));
+ assertEquals(sChildAppWindowAbove, windows.get(6));
+ assertEquals(sDockedDividerWindow, windows.get(5));
+ assertEquals(voiceInteractionWindow, windows.get(4));
+ assertEquals(sStatusBarWindow, windows.get(3));
+ assertEquals(sNavBarWindow, windows.get(2));
+ assertEquals(sImeWindow, windows.get(1));
+ assertEquals(sImeDialogWindow, windows.get(0));
+
+ voiceInteractionWindow.removeImmediately();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
new file mode 100644
index 0000000..1260a53
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.graphics.Rect;
+import android.os.Binder;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Display;
+
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static com.android.server.wm.TaskPositioner.MIN_ASPECT;
+import static com.android.server.wm.WindowManagerService.dipToPixel;
+import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
+import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for the {@link TaskPositioner} class.
+ *
+ * runtest frameworks-services -c com.android.server.wm.TaskPositionerTests
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TaskPositionerTests extends WindowTestsBase {
+
+ private final boolean DEBUGGING = false;
+ private final String TAG = "TaskPositionerTest";
+
+ private final static int MOUSE_DELTA_X = 5;
+ private final static int MOUSE_DELTA_Y = 5;
+
+ private int mMinVisibleWidth;
+ private int mMinVisibleHeight;
+ private TaskPositioner mPositioner;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ final Display display = sDisplayContent.getDisplay();
+ final DisplayMetrics dm = new DisplayMetrics();
+ display.getMetrics(dm);
+
+ // This should be the same calculation as the TaskPositioner uses.
+ mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, dm);
+ mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, dm);
+
+ mPositioner = new TaskPositioner(sWm);
+ mPositioner.register(display);
+ }
+
+ /**
+ * This tests that free resizing will allow to change the orientation as well
+ * as does some basic tests (e.g. dragging in Y only will keep X stable).
+ */
+ @Test
+ public void testBasicFreeWindowResizing() throws Exception {
+ final Rect r = new Rect(100, 220, 700, 520);
+ final int midY = (r.top + r.bottom) / 2;
+
+ // Start a drag resize starting upper left.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+ assertBoundsEquals(r, mPositioner.getWindowDragBounds());
+
+ // Drag to a good landscape size.
+ mPositioner.resizeDrag(0.0f, 0.0f);
+ assertBoundsEquals(new Rect(MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a good portrait size.
+ mPositioner.resizeDrag(400.0f, 0.0f);
+ assertBoundsEquals(new Rect(400 + MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a too small size for the width.
+ mPositioner.resizeDrag(2000.0f, r.top);
+ assertBoundsEquals(
+ new Rect(r.right - mMinVisibleWidth, r.top + MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a too small size for the height.
+ mPositioner.resizeDrag(r.left, 2000.0f);
+ assertBoundsEquals(
+ new Rect(r.left + MOUSE_DELTA_X, r.bottom - mMinVisibleHeight, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Start a drag resize left and see that only the left coord changes..
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);
+
+ // Drag to the left.
+ mPositioner.resizeDrag(0.0f, midY);
+ assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the right.
+ mPositioner.resizeDrag(200.0f, midY);
+ assertBoundsEquals(new Rect(200 + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the top
+ mPositioner.resizeDrag(r.left, 0.0f);
+ assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the bottom
+ mPositioner.resizeDrag(r.left, 1000.0f);
+ assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+ }
+
+ /**
+ * This tests that by dragging any edge, the fixed / opposite edge(s) remains anchored.
+ */
+ @Test
+ public void testFreeWindowResizingTestAllEdges() throws Exception {
+ final Rect r = new Rect(100, 220, 700, 520);
+ final int midX = (r.left + r.right) / 2;
+ final int midY = (r.top + r.bottom) / 2;
+
+ // Drag upper left.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+ mPositioner.resizeDrag(0.0f, 0.0f);
+ assertTrue(r.left != mPositioner.getWindowDragBounds().left);
+ assertEquals(r.right, mPositioner.getWindowDragBounds().right);
+ assertTrue(r.top != mPositioner.getWindowDragBounds().top);
+ assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
+
+ // Drag upper.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);
+ mPositioner.resizeDrag(0.0f, 0.0f);
+ assertEquals(r.left, mPositioner.getWindowDragBounds().left);
+ assertEquals(r.right, mPositioner.getWindowDragBounds().right);
+ assertTrue(r.top != mPositioner.getWindowDragBounds().top);
+ assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
+
+ // Drag upper right.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, r.right + MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+ mPositioner.resizeDrag(r.right + 100, 0.0f);
+ assertEquals(r.left, mPositioner.getWindowDragBounds().left);
+ assertTrue(r.right != mPositioner.getWindowDragBounds().right);
+ assertTrue(r.top != mPositioner.getWindowDragBounds().top);
+ assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
+
+ // Drag right.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, r.right + MOUSE_DELTA_X, midY, r);
+ mPositioner.resizeDrag(r.right + 100, 0.0f);
+ assertEquals(r.left, mPositioner.getWindowDragBounds().left);
+ assertTrue(r.right != mPositioner.getWindowDragBounds().right);
+ assertEquals(r.top, mPositioner.getWindowDragBounds().top);
+ assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
+
+ // Drag bottom right.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/,
+ r.right + MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y, r);
+ mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
+ assertEquals(r.left, mPositioner.getWindowDragBounds().left);
+ assertTrue(r.right != mPositioner.getWindowDragBounds().right);
+ assertEquals(r.top, mPositioner.getWindowDragBounds().top);
+ assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
+
+ // Drag bottom.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, midX, r.bottom + MOUSE_DELTA_Y, r);
+ mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
+ assertEquals(r.left, mPositioner.getWindowDragBounds().left);
+ assertEquals(r.right, mPositioner.getWindowDragBounds().right);
+ assertEquals(r.top, mPositioner.getWindowDragBounds().top);
+ assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
+
+ // Drag bottom left.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y, r);
+ mPositioner.resizeDrag(0.0f, r.bottom + 100);
+ assertTrue(r.left != mPositioner.getWindowDragBounds().left);
+ assertEquals(r.right, mPositioner.getWindowDragBounds().right);
+ assertEquals(r.top, mPositioner.getWindowDragBounds().top);
+ assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
+
+ // Drag left.
+ mPositioner.startDrag(true /*resizing*/,
+ false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midX, r);
+ mPositioner.resizeDrag(0.0f, r.bottom + 100);
+ assertTrue(r.left != mPositioner.getWindowDragBounds().left);
+ assertEquals(r.right, mPositioner.getWindowDragBounds().right);
+ assertEquals(r.top, mPositioner.getWindowDragBounds().top);
+ assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
+ }
+
+ /**
+ * This tests that a constrained landscape window will keep the aspect and do the
+ * right things upon resizing when dragged from the top left corner.
+ */
+ @Test
+ public void testLandscapePreservedWindowResizingDragTopLeft() throws Exception {
+ final Rect r = new Rect(100, 220, 700, 520);
+
+ mPositioner.startDrag(true /*resizing*/,
+ true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+ assertBoundsEquals(r, mPositioner.getWindowDragBounds());
+
+ // Drag to a good landscape size.
+ mPositioner.resizeDrag(0.0f, 0.0f);
+ assertBoundsEquals(new Rect(MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a good portrait size.
+ mPositioner.resizeDrag(400.0f, 0.0f);
+ int width = Math.round((float) (r.bottom - MOUSE_DELTA_Y) * MIN_ASPECT);
+ assertBoundsEquals(new Rect(r.right - width, MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a too small size for the width.
+ mPositioner.resizeDrag(2000.0f, r.top);
+ final int w = mMinVisibleWidth;
+ final int h = Math.round(w / MIN_ASPECT);
+ assertBoundsEquals(new Rect(r.right - w, r.bottom - h, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a too small size for the height.
+ mPositioner.resizeDrag(r.left, 2000.0f);
+ assertBoundsEquals(
+ new Rect(r.left + MOUSE_DELTA_X, r.bottom - mMinVisibleHeight, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+ }
+
+ /**
+ * This tests that a constrained landscape window will keep the aspect and do the
+ * right things upon resizing when dragged from the left corner.
+ */
+ @Test
+ public void testLandscapePreservedWindowResizingDragLeft() throws Exception {
+ final Rect r = new Rect(100, 220, 700, 520);
+ final int midY = (r.top + r.bottom) / 2;
+
+ mPositioner.startDrag(true /*resizing*/,
+ true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);
+
+ // Drag to the left.
+ mPositioner.resizeDrag(0.0f, midY);
+ assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the right.
+ mPositioner.resizeDrag(200.0f, midY);
+ assertBoundsEquals(new Rect(200 + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag all the way to the right and see the height also shrinking.
+ mPositioner.resizeDrag(2000.0f, midY);
+ final int w = mMinVisibleWidth;
+ final int h = Math.round((float)w / MIN_ASPECT);
+ assertBoundsEquals(new Rect(r.right - w, r.top, r.right, r.top + h),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the top.
+ mPositioner.resizeDrag(r.left, 0.0f);
+ assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the bottom.
+ mPositioner.resizeDrag(r.left, 1000.0f);
+ assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+ }
+
+ /**
+ * This tests that a constrained landscape window will keep the aspect and do the
+ * right things upon resizing when dragged from the top corner.
+ */
+ @Test
+ public void testLandscapePreservedWindowResizingDragTop() throws Exception {
+ final Rect r = new Rect(100, 220, 700, 520);
+ final int midX = (r.left + r.right) / 2;
+
+ mPositioner.startDrag(true /*resizing*/,
+ true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);
+
+ // Drag to the left (no change).
+ mPositioner.resizeDrag(0.0f, r.top);
+ assertBoundsEquals(new Rect(r.left, r.top + MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the right (no change).
+ mPositioner.resizeDrag(2000.0f, r.top);
+ assertBoundsEquals(new Rect(r.left , r.top + MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the top.
+ mPositioner.resizeDrag(300.0f, 0.0f);
+ int h = r.bottom - MOUSE_DELTA_Y;
+ int w = Math.max(r.right - r.left, Math.round(h * MIN_ASPECT));
+ assertBoundsEquals(new Rect(r.left, MOUSE_DELTA_Y, r.left + w, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the bottom.
+ mPositioner.resizeDrag(r.left, 1000.0f);
+ h = mMinVisibleHeight;
+ assertBoundsEquals(new Rect(r.left, r.bottom - h, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+ }
+
+ /**
+ * This tests that a constrained portrait window will keep the aspect and do the
+ * right things upon resizing when dragged from the top left corner.
+ */
+ @Test
+ public void testPortraitPreservedWindowResizingDragTopLeft() throws Exception {
+ final Rect r = new Rect(330, 100, 630, 600);
+
+ mPositioner.startDrag(true /*resizing*/,
+ true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+ assertBoundsEquals(r, mPositioner.getWindowDragBounds());
+
+ // Drag to a good landscape size.
+ mPositioner.resizeDrag(0.0f, 0.0f);
+ int height = Math.round((float) (r.right - MOUSE_DELTA_X) * MIN_ASPECT);
+ assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.bottom - height, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a good portrait size.
+ mPositioner.resizeDrag(500.0f, 0.0f);
+ assertBoundsEquals(new Rect(500 + MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to a too small size for the height and the the width shrinking.
+ mPositioner.resizeDrag(r.left + MOUSE_DELTA_X, 2000.0f);
+ final int w = Math.max(mMinVisibleWidth, Math.round(mMinVisibleHeight / MIN_ASPECT));
+ final int h = Math.max(mMinVisibleHeight, Math.round(w * MIN_ASPECT));
+ assertBoundsEquals(
+ new Rect(r.right - w, r.bottom - h, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+ }
+
+ /**
+ * This tests that a constrained portrait window will keep the aspect and do the
+ * right things upon resizing when dragged from the left corner.
+ */
+ @Test
+ public void testPortraitPreservedWindowResizingDragLeft() throws Exception {
+ final Rect r = new Rect(330, 100, 630, 600);
+ final int midY = (r.top + r.bottom) / 2;
+
+ mPositioner.startDrag(true /*resizing*/,
+ true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);
+
+ // Drag to the left.
+ mPositioner.resizeDrag(0.0f, midY);
+ int w = r.right - MOUSE_DELTA_X;
+ int h = Math.round(w * MIN_ASPECT);
+ assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.top, r.right, r.top + h),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the right.
+ mPositioner.resizeDrag(450.0f, midY);
+ assertBoundsEquals(new Rect(450 + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag all the way to the right.
+ mPositioner.resizeDrag(2000.0f, midY);
+ w = mMinVisibleWidth;
+ h = Math.max(Math.round((float)w * MIN_ASPECT), r.height());
+ assertBoundsEquals(new Rect(r.right - w, r.top, r.right, r.top + h),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the top.
+ mPositioner.resizeDrag(r.left, 0.0f);
+ assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the bottom.
+ mPositioner.resizeDrag(r.left, 1000.0f);
+ assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+ }
+
+ /**
+ * This tests that a constrained portrait window will keep the aspect and do the
+ * right things upon resizing when dragged from the top corner.
+ */
+ @Test
+ public void testPortraitPreservedWindowResizingDragTop() throws Exception {
+ final Rect r = new Rect(330, 100, 630, 600);
+ final int midX = (r.left + r.right) / 2;
+
+ mPositioner.startDrag(true /*resizing*/,
+ true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);
+
+ // Drag to the left (no change).
+ mPositioner.resizeDrag(0.0f, r.top);
+ assertBoundsEquals(new Rect(r.left, r.top + MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the right (no change).
+ mPositioner.resizeDrag(2000.0f, r.top);
+ assertBoundsEquals(new Rect(r.left , r.top + MOUSE_DELTA_Y, r.right, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the top.
+ mPositioner.resizeDrag(300.0f, 0.0f);
+ int h = r.bottom - MOUSE_DELTA_Y;
+ int w = Math.min(r.width(), Math.round(h / MIN_ASPECT));
+ assertBoundsEquals(new Rect(r.left, MOUSE_DELTA_Y, r.left + w, r.bottom),
+ mPositioner.getWindowDragBounds());
+
+ // Drag to the bottom.
+ mPositioner.resizeDrag(r.left, 1000.0f);
+ h = Math.max(mMinVisibleHeight, Math.round(mMinVisibleWidth * MIN_ASPECT));
+ w = Math.round(h / MIN_ASPECT);
+ assertBoundsEquals(new Rect(r.left, r.bottom - h, r.left + w, r.bottom),
+ mPositioner.getWindowDragBounds());
+ }
+
+ private void assertBoundsEquals(Rect expected, Rect actual) {
+ if (DEBUGGING) {
+ if (!expected.equals(actual)) {
+ Log.e(TAG, "rect(" + actual.toString() + ") != isRect(" + actual.toString()
+ + ") " + Log.getStackTraceString(new Throwable()));
+ }
+ }
+ assertEquals(expected.left, actual.left);
+ assertEquals(expected.right, actual.right);
+ assertEquals(expected.top, actual.top);
+ assertEquals(expected.bottom, actual.bottom);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 36bd13a..a820eb1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -45,7 +45,6 @@
* runtest frameworks-services -c com.android.server.wm.UnknownVisibilityControllerTest
*/
@SmallTest
-@Presubmit
@RunWith(AndroidJUnit4.class)
public class UnknownAppVisibilityControllerTest {
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index b10c273..ef6ee32 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -76,7 +76,7 @@
final Rect mInsetBounds = new Rect();
boolean mFullscreenForTest = true;
TaskWithBounds(Rect bounds) {
- super(0, mStubStack, 0, sWm, null, null, false);
+ super(0, mStubStack, 0, sWm, null, null, false, 0, false);
mBounds = bounds;
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowLayersControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowLayersControllerTests.java
index 5a035d6..c8650bf 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowLayersControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowLayersControllerTests.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -25,14 +24,9 @@
import android.support.test.runner.AndroidJUnit4;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
/**
* Tests for the {@link WindowLayersController} class.
@@ -45,43 +39,6 @@
@RunWith(AndroidJUnit4.class)
public class WindowLayersControllerTests extends WindowTestsBase {
- private static boolean sOneTimeSetupDone = false;
- private static WindowLayersController sLayersController;
- private static DisplayContent sDisplayContent;
- private static WindowState sImeWindow;
- private static WindowState sImeDialogWindow;
- private static WindowState sStatusBarWindow;
- private static WindowState sDockedDividerWindow;
- private static WindowState sNavBarWindow;
- private static WindowState sAppWindow;
- private static WindowState sChildAppWindow;
-
- @Before
- public void setUp() throws Exception {
- super.setUp();
-
- if (sOneTimeSetupDone) {
- return;
- }
- sOneTimeSetupDone = true;
- sLayersController = new WindowLayersController(sWm);
- sDisplayContent =
- new DisplayContent(mDisplay, sWm, sLayersController, new WallpaperController(sWm));
- final WindowState wallpaperWindow =
- createWindow(null, TYPE_WALLPAPER, sDisplayContent, "wallpaperWindow");
- sImeWindow = createWindow(null, TYPE_INPUT_METHOD, sDisplayContent, "sImeWindow");
- sImeDialogWindow =
- createWindow(null, TYPE_INPUT_METHOD_DIALOG, sDisplayContent, "sImeDialogWindow");
- sStatusBarWindow = createWindow(null, TYPE_STATUS_BAR, sDisplayContent, "sStatusBarWindow");
- sNavBarWindow =
- createWindow(null, TYPE_NAVIGATION_BAR, sStatusBarWindow.mToken, "sNavBarWindow");
- sDockedDividerWindow =
- createWindow(null, TYPE_DOCK_DIVIDER, sDisplayContent, "sDockedDividerWindow");
- sAppWindow = createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "sAppWindow");
- sChildAppWindow = createWindow(sAppWindow,
- TYPE_APPLICATION_ATTACHED_DIALOG, sAppWindow.mToken, "sChildAppWindow");
- }
-
@Test
public void testAssignWindowLayers_ForImeWithNoTarget() throws Exception {
sWm.mInputMethodTarget = null;
@@ -90,7 +47,7 @@
// The Ime has an higher base layer than app windows and lower base layer than system
// windows, so it should be above app windows and below system windows if there isn't an IME
// target.
- assertWindowLayerGreaterThan(sImeWindow, sChildAppWindow);
+ assertWindowLayerGreaterThan(sImeWindow, sChildAppWindowAbove);
assertWindowLayerGreaterThan(sImeWindow, sAppWindow);
assertWindowLayerGreaterThan(sImeWindow, sDockedDividerWindow);
assertWindowLayerGreaterThan(sNavBarWindow, sImeWindow);
@@ -110,7 +67,63 @@
// Ime should be above all app windows and below system windows if it is targeting an app
// window.
assertWindowLayerGreaterThan(sImeWindow, imeAppTarget);
- assertWindowLayerGreaterThan(sImeWindow, sChildAppWindow);
+ assertWindowLayerGreaterThan(sImeWindow, sChildAppWindowAbove);
+ assertWindowLayerGreaterThan(sImeWindow, sAppWindow);
+ assertWindowLayerGreaterThan(sImeWindow, sDockedDividerWindow);
+ assertWindowLayerGreaterThan(sNavBarWindow, sImeWindow);
+ assertWindowLayerGreaterThan(sStatusBarWindow, sImeWindow);
+
+ // And, IME dialogs should always have an higher layer than the IME.
+ assertWindowLayerGreaterThan(sImeDialogWindow, sImeWindow);
+ }
+
+ @Test
+ public void testAssignWindowLayers_ForImeWithAppTargetWithChildWindows() throws Exception {
+ final WindowState imeAppTarget =
+ createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "imeAppTarget");
+ final WindowState imeAppTargetChildAboveWindow = createWindow(imeAppTarget,
+ TYPE_APPLICATION_ATTACHED_DIALOG, imeAppTarget.mToken,
+ "imeAppTargetChildAboveWindow");
+ final WindowState imeAppTargetChildBelowWindow = createWindow(imeAppTarget,
+ TYPE_APPLICATION_MEDIA_OVERLAY, imeAppTarget.mToken,
+ "imeAppTargetChildBelowWindow");
+
+ sWm.mInputMethodTarget = imeAppTarget;
+ sLayersController.assignWindowLayers(sDisplayContent);
+
+ // Ime should be above all app windows except for child windows that are z-ordered above it
+ // and below system windows if it is targeting an app window.
+ assertWindowLayerGreaterThan(sImeWindow, imeAppTarget);
+ assertWindowLayerGreaterThan(imeAppTargetChildAboveWindow, sImeWindow);
+ assertWindowLayerGreaterThan(sImeWindow, imeAppTargetChildBelowWindow);
+ assertWindowLayerGreaterThan(sImeWindow, sChildAppWindowAbove);
+ assertWindowLayerGreaterThan(sImeWindow, sAppWindow);
+ assertWindowLayerGreaterThan(sImeWindow, sDockedDividerWindow);
+ assertWindowLayerGreaterThan(sNavBarWindow, sImeWindow);
+ assertWindowLayerGreaterThan(sStatusBarWindow, sImeWindow);
+
+ // And, IME dialogs should always have an higher layer than the IME.
+ assertWindowLayerGreaterThan(sImeDialogWindow, sImeWindow);
+ }
+
+ @Test
+ public void testAssignWindowLayers_ForImeWithAppTargetAndAppAbove() throws Exception {
+ final WindowState appBelowImeTarget =
+ createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "appBelowImeTarget");
+ final WindowState imeAppTarget =
+ createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "imeAppTarget");
+ final WindowState appAboveImeTarget =
+ createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "appAboveImeTarget");
+
+ sWm.mInputMethodTarget = imeAppTarget;
+ sLayersController.assignWindowLayers(sDisplayContent);
+
+ // Ime should be above all app windows except for non-fullscreen app window above it and
+ // below system windows if it is targeting an app window.
+ assertWindowLayerGreaterThan(sImeWindow, imeAppTarget);
+ assertWindowLayerGreaterThan(sImeWindow, appBelowImeTarget);
+ assertWindowLayerGreaterThan(appAboveImeTarget, sImeWindow);
+ assertWindowLayerGreaterThan(sImeWindow, sChildAppWindowAbove);
assertWindowLayerGreaterThan(sImeWindow, sAppWindow);
assertWindowLayerGreaterThan(sImeWindow, sDockedDividerWindow);
assertWindowLayerGreaterThan(sNavBarWindow, sImeWindow);
@@ -131,7 +144,7 @@
// The IME target base layer is higher than all window except for the nav bar window, so the
// IME should be above all windows except for the nav bar.
assertWindowLayerGreaterThan(sImeWindow, imeSystemOverlayTarget);
- assertWindowLayerGreaterThan(sImeWindow, sChildAppWindow);
+ assertWindowLayerGreaterThan(sImeWindow, sChildAppWindowAbove);
assertWindowLayerGreaterThan(sImeWindow, sAppWindow);
assertWindowLayerGreaterThan(sImeWindow, sDockedDividerWindow);
assertWindowLayerGreaterThan(sImeWindow, sStatusBarWindow);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index 50e5a22..df35b7e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -16,23 +16,18 @@
package com.android.server.wm;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import android.content.Context;
-import android.os.Binder;
import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.IWindow;
-import android.view.WindowManager;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -41,30 +36,19 @@
/**
* Tests for the {@link WindowState} class.
*
- * runtest frameworks-services -c com.android.server.wm.WindowStateTests
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.wm.WindowStateTests
*/
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
public class WindowStateTests extends WindowTestsBase {
- private WindowToken mWindowToken;
-
- @Before
- public void setUp() throws Exception {
- super.setUp();
- mWindowToken = new WindowToken(sWm, new Binder(), 0, false,
- sWm.getDefaultDisplayContentLocked());
- }
-
@Test
public void testIsParentWindowHidden() throws Exception {
- final WindowState parentWindow =
- createWindow(null, TYPE_APPLICATION, mWindowToken, "parentWindow");
- final WindowState child1 =
- createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child1");
- final WindowState child2 =
- createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child2");
+ final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
+ final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");
assertFalse(parentWindow.mHidden);
assertFalse(parentWindow.isParentWindowHidden());
@@ -79,14 +63,10 @@
@Test
public void testIsChildWindow() throws Exception {
- final WindowState parentWindow =
- createWindow(null, TYPE_APPLICATION, mWindowToken, "parentWindow");
- final WindowState child1 =
- createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child1");
- final WindowState child2 =
- createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child2");
- final WindowState randomWindow =
- createWindow(null, TYPE_APPLICATION, mWindowToken, "randomWindow");
+ final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
+ final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");
+ final WindowState randomWindow = createWindow(null, TYPE_APPLICATION, "randomWindow");
assertFalse(parentWindow.isChildWindow());
assertTrue(child1.isChildWindow());
@@ -96,13 +76,12 @@
@Test
public void testHasChild() throws Exception {
- final WindowState win1 = createWindow(null, TYPE_APPLICATION, mWindowToken, "win1");
- final WindowState win11 = createWindow(win1, FIRST_SUB_WINDOW, mWindowToken, "win11");
- final WindowState win12 = createWindow(win1, FIRST_SUB_WINDOW, mWindowToken, "win12");
- final WindowState win2 = createWindow(null, TYPE_APPLICATION, mWindowToken, "win2");
- final WindowState win21 = createWindow(win2, FIRST_SUB_WINDOW, mWindowToken, "win21");
- final WindowState randomWindow =
- createWindow(null, TYPE_APPLICATION, mWindowToken, "randomWindow");
+ final WindowState win1 = createWindow(null, TYPE_APPLICATION, "win1");
+ final WindowState win11 = createWindow(win1, FIRST_SUB_WINDOW, "win11");
+ final WindowState win12 = createWindow(win1, FIRST_SUB_WINDOW, "win12");
+ final WindowState win2 = createWindow(null, TYPE_APPLICATION, "win2");
+ final WindowState win21 = createWindow(win2, FIRST_SUB_WINDOW, "win21");
+ final WindowState randomWindow = createWindow(null, TYPE_APPLICATION, "randomWindow");
assertTrue(win1.hasChild(win11));
assertTrue(win1.hasChild(win12));
@@ -117,42 +96,10 @@
}
@Test
- public void testGetBottomChild() throws Exception {
- final WindowState parentWindow =
- createWindow(null, TYPE_APPLICATION, mWindowToken, "parentWindow");
- assertNull(parentWindow.getBottomChild());
-
- final WindowState child1 =
- createWindow(parentWindow, TYPE_APPLICATION_PANEL, mWindowToken, "child1");
- assertEquals(child1, parentWindow.getBottomChild());
-
- final WindowState child2 =
- createWindow(parentWindow, TYPE_APPLICATION_PANEL, mWindowToken, "child2");
- // Since child1 and child2 are at the same layer, then child2 is expect to be added on top
- // on child1
- assertEquals(child1, parentWindow.getBottomChild());
-
- final WindowState child3 =
- createWindow(parentWindow, TYPE_APPLICATION_MEDIA_OVERLAY, mWindowToken, "child3");
- // Since child3 is a negative layer, we would expect it to be added below current children
- // with positive layers.
- assertEquals(child3, parentWindow.getBottomChild());
-
- final WindowState child4 =
- createWindow(parentWindow, TYPE_APPLICATION_MEDIA_OVERLAY, mWindowToken, "child4");
- // We would also expect additional negative layers to be added below existing negative
- // layers.
- assertEquals(child4, parentWindow.getBottomChild());
- }
-
- @Test
public void testGetParentWindow() throws Exception {
- final WindowState parentWindow =
- createWindow(null, TYPE_APPLICATION, mWindowToken, "parentWindow");
- final WindowState child1 =
- createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child1");
- final WindowState child2 =
- createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child2");
+ final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
+ final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");
assertNull(parentWindow.getParentWindow());
assertEquals(parentWindow, child1.getParentWindow());
@@ -161,22 +108,63 @@
@Test
public void testGetTopParentWindow() throws Exception {
- final WindowState root = createWindow(null, TYPE_APPLICATION, mWindowToken, "root");
- final WindowState child1 = createWindow(root, FIRST_SUB_WINDOW, mWindowToken, "child1");
- final WindowState child2 = createWindow(child1, FIRST_SUB_WINDOW, mWindowToken, "child2");
+ final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
+ final WindowState child1 = createWindow(root, FIRST_SUB_WINDOW, "child1");
+ final WindowState child2 = createWindow(child1, FIRST_SUB_WINDOW, "child2");
assertEquals(root, root.getTopParentWindow());
assertEquals(root, child1.getTopParentWindow());
assertEquals(child1, child2.getParentWindow());
assertEquals(root, child2.getTopParentWindow());
+
+ // Test case were child is detached from parent.
+ root.removeChild(child1);
+ assertEquals(child1, child1.getTopParentWindow());
+ assertEquals(child1, child2.getParentWindow());
}
@Test
public void testIsOnScreen_hiddenByPolicy() {
- final WindowState window = createWindow(null, TYPE_APPLICATION, mWindowToken, "window");
+ final WindowState window = createWindow(null, TYPE_APPLICATION, "window");
window.setHasSurface(true);
assertTrue(window.isOnScreen());
window.hideLw(false /* doAnimation */);
assertFalse(window.isOnScreen());
}
+
+ @Test
+ public void testCanBeImeTarget() throws Exception {
+ final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
+ final WindowState imeWindow = createWindow(null, TYPE_INPUT_METHOD, "imeWindow");
+
+ // Setting FLAG_NOT_FOCUSABLE without FLAG_ALT_FOCUSABLE_IM prevents the window from being
+ // an IME target.
+ appWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
+ imeWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
+
+ // Make windows visible
+ appWindow.setHasSurface(true);
+ imeWindow.setHasSurface(true);
+
+ // Windows without flags (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) can't be IME targets
+ assertFalse(appWindow.canBeImeTarget());
+ assertFalse(imeWindow.canBeImeTarget());
+
+ // Add IME target flags
+ appWindow.mAttrs.flags |= (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);
+ imeWindow.mAttrs.flags |= (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);
+
+ // Visible app window with flags can be IME target while an IME window can never be an IME
+ // target regardless of its visibility or flags.
+ assertTrue(appWindow.canBeImeTarget());
+ assertFalse(imeWindow.canBeImeTarget());
+
+ // Make windows invisible
+ appWindow.hideLw(false /* doAnimation */);
+ imeWindow.hideLw(false /* doAnimation */);
+
+ // Invisible window can't be IME targets even if they have the right flags.
+ assertFalse(appWindow.canBeImeTarget());
+ assertFalse(imeWindow.canBeImeTarget());
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 9681bd2..41bf646 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -22,7 +22,6 @@
import android.content.Context;
import android.os.IBinder;
import android.support.test.InstrumentationRegistry;
-import android.view.Display;
import android.view.IWindow;
import android.view.WindowManager;
@@ -31,6 +30,15 @@
import static android.content.res.Configuration.EMPTY;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static org.mockito.Mockito.mock;
/**
@@ -40,15 +48,49 @@
static WindowManagerService sWm = null;
private final IWindow mIWindow = new TestIWindow();
private final Session mMockSession = mock(Session.class);
- Display mDisplay;
private static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
private static int sNextTaskId = 0;
+ private static boolean sOneTimeSetupDone = false;
+ protected static DisplayContent sDisplayContent;
+ protected static WindowLayersController sLayersController;
+ protected static WindowState sWallpaperWindow;
+ protected static WindowState sImeWindow;
+ protected static WindowState sImeDialogWindow;
+ protected static WindowState sStatusBarWindow;
+ protected static WindowState sDockedDividerWindow;
+ protected static WindowState sNavBarWindow;
+ protected static WindowState sAppWindow;
+ protected static WindowState sChildAppWindowAbove;
+ protected static WindowState sChildAppWindowBelow;
+
@Before
public void setUp() throws Exception {
+ if (sOneTimeSetupDone) {
+ return;
+ }
+ sOneTimeSetupDone = true;
final Context context = InstrumentationRegistry.getTargetContext();
sWm = TestWindowManagerPolicy.getWindowManagerService(context);
- mDisplay = context.getDisplay();
+ sLayersController = new WindowLayersController(sWm);
+ sDisplayContent = new DisplayContent(context.getDisplay(), sWm, sLayersController,
+ new WallpaperController(sWm));
+
+ // Set-up some common windows.
+ sWallpaperWindow = createWindow(null, TYPE_WALLPAPER, sDisplayContent, "wallpaperWindow");
+ sImeWindow = createWindow(null, TYPE_INPUT_METHOD, sDisplayContent, "sImeWindow");
+ sImeDialogWindow =
+ createWindow(null, TYPE_INPUT_METHOD_DIALOG, sDisplayContent, "sImeDialogWindow");
+ sStatusBarWindow = createWindow(null, TYPE_STATUS_BAR, sDisplayContent, "sStatusBarWindow");
+ sNavBarWindow =
+ createWindow(null, TYPE_NAVIGATION_BAR, sDisplayContent, "sNavBarWindow");
+ sDockedDividerWindow =
+ createWindow(null, TYPE_DOCK_DIVIDER, sDisplayContent, "sDockedDividerWindow");
+ sAppWindow = createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "sAppWindow");
+ sChildAppWindowAbove = createWindow(sAppWindow,
+ TYPE_APPLICATION_ATTACHED_DIALOG, sAppWindow.mToken, "sChildAppWindowAbove");
+ sChildAppWindowBelow = createWindow(sAppWindow,
+ TYPE_APPLICATION_MEDIA_OVERLAY, sAppWindow.mToken, "sChildAppWindowBelow");
}
/** Asserts that the first entry is greater than the second entry. */
@@ -56,21 +98,27 @@
Assert.assertTrue("Excepted " + first + " to be greater than " + second, first > second);
}
- WindowToken createWindowToken(DisplayContent dc, int type) {
+ private WindowToken createWindowToken(DisplayContent dc, int type) {
if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) {
- return new WindowToken(sWm, mock(IBinder.class), type, false, dc);
+ return new TestWindowToken(type, dc);
}
final int stackId = sNextStackId++;
dc.addStackToDisplay(stackId, true);
final TaskStack stack = sWm.mStackIdToStack.get(stackId);
- final Task task = new Task(sNextTaskId++, stack, 0, sWm, null, EMPTY, false);
+ final Task task = new Task(sNextTaskId++, stack, 0, sWm, null, EMPTY, false, 0, false);
stack.addTask(task, true);
- final AppWindowToken token = new AppWindowToken(sWm, null, false, dc);
- task.addAppToken(0, token, 0, false);
+ final TestAppWindowToken token = new TestAppWindowToken(dc);
+ task.addChild(token, 0);
return token;
}
+ WindowState createWindow(WindowState parent, int type, String name) {
+ return (parent == null)
+ ? createWindow(parent, type, sDisplayContent, name)
+ : createWindow(parent, type, parent.mToken, name);
+ }
+
WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name) {
final WindowToken token = createWindowToken(dc, type);
return createWindow(parent, type, token, name);
@@ -87,4 +135,48 @@
token.addWindow(w);
return w;
}
+
+ /* Used so we can gain access to some protected members of the {@link WindowToken} class */
+ class TestWindowToken extends WindowToken {
+
+ TestWindowToken(int type, DisplayContent dc) {
+ this(type, dc, false /* persistOnEmpty */);
+ }
+
+ TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
+ super(sWm, mock(IBinder.class), type, persistOnEmpty, dc);
+ }
+
+ int getWindowsCount() {
+ return mChildren.size();
+ }
+
+ boolean hasWindow(WindowState w) {
+ return mChildren.contains(w);
+ }
+ }
+
+ /* Used so we can gain access to some protected members of the {@link AppWindowToken} class */
+ class TestAppWindowToken extends AppWindowToken {
+
+ TestAppWindowToken(DisplayContent dc) {
+ super(sWm, null, false, dc);
+ }
+
+ int getWindowsCount() {
+ return mChildren.size();
+ }
+
+ boolean hasWindow(WindowState w) {
+ return mChildren.contains(w);
+ }
+
+ WindowState getFirstChild() {
+ return mChildren.getFirst();
+ }
+
+ WindowState getLastChild() {
+ return mChildren.getLast();
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
index d6bfa17..0c053b9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
@@ -16,24 +16,19 @@
package com.android.server.wm;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import android.content.Context;
-import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.IWindow;
-import android.view.WindowManager;
-import static android.app.AppOpsManager.OP_NONE;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
@@ -51,7 +46,7 @@
@Test
public void testAddWindow() throws Exception {
- final TestWindowToken token = new TestWindowToken();
+ final TestWindowToken token = new TestWindowToken(0, sDisplayContent);
assertEquals(0, token.getWindowsCount());
@@ -80,15 +75,13 @@
@Test
public void testChildRemoval() throws Exception {
- final TestWindowToken token = new TestWindowToken();
- final DisplayContent dc = sWm.getDefaultDisplayContentLocked();
+ final DisplayContent dc = sDisplayContent;
+ final TestWindowToken token = new TestWindowToken(0, dc);
assertEquals(token, dc.getWindowToken(token.token));
final WindowState window1 = createWindow(null, TYPE_APPLICATION, token, "window1");
final WindowState window2 = createWindow(null, TYPE_APPLICATION, token, "window2");
- token.addWindow(window1);
- token.addWindow(window2);
window2.removeImmediately();
// The token should still be mapped in the display content since it still has a child.
@@ -102,17 +95,13 @@
@Test
public void testAdjustAnimLayer() throws Exception {
- final TestWindowToken token = new TestWindowToken();
+ final TestWindowToken token = new TestWindowToken(0, sDisplayContent);
final WindowState window1 = createWindow(null, TYPE_APPLICATION, token, "window1");
final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token, "window11");
final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token, "window12");
final WindowState window2 = createWindow(null, TYPE_APPLICATION, token, "window2");
final WindowState window3 = createWindow(null, TYPE_APPLICATION, token, "window3");
- token.addWindow(window1);
- token.addWindow(window2);
- token.addWindow(window3);
-
final int adj = 50;
final int window2StartLayer = window2.mLayer = 100;
final int window3StartLayer = window3.mLayer = 200;
@@ -126,19 +115,39 @@
assertEquals(window3StartLayer + adj, highestLayer);
}
- /* Used so we can gain access to some protected members of the {@link WindowToken} class */
- private class TestWindowToken extends WindowToken {
+ /**
+ * Test that a window token isn't orphaned by the system when it is requested to be removed.
+ * Tokens should only be removed from the system when all their windows are gone.
+ */
+ @Test
+ public void testTokenRemovalProcess() throws Exception {
+ final TestWindowToken token =
+ new TestWindowToken(TYPE_TOAST, sDisplayContent, true /* persistOnEmpty */);
- TestWindowToken() {
- super(sWm, mock(IBinder.class), 0, false, sWm.getDefaultDisplayContentLocked());
- }
+ // Verify that the token is on the display
+ assertNotNull(sDisplayContent.getWindowToken(token.token));
- int getWindowsCount() {
- return mChildren.size();
- }
+ final WindowState window1 = createWindow(null, TYPE_TOAST, token, "window1");
+ final WindowState window2 = createWindow(null, TYPE_TOAST, token, "window2");
- boolean hasWindow(WindowState w) {
- return mChildren.contains(w);
- }
+ sDisplayContent.removeWindowToken(token.token);
+ // Verify that the token is no longer mapped on the display
+ assertNull(sDisplayContent.getWindowToken(token.token));
+ // Verify that the token is still attached to its parent
+ assertNotNull(token.getParent());
+ // Verify that the token windows are still around.
+ assertEquals(2, token.getWindowsCount());
+
+ window1.removeImmediately();
+ // Verify that the token is still attached to its parent
+ assertNotNull(token.getParent());
+ // Verify that the other token window is still around.
+ assertEquals(1, token.getWindowsCount());
+
+ window2.removeImmediately();
+ // Verify that the token is no-longer attached to its parent
+ assertNull(token.getParent());
+ // Verify that the token windows are no longer attached to it.
+ assertEquals(0, token.getWindowsCount());
}
}
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index 1fe5cb7..6e74deb 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -764,6 +764,12 @@
filter(mList, ShortcutInfo::isPinned));
}
+ public ShortcutListAsserter selectFloating() {
+ return new ShortcutListAsserter(this,
+ filter(mList, (si -> si.isPinned()
+ && !(si.isDynamic() || si.isDeclaredInManifest()))));
+ }
+
public ShortcutListAsserter selectByActivity(ComponentName activity) {
return new ShortcutListAsserter(this,
ShortcutManagerTestUtils.filterByActivity(mList, activity));
@@ -895,6 +901,11 @@
return this;
}
+ public ShortcutListAsserter areAllWithNoActivity() {
+ forAllShortcuts(s -> assertNull("id=" + s.getId(), s.getActivity()));
+ return this;
+ }
+
public ShortcutListAsserter forAllShortcuts(Consumer<ShortcutInfo> sa) {
boolean found = false;
for (int i = 0; i < mList.size(); i++) {
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index f541f70..cb32d1f 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -121,6 +121,23 @@
endTime = timeStamp;
}
+ void updateChooserCounts(String packageName, String category, String action) {
+ UsageStats usageStats = getOrCreateUsageStats(packageName);
+ if (usageStats.mChooserCounts == null) {
+ usageStats.mChooserCounts = new ArrayMap<>();
+ }
+ ArrayMap<String, Integer> chooserCounts;
+ final int idx = usageStats.mChooserCounts.indexOfKey(action);
+ if (idx < 0) {
+ chooserCounts = new ArrayMap<>();
+ usageStats.mChooserCounts.put(action, chooserCounts);
+ } else {
+ chooserCounts = usageStats.mChooserCounts.valueAt(idx);
+ }
+ int currentCount = chooserCounts.getOrDefault(category, 0);
+ chooserCounts.put(category, currentCount + 1);
+ }
+
void updateConfigurationStats(Configuration config, long timeStamp) {
if (activeConfiguration != null) {
ConfigurationStats activeStats = configurations.get(activeConfiguration);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 849262e..1b28db7 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -17,6 +17,7 @@
package com.android.server.usage;
import android.app.usage.TimeSparseArray;
+import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.os.Build;
import android.util.AtomicFile;
@@ -502,6 +503,12 @@
pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_DAILY],
mCal.getTimeInMillis());
+ mCal.setTimeInMillis(currentTimeMillis);
+ mCal.addDays(-14);
+ for (int i = 0; i < mIntervalDirs.length; ++i) {
+ pruneChooserCountsOlderThan(mIntervalDirs[i], mCal.getTimeInMillis());
+ }
+
// We must re-index our file list or we will be trying to read
// deleted files.
indexFilesLocked();
@@ -531,6 +538,43 @@
}
}
+ private static void pruneChooserCountsOlderThan(File dir, long expiryTime) {
+ File[] files = dir.listFiles();
+ if (files != null) {
+ for (File f : files) {
+ String path = f.getPath();
+ if (path.endsWith(BAK_SUFFIX)) {
+ f = new File(path.substring(0, path.length() - BAK_SUFFIX.length()));
+ }
+
+ long beginTime;
+ try {
+ beginTime = UsageStatsXml.parseBeginTime(f);
+ } catch (IOException e) {
+ beginTime = 0;
+ }
+
+ if (beginTime < expiryTime) {
+ try {
+ final AtomicFile af = new AtomicFile(f);
+ final IntervalStats stats = new IntervalStats();
+ UsageStatsXml.read(af, stats);
+ final int pkgCount = stats.packageStats.size();
+ for (int i = 0; i < pkgCount; i++) {
+ UsageStats pkgStats = stats.packageStats.valueAt(i);
+ if (pkgStats.mChooserCounts != null) {
+ pkgStats.mChooserCounts.clear();
+ }
+ }
+ UsageStatsXml.write(af, stats);
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to delete chooser counts from usage stats file", e);
+ }
+ }
+ }
+ }
+ }
+
/**
* Update the stats in the database. They may not be written to disk immediately.
*/
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 515370f..4bfc3df 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -1379,6 +1379,31 @@
}
UsageStatsService.this.dump(args, pw);
}
+
+ @Override
+ public void reportChooserSelection(String packageName, int userId, String contentType,
+ String[] annotations, String action) {
+ if (packageName == null) {
+ Slog.w(TAG, "Event report user selecting a null package");
+ return;
+ }
+
+ UsageEvents.Event event = new UsageEvents.Event();
+ event.mPackage = packageName;
+
+ // This will later be converted to system time.
+ event.mTimeStamp = SystemClock.elapsedRealtime();
+
+ event.mEventType = Event.CHOOSER_ACTION;
+
+ event.mAction = action;
+
+ event.mContentType = contentType;
+
+ event.mContentAnnotations = annotations;
+
+ mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
+ }
}
/**
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index 03cee9c..96f3305 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -26,6 +26,7 @@
import android.app.usage.UsageEvents;
import android.app.usage.UsageStats;
import android.content.res.Configuration;
+import android.util.ArrayMap;
import java.io.IOException;
import java.net.ProtocolException;
@@ -37,6 +38,11 @@
private static final String PACKAGES_TAG = "packages";
private static final String PACKAGE_TAG = "package";
+ private static final String CHOOSER_COUNT_TAG = "chosen_action";
+ private static final String CATEGORY_TAG = "category";
+ private static final String NAME = "name";
+ private static final String COUNT = "count";
+
private static final String CONFIGURATIONS_TAG = "configurations";
private static final String CONFIG_TAG = "config";
@@ -59,7 +65,7 @@
private static final String TIME_ATTR = "time";
private static void loadUsageStats(XmlPullParser parser, IntervalStats statsOut)
- throws IOException {
+ throws XmlPullParserException, IOException {
final String pkg = parser.getAttributeValue(null, PACKAGE_ATTR);
if (pkg == null) {
throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present");
@@ -72,6 +78,51 @@
parser, LAST_TIME_ACTIVE_ATTR);
stats.mTotalTimeInForeground = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR);
stats.mLastEvent = XmlUtils.readIntAttribute(parser, LAST_EVENT_ATTR);
+ int eventCode;
+ while ((eventCode = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ final String tag = parser.getName();
+ if (eventCode == XmlPullParser.END_TAG && tag.equals(PACKAGE_TAG)) {
+ break;
+ }
+ if (eventCode != XmlPullParser.START_TAG) {
+ continue;
+ }
+ if (tag.equals(CHOOSER_COUNT_TAG)) {
+ String action = XmlUtils.readStringAttribute(parser, NAME);
+ loadChooserCounts(parser, stats, action);
+ }
+ }
+ }
+
+ private static void loadChooserCounts(
+ XmlPullParser parser, UsageStats usageStats, String action)
+ throws XmlPullParserException, IOException {
+ if (action == null) {
+ return;
+ }
+ if (usageStats.mChooserCounts == null) {
+ usageStats.mChooserCounts = new ArrayMap<>();
+ }
+ if (!usageStats.mChooserCounts.containsKey(action)) {
+ ArrayMap<String, Integer> counts = new ArrayMap<>();
+ usageStats.mChooserCounts.put(action, counts);
+ }
+
+ int eventCode;
+ while ((eventCode = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ final String tag = parser.getName();
+ if (eventCode == XmlPullParser.END_TAG && tag.equals(CHOOSER_COUNT_TAG)) {
+ break;
+ }
+ if (eventCode != XmlPullParser.START_TAG) {
+ continue;
+ }
+ if (tag.equals(CATEGORY_TAG)) {
+ String category = XmlUtils.readStringAttribute(parser, NAME);
+ int count = XmlUtils.readIntAttribute(parser, COUNT);
+ usageStats.mChooserCounts.get(action).put(category, count);
+ }
+ }
}
private static void loadConfigStats(XmlPullParser parser, IntervalStats statsOut)
@@ -135,10 +186,45 @@
XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, usageStats.mPackageName);
XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, usageStats.mTotalTimeInForeground);
XmlUtils.writeIntAttribute(xml, LAST_EVENT_ATTR, usageStats.mLastEvent);
-
+ writeChooserCounts(xml, usageStats);
xml.endTag(null, PACKAGE_TAG);
}
+ private static void writeChooserCounts(XmlSerializer xml, final UsageStats usageStats)
+ throws IOException {
+ if (usageStats == null || usageStats.mChooserCounts == null ||
+ usageStats.mChooserCounts.keySet().isEmpty()) {
+ return;
+ }
+ final int chooserCountSize = usageStats.mChooserCounts.size();
+ for (int i = 0; i < chooserCountSize; i++) {
+ final String action = usageStats.mChooserCounts.keyAt(i);
+ final ArrayMap<String, Integer> counts = usageStats.mChooserCounts.valueAt(i);
+ if (action == null || counts == null || counts.isEmpty()) {
+ continue;
+ }
+ xml.startTag(null, CHOOSER_COUNT_TAG);
+ XmlUtils.writeStringAttribute(xml, NAME, action);
+ writeCountsForAction(xml, counts);
+ xml.endTag(null, CHOOSER_COUNT_TAG);
+ }
+ }
+
+ private static void writeCountsForAction(XmlSerializer xml, ArrayMap<String, Integer> counts)
+ throws IOException {
+ final int countsSize = counts.size();
+ for (int i = 0; i < countsSize; i++) {
+ String key = counts.keyAt(i);
+ int count = counts.valueAt(i);
+ if (count > 0) {
+ xml.startTag(null, CATEGORY_TAG);
+ XmlUtils.writeStringAttribute(xml, NAME, key);
+ XmlUtils.writeIntAttribute(xml, COUNT, count);
+ xml.endTag(null, CATEGORY_TAG);
+ }
+ }
+ }
+
private static void writeConfigStats(XmlSerializer xml, final IntervalStats stats,
final ConfigurationStats configStats, boolean isActive) throws IOException {
xml.startTag(null, CONFIG_TAG);
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 59e4c80..ba770ef 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -183,6 +183,15 @@
for (IntervalStats stats : mCurrentStats) {
if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE) {
stats.updateConfigurationStats(newFullConfig, event.mTimeStamp);
+ } else if (event.mEventType == UsageEvents.Event.CHOOSER_ACTION) {
+ stats.updateChooserCounts(event.mPackage, event.mContentType, event.mAction);
+ String[] annotations = event.mContentAnnotations;
+ if (annotations != null) {
+ for (String annotation : annotations) {
+ // TODO(kanlig): update with confidences of annotations.
+ stats.updateChooserCounts(event.mPackage, annotation, event.mAction);
+ }
+ }
} else {
stats.update(event.mPackage, event.mTimeStamp, event.mEventType);
}
@@ -520,6 +529,32 @@
}
pw.decreaseIndent();
+ pw.println();
+ pw.increaseIndent();
+ pw.println("ChooserCounts");
+ pw.increaseIndent();
+ for (UsageStats usageStats : pkgStats.values()) {
+ pw.printPair("package", usageStats.mPackageName);
+ if (usageStats.mChooserCounts != null) {
+ final int chooserCountSize = usageStats.mChooserCounts.size();
+ for (int i = 0; i < chooserCountSize; i++) {
+ final String action = usageStats.mChooserCounts.keyAt(i);
+ final ArrayMap<String, Integer> counts = usageStats.mChooserCounts.valueAt(i);
+ final int annotationSize = counts.size();
+ for (int j = 0; j < annotationSize; j++) {
+ final String key = counts.keyAt(j);
+ final int count = counts.valueAt(j);
+ if (count != 0) {
+ pw.printPair("ChooserCounts", action + ":" + key + " is " +
+ Integer.toString(count));
+ pw.println();
+ }
+ }
+ }
+ }
+ pw.println();
+ }
+
pw.println("configurations");
pw.increaseIndent();
final ArrayMap<Configuration, ConfigurationStats> configStats = stats.configurations;
@@ -593,6 +628,8 @@
return "USER_INTERACTION";
case UsageEvents.Event.SHORTCUT_INVOCATION:
return "SHORTCUT_INVOCATION";
+ case UsageEvents.Event.CHOOSER_ACTION:
+ return "CHOOSER_ACTION";
default:
return "UNKNOWN";
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index b86a85b..581dbe3 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -361,8 +361,6 @@
UsbManager.removeFunction(persisted, UsbManager.USB_FUNCTION_MTP));
}
- setEnabledFunctions(null, false, false);
-
String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
updateState(state);
@@ -456,13 +454,12 @@
return false;
}
- private boolean setUsbConfig(String config) {
+ private void setUsbConfig(String config) {
if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")");
// set the new configuration
// we always set it due to b/23631400, where adbd was getting killed
// and not restarted due to property timeouts on some devices
SystemProperties.set(USB_CONFIG_PROPERTY, config);
- return waitForState(config);
}
private void setAdbEnabled(boolean enable) {
@@ -557,8 +554,18 @@
// Kick the USB stack to close existing connections.
setUsbConfig(UsbManager.USB_FUNCTION_NONE);
+ if (!waitForState(UsbManager.USB_FUNCTION_NONE)) {
+ Slog.e(TAG, "Failed to kick USB config");
+ return false;
+ }
+
// Set the new USB configuration.
- if (!setUsbConfig(functions)) {
+ setUsbConfig(functions);
+
+ // Start up dependent services.
+ updateUsbStateBroadcastIfNeeded(true);
+
+ if (!waitForState(functions)) {
Slog.e(TAG, "Failed to switch USB config to " + functions);
return false;
}
@@ -641,7 +648,7 @@
return false;
}
- private void updateUsbStateBroadcastIfNeeded() {
+ private void updateUsbStateBroadcastIfNeeded(boolean configChanged) {
// send a sticky broadcast containing current USB state
Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
@@ -650,6 +657,7 @@
intent.putExtra(UsbManager.USB_HOST_CONNECTED, mHostConnected);
intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
intent.putExtra(UsbManager.USB_DATA_UNLOCKED, isUsbTransferAllowed() && mUsbDataUnlocked);
+ intent.putExtra(UsbManager.USB_CONFIG_CHANGED, configChanged);
if (mCurrentFunctions != null) {
String[] functions = mCurrentFunctions.split(",");
@@ -747,7 +755,7 @@
setEnabledFunctions(null, false, false);
}
if (mBootCompleted) {
- updateUsbStateBroadcastIfNeeded();
+ updateUsbStateBroadcastIfNeeded(false);
updateUsbFunctions();
}
break;
@@ -759,7 +767,7 @@
args.recycle();
updateUsbNotification();
if (mBootCompleted) {
- updateUsbStateBroadcastIfNeeded();
+ updateUsbStateBroadcastIfNeeded(false);
}
break;
case MSG_ENABLE_ADB:
@@ -775,11 +783,11 @@
case MSG_SYSTEM_READY:
updateUsbNotification();
updateAdbNotification();
- updateUsbStateBroadcastIfNeeded();
updateUsbFunctions();
break;
case MSG_BOOT_COMPLETED:
mBootCompleted = true;
+ setEnabledFunctions(null, false, false);
if (mCurrentAccessory != null) {
getCurrentSettings().accessoryAttached(mCurrentAccessory);
}
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index c99e22a..c69b7c2 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -324,6 +324,7 @@
private final PhoneAccountHandle mAccountHandle;
private final int mCallCapabilities;
private final int mCallProperties;
+ private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
private final DisconnectCause mDisconnectCause;
private final long mConnectTimeMillis;
private final GatewayInfo mGatewayInfo;
@@ -536,6 +537,15 @@
}
/**
+ * @return a bitmask of the audio routes available for the call.
+ *
+ * @hide
+ */
+ public int getSupportedAudioRoutes() {
+ return mSupportedAudioRoutes;
+ }
+
+ /**
* @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
* by {@link android.telecom.DisconnectCause}.
*/
diff --git a/telecomm/java/android/telecom/CallAudioState.java b/telecomm/java/android/telecom/CallAudioState.java
index 2b16722..f601d8b 100644
--- a/telecomm/java/android/telecom/CallAudioState.java
+++ b/telecomm/java/android/telecom/CallAudioState.java
@@ -44,8 +44,12 @@
*/
public static final int ROUTE_WIRED_OR_EARPIECE = ROUTE_EARPIECE | ROUTE_WIRED_HEADSET;
- /** Bit mask of all possible audio routes. */
- private static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
+ /**
+ * Bit mask of all possible audio routes.
+ *
+ * @hide
+ **/
+ public static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
ROUTE_SPEAKER;
private final boolean isMuted;
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index a012082..177759e 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -28,6 +28,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
@@ -453,6 +454,10 @@
* @param conferenceableConnections The set of connections this connection can conference with.
*/
public final void setConferenceableConnections(List<Connection> conferenceableConnections) {
+ if (Objects.equals(mConferenceableConnections, conferenceableConnections)) {
+ return;
+ }
+
clearConferenceableList();
for (Connection c : conferenceableConnections) {
// If statement checks for duplicates in input. It makes it N^2 but we're dealing with a
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 2b9a508..7d258a0 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -723,6 +723,7 @@
public void onDestroyed(Connection c) {}
public void onConnectionCapabilitiesChanged(Connection c, int capabilities) {}
public void onConnectionPropertiesChanged(Connection c, int properties) {}
+ public void onSupportedAudioRoutesChanged(Connection c, int supportedAudioRoutes) {}
public void onVideoProviderChanged(
Connection c, VideoProvider videoProvider) {}
public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {}
@@ -1485,6 +1486,7 @@
private boolean mRingbackRequested = false;
private int mConnectionCapabilities;
private int mConnectionProperties;
+ private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
private VideoProvider mVideoProvider;
private boolean mAudioModeIsVoip;
private long mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED;
@@ -1765,6 +1767,15 @@
}
/**
+ * Returns the connection's supported audio routes.
+ *
+ * @hide
+ */
+ public final int getSupportedAudioRoutes() {
+ return mSupportedAudioRoutes;
+ }
+
+ /**
* Sets the value of the {@link #getAddress()} property.
*
* @param address The new address.
@@ -1986,6 +1997,28 @@
}
/**
+ * Sets the supported audio routes.
+ *
+ * @param supportedAudioRoutes the supported audio routes as a bitmask.
+ * See {@link CallAudioState}
+ * @hide
+ */
+ public final void setSupportedAudioRoutes(int supportedAudioRoutes) {
+ if ((supportedAudioRoutes
+ & (CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER)) == 0) {
+ throw new IllegalArgumentException(
+ "supported audio routes must include either speaker or earpiece");
+ }
+
+ if (mSupportedAudioRoutes != supportedAudioRoutes) {
+ mSupportedAudioRoutes = supportedAudioRoutes;
+ for (Listener l : mListeners) {
+ l.onSupportedAudioRoutesChanged(this, mSupportedAudioRoutes);
+ }
+ }
+ }
+
+ /**
* Tears down the Connection object.
*/
public final void destroy() {
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index c2a0ff1..b119e16 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -1131,6 +1131,7 @@
connection.getState(),
connection.getConnectionCapabilities(),
connection.getConnectionProperties(),
+ connection.getSupportedAudioRoutes(),
connection.getAddress(),
connection.getAddressPresentation(),
connection.getCallerDisplayName(),
@@ -1530,6 +1531,7 @@
connection.getState(),
connection.getConnectionCapabilities(),
connection.getConnectionProperties(),
+ connection.getSupportedAudioRoutes(),
connection.getAddress(),
connection.getAddressPresentation(),
connection.getCallerDisplayName(),
diff --git a/telecomm/java/android/telecom/DefaultDialerManager.java b/telecomm/java/android/telecom/DefaultDialerManager.java
index a5e8fe1..cd65232 100644
--- a/telecomm/java/android/telecom/DefaultDialerManager.java
+++ b/telecomm/java/android/telecom/DefaultDialerManager.java
@@ -118,7 +118,7 @@
String defaultPackageName = Settings.Secure.getStringForUser(context.getContentResolver(),
Settings.Secure.DIALER_DEFAULT_APPLICATION, user);
- final List<String> packageNames = getInstalledDialerApplications(context);
+ final List<String> packageNames = getInstalledDialerApplications(context, user);
// Verify that the default dialer has not been disabled or uninstalled.
if (packageNames.contains(defaultPackageName)) {
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index 6860269..e6b567e 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -75,6 +75,14 @@
*/
public static final int CALL_PULLED = 12;
+ /**
+ * Reason code (returned via {@link #getReason()}) which indicates that a call could not be
+ * completed because the cellular radio is off or out of service, the device is connected to
+ * a wifi network, but the user has not enabled wifi calling.
+ * @hide
+ */
+ public static final String REASON_WIFI_ON_BUT_WFC_OFF = "REASON_WIFI_ON_BUT_WFC_OFF";
+
private int mDisconnectCode;
private CharSequence mDisconnectLabel;
private CharSequence mDisconnectDescription;
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index 1900cb9..a3fce9c 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -39,6 +39,7 @@
private final List<String> mCannedSmsResponses;
private final int mCapabilities;
private final int mProperties;
+ private final int mSupportedAudioRoutes;
private final long mConnectTimeMillis;
private final Uri mHandle;
private final int mHandlePresentation;
@@ -64,6 +65,7 @@
List<String> cannedSmsResponses,
int capabilities,
int properties,
+ int supportedAudioRoutes,
long connectTimeMillis,
Uri handle,
int handlePresentation,
@@ -86,6 +88,7 @@
mCannedSmsResponses = cannedSmsResponses;
mCapabilities = capabilities;
mProperties = properties;
+ mSupportedAudioRoutes = supportedAudioRoutes;
mConnectTimeMillis = connectTimeMillis;
mHandle = handle;
mHandlePresentation = handlePresentation;
@@ -137,6 +140,11 @@
/** Bitmask of properties of the call. */
public int getProperties() { return mProperties; }
+ /** Bitmask of supported routes of the call */
+ public int getSupportedAudioRoutes() {
+ return mSupportedAudioRoutes;
+ }
+
/** The time that the call switched to the active state. */
public long getConnectTimeMillis() {
return mConnectTimeMillis;
@@ -292,6 +300,7 @@
source.readList(conferenceableCallIds, classLoader);
Bundle intentExtras = source.readBundle(classLoader);
Bundle extras = source.readBundle(classLoader);
+ int supportedAudioRoutes = source.readInt();
return new ParcelableCall(
id,
state,
@@ -299,6 +308,7 @@
cannedSmsResponses,
capabilities,
properties,
+ supportedAudioRoutes,
connectTimeMillis,
handle,
handlePresentation,
@@ -355,6 +365,7 @@
destination.writeList(mConferenceableCallIds);
destination.writeBundle(mIntentExtras);
destination.writeBundle(mExtras);
+ destination.writeInt(mSupportedAudioRoutes);
}
@Override
diff --git a/telecomm/java/android/telecom/ParcelableConnection.java b/telecomm/java/android/telecom/ParcelableConnection.java
index 540f388..e9dba68 100644
--- a/telecomm/java/android/telecom/ParcelableConnection.java
+++ b/telecomm/java/android/telecom/ParcelableConnection.java
@@ -37,6 +37,7 @@
private final int mState;
private final int mConnectionCapabilities;
private final int mConnectionProperties;
+ private final int mSupportedAudioRoutes;
private final Uri mAddress;
private final int mAddressPresentation;
private final String mCallerDisplayName;
@@ -57,6 +58,7 @@
int state,
int capabilities,
int properties,
+ int supportedAudioRoutes,
Uri address,
int addressPresentation,
String callerDisplayName,
@@ -74,6 +76,7 @@
mState = state;
mConnectionCapabilities = capabilities;
mConnectionProperties = properties;
+ mSupportedAudioRoutes = supportedAudioRoutes;
mAddress = address;
mAddressPresentation = addressPresentation;
mCallerDisplayName = callerDisplayName;
@@ -117,6 +120,10 @@
return mConnectionProperties;
}
+ public int getSupportedAudioRoutes() {
+ return mSupportedAudioRoutes;
+ }
+
public Uri getHandle() {
return mAddress;
}
@@ -210,12 +217,14 @@
source.readStringList(conferenceableConnectionIds);
Bundle extras = Bundle.setDefusable(source.readBundle(classLoader), true);
int properties = source.readInt();
+ int supportedAudioRoutes = source.readInt();
return new ParcelableConnection(
phoneAccount,
state,
capabilities,
properties,
+ supportedAudioRoutes,
address,
addressPresentation,
callerDisplayName,
@@ -264,5 +273,6 @@
destination.writeStringList(mConferenceableConnectionIds);
destination.writeBundle(mExtras);
destination.writeInt(mConnectionProperties);
+ destination.writeInt(mSupportedAudioRoutes);
}
}
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 0457d63..ca54486 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -17,15 +17,6 @@
package android.telecom;
import android.annotation.SystemApi;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.Resources.NotFoundException;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Bundle;
@@ -37,7 +28,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.MissingResourceException;
/**
* Represents a distinct method to place or receive a phone call. Apps which can place calls and
@@ -237,6 +227,7 @@
private final CharSequence mLabel;
private final CharSequence mShortDescription;
private final List<String> mSupportedUriSchemes;
+ private final int mSupportedAudioRoutes;
private final Icon mIcon;
private final Bundle mExtras;
private boolean mIsEnabled;
@@ -246,10 +237,12 @@
* Helper class for creating a {@link PhoneAccount}.
*/
public static class Builder {
+
private PhoneAccountHandle mAccountHandle;
private Uri mAddress;
private Uri mSubscriptionAddress;
private int mCapabilities;
+ private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
private int mHighlightColor = NO_HIGHLIGHT_COLOR;
private CharSequence mLabel;
private CharSequence mShortDescription;
@@ -286,6 +279,7 @@
mIsEnabled = phoneAccount.isEnabled();
mExtras = phoneAccount.getExtras();
mGroupId = phoneAccount.getGroupId();
+ mSupportedAudioRoutes = phoneAccount.getSupportedAudioRoutes();
}
/**
@@ -431,6 +425,18 @@
}
/**
+ * Sets the audio routes supported by this {@link PhoneAccount}.
+ *
+ * @param routes bit mask of available routes.
+ * @return The builder.
+ * @hide
+ */
+ public Builder setSupportedAudioRoutes(int routes) {
+ mSupportedAudioRoutes = routes;
+ return this;
+ }
+
+ /**
* Creates an instance of a {@link PhoneAccount} based on the current builder settings.
*
* @return The {@link PhoneAccount}.
@@ -452,6 +458,7 @@
mShortDescription,
mSupportedUriSchemes,
mExtras,
+ mSupportedAudioRoutes,
mIsEnabled,
mGroupId);
}
@@ -468,6 +475,7 @@
CharSequence shortDescription,
List<String> supportedUriSchemes,
Bundle extras,
+ int supportedAudioRoutes,
boolean isEnabled,
String groupId) {
mAccountHandle = account;
@@ -480,6 +488,7 @@
mShortDescription = shortDescription;
mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
mExtras = extras;
+ mSupportedAudioRoutes = supportedAudioRoutes;
mIsEnabled = isEnabled;
mGroupId = groupId;
}
@@ -553,6 +562,17 @@
}
/**
+ * Determines if this {@code PhoneAccount} has routes specified by the passed in bit mask.
+ *
+ * @param route The routes to check.
+ * @return {@code true} if the phone account has the routes.
+ * @hide
+ */
+ public boolean hasAudioRoutes(int routes) {
+ return (mSupportedAudioRoutes & routes) == routes;
+ }
+
+ /**
* A short label describing a {@code PhoneAccount}.
*
* @return A label for this {@code PhoneAccount}.
@@ -592,6 +612,15 @@
}
/**
+ * The audio routes supported by this {@code PhoneAccount}.
+ *
+ * @hide
+ */
+ public int getSupportedAudioRoutes() {
+ return mSupportedAudioRoutes;
+ }
+
+ /**
* The icon to represent this {@code PhoneAccount}.
*
* @return The icon.
@@ -707,6 +736,7 @@
out.writeByte((byte) (mIsEnabled ? 1 : 0));
out.writeBundle(mExtras);
out.writeString(mGroupId);
+ out.writeInt(mSupportedAudioRoutes);
}
public static final Creator<PhoneAccount> CREATOR
@@ -751,6 +781,7 @@
mIsEnabled = in.readByte() == 1;
mExtras = in.readBundle();
mGroupId = in.readString();
+ mSupportedAudioRoutes = in.readInt();
}
@Override
@@ -760,7 +791,9 @@
.append("] PhoneAccount: ")
.append(mAccountHandle)
.append(" Capabilities: ")
- .append(capabilitiesToString(mCapabilities))
+ .append(capabilitiesToString())
+ .append(" Audio Routes: ")
+ .append(audioRoutesToString())
.append(" Schemes: ");
for (String scheme : mSupportedUriSchemes) {
sb.append(scheme)
@@ -780,7 +813,7 @@
* @param capabilities The capabilities bitmask.
* @return String representation of the capabilities bitmask.
*/
- private String capabilitiesToString(int capabilities) {
+ private String capabilitiesToString() {
StringBuilder sb = new StringBuilder();
if (hasCapabilities(CAPABILITY_SUPPORTS_VIDEO_CALLING)) {
sb.append("SuppVideo ");
@@ -817,4 +850,23 @@
}
return sb.toString();
}
+
+ private String audioRoutesToString() {
+ StringBuilder sb = new StringBuilder();
+
+ if (hasAudioRoutes(CallAudioState.ROUTE_BLUETOOTH)) {
+ sb.append("B");
+ }
+ if (hasAudioRoutes(CallAudioState.ROUTE_EARPIECE)) {
+ sb.append("E");
+ }
+ if (hasAudioRoutes(CallAudioState.ROUTE_SPEAKER)) {
+ sb.append("S");
+ }
+ if (hasAudioRoutes(CallAudioState.ROUTE_WIRED_HEADSET)) {
+ sb.append("W");
+ }
+
+ return sb.toString();
+ }
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index d6a88e8..5e28734 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -73,6 +73,15 @@
KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
/**
+ * When checking if a given number is the voicemail number, if this flag is true
+ * then in addition to comparing the given number to the voicemail number, we also compare it
+ * to the mdn. If this flag is false, the given number is only compared to the voicemail number.
+ * By default this value is false.
+ */
+ public static final String KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL =
+ "mdn_is_additional_voicemail_number_bool";
+
+ /**
* Flag indicating whether the Phone app should provide a "Dismiss" button on the SIM network
* unlock screen. The default value is true. If set to false, there will be *no way* to dismiss
* the SIM network unlock screen if you don't enter the correct unlock code. (One important
@@ -156,6 +165,14 @@
public static final String
KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
+ /**
+ * Control whether users receive a simplified network settings UI and improved network
+ * selection.
+ * @hide
+ */
+ public static final String
+ KEY_SIMPLIFIED_NETWORK_SETTINGS_BOOL = "simplified_network_settings_bool";
+
/** Control whether users can reach the SIM lock settings. */
public static final String
KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
@@ -649,6 +666,24 @@
public static final String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
/**
+ * Determines whether a maximum size limit for IMS conference calls is enforced on the device.
+ * When {@code true}, IMS conference calls will be limited to at most
+ * {@link #KEY_IMS_CONFERENCE_SIZE_LIMIT_INT} participants. When {@code false}, no attempt is made
+ * to limit the number of participants in a conference (the carrier will raise an error when an
+ * attempt is made to merge too many participants into a conference).
+ */
+ public static final String KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL =
+ "is_ims_conference_size_enforced_bool";
+
+ /**
+ * Determines the maximum number of participants the carrier supports for a conference call.
+ * This number is exclusive of the current device. A conference between 3 devices, for example,
+ * would have a size limit of 2 participants.
+ * Enforced when {@link #KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL} is {@code true}.
+ */
+ public static final String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int";
+
+ /**
* Determines whether High Definition audio property is displayed in the dialer UI.
* If {@code false}, remove the HD audio property from the connection so that HD audio related
* UI is not displayed. If {@code true}, keep HD audio property as it is configured.
@@ -1067,7 +1102,7 @@
* is returned.
* @hide
*/
- public static final String FILTERED_CNAP_NAMES_STRING_ARRAY = "filtered_cnap_names_string_array";
+ public static final String KEY_FILTERED_CNAP_NAMES_STRING_ARRAY = "filtered_cnap_names_string_array";
/**
* The RCS configuration server URL. This URL is used to initiate RCS provisioning.
@@ -1103,6 +1138,14 @@
*/
public static final String KEY_CARRIER_WIFI_STRING_ARRAY = "carrier_wifi_string_array";
+ /**
+ * Time delay (in ms) after which we show the notification to switch the preferred
+ * network.
+ * @hide
+ */
+ public static final String KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT =
+ "network_notification_delay_int";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -1144,10 +1187,12 @@
sDefaults.putBoolean(KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL, true);
sDefaults.putBoolean(KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL, false);
sDefaults.putBoolean(KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+ sDefaults.putBoolean(KEY_SIMPLIFIED_NETWORK_SETTINGS_BOOL, false);
sDefaults.putBoolean(KEY_HIDE_SIM_LOCK_SETTINGS_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONED_BOOL, false);
sDefaults.putBoolean(KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL, false);
+ sDefaults.putBoolean(KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL, false);
sDefaults.putBoolean(KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
sDefaults.putBoolean(KEY_PREFER_2G_BOOL, true);
sDefaults.putBoolean(KEY_SHOW_APN_SETTING_CDMA_BOOL, false);
@@ -1222,6 +1267,8 @@
sDefaults.putInt(KEY_CDMA_3WAYCALL_FLASH_DELAY_INT , 0);
sDefaults.putBoolean(KEY_SUPPORT_CONFERENCE_CALL_BOOL, true);
sDefaults.putBoolean(KEY_SUPPORT_VIDEO_CONFERENCE_CALL_BOOL, false);
+ sDefaults.putBoolean(KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL, false);
+ sDefaults.putInt(KEY_IMS_CONFERENCE_SIZE_LIMIT_INT, 5);
sDefaults.putBoolean(KEY_DISPLAY_HD_AUDIO_PROPERTY_BOOL, true);
sDefaults.putBoolean(KEY_EDITABLE_ENHANCED_4G_LTE_BOOL, true);
sDefaults.putBoolean(KEY_HIDE_IMS_APN_BOOL, false);
@@ -1296,11 +1343,12 @@
sDefaults.putStringArray(KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL, false);
sDefaults.putBoolean(KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL, false);
- sDefaults.putStringArray(FILTERED_CNAP_NAMES_STRING_ARRAY, null);
+ sDefaults.putStringArray(KEY_FILTERED_CNAP_NAMES_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
sDefaults.putBoolean(KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL, false);
sDefaults.putBoolean(KEY_PERSIST_LPP_MODE_BOOL, false);
sDefaults.putStringArray(KEY_CARRIER_WIFI_STRING_ARRAY, null);
+ sDefaults.putInt(KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT, -1);
}
/**
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 152b868..6f51c6e 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -29,6 +29,7 @@
import android.location.CountryDetector;
import android.net.Uri;
import android.os.SystemProperties;
+import android.os.PersistableBundle;
import android.provider.Contacts;
import android.provider.ContactsContract;
import android.telecom.PhoneAccount;
@@ -2106,7 +2107,7 @@
* number provided by the RIL and SIM card. The caller must have
* the READ_PHONE_STATE credential.
*
- * @param context a non-null {@link Context}.
+ * @param context {@link Context}.
* @param subId the subscription id of the SIM.
* @param number the number to look up.
* @return true if the number is in the list of voicemail. False
@@ -2115,25 +2116,54 @@
* @hide
*/
public static boolean isVoiceMailNumber(Context context, int subId, String number) {
- String vmNumber;
+ String vmNumber, mdn;
try {
final TelephonyManager tm;
if (context == null) {
tm = TelephonyManager.getDefault();
+ if (DBG) log("isVoiceMailNumber: default tm");
} else {
tm = TelephonyManager.from(context);
+ if (DBG) log("isVoiceMailNumber: tm from context");
}
vmNumber = tm.getVoiceMailNumber(subId);
+ mdn = tm.getLine1Number(subId);
+ if (DBG) log("isVoiceMailNumber: mdn=" + mdn + ", vmNumber=" + vmNumber
+ + ", number=" + number);
} catch (SecurityException ex) {
+ if (DBG) log("isVoiceMailNumber: SecurityExcpetion caught");
return false;
}
// Strip the separators from the number before comparing it
// to the list.
number = extractNetworkPortionAlt(number);
+ if (TextUtils.isEmpty(number)) {
+ if (DBG) log("isVoiceMailNumber: number is empty after stripping");
+ return false;
+ }
- // compare tolerates null so we need to make sure that we
- // don't return true when both are null.
- return !TextUtils.isEmpty(number) && compare(number, vmNumber);
+ // check if the carrier considers MDN to be an additional voicemail number
+ boolean compareWithMdn = false;
+ if (context != null) {
+ CarrierConfigManager configManager = (CarrierConfigManager)
+ context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (configManager != null) {
+ PersistableBundle b = configManager.getConfigForSubId(subId);
+ if (b != null) {
+ compareWithMdn = b.getBoolean(CarrierConfigManager.
+ KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL);
+ if (DBG) log("isVoiceMailNumber: compareWithMdn=" + compareWithMdn);
+ }
+ }
+ }
+
+ if (compareWithMdn) {
+ if (DBG) log("isVoiceMailNumber: treating mdn as additional vm number");
+ return compare(number, vmNumber) || compare(number, mdn);
+ } else {
+ if (DBG) log("isVoiceMailNumber: returning regular compare");
+ return compare(number, vmNumber);
+ }
}
/**
diff --git a/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl b/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
index 39e83c6..0da27e1 100644
--- a/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
+++ b/telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl
@@ -43,7 +43,7 @@
oneway interface IImsVideoCallProvider {
void setCallback(IImsVideoCallCallback callback);
- void setCamera(String cameraId);
+ void setCamera(String cameraId, int uid);
void setPreviewSurface(in Surface surface);
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index d4104bd..20c303e 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -438,7 +438,7 @@
// check to see if these are recognized numbers, and use shortcuts if we can.
if (PhoneNumberUtils.isLocalEmergencyNumber(context, number)) {
cw.event = EVENT_EMERGENCY_NUMBER;
- } else if (PhoneNumberUtils.isVoiceMailNumber(subId, number)) {
+ } else if (PhoneNumberUtils.isVoiceMailNumber(context, subId, number)) {
cw.event = EVENT_VOICEMAIL_NUMBER;
} else {
cw.event = EVENT_NEW_QUERY;
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 6115656..fe37531 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -447,4 +447,16 @@
void sendStoredMultipartText(int subId, String callingPkg, in Uri messageUri,
String scAddress, in List<PendingIntent> sentIntents,
in List<PendingIntent> deliveryIntents);
+
+ /**
+ * Create an app-only incoming SMS request for the calling package.
+ *
+ * If an incoming text contains the token returned by this method the provided
+ * <code>PendingIntent</code> will be sent containing the SMS data.
+ *
+ * @param subId the SIM id.
+ * @param callingPkg the package name of the calling app.
+ * @param intent PendingIntent to be sent when an SMS is received containing the token.
+ */
+ String createAppSpecificSmsToken(int subId, String callingPkg, in PendingIntent intent);
}
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index 68bde35..0e9a485 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -20,8 +20,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := core-oj core-libart core-junit framework
-LOCAL_STATIC_JAVA_LIBRARIES := junit-runner
+LOCAL_JAVA_LIBRARIES := core-oj core-libart junit framework
LOCAL_MODULE:= android.test.runner
diff --git a/test-runner/src/android/test/mock/MockContentProvider.java b/test-runner/src/android/test/mock/MockContentProvider.java
index e443911..d5f3ce8 100644
--- a/test-runner/src/android/test/mock/MockContentProvider.java
+++ b/test-runner/src/android/test/mock/MockContentProvider.java
@@ -16,6 +16,7 @@
package android.test.mock;
+import android.annotation.Nullable;
import android.content.ContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
@@ -97,11 +98,11 @@
}
@Override
- public Cursor query(String callingPackage, Uri url, String[] projection, String selection,
- String[] selectionArgs,
- String sortOrder, ICancellationSignal cancellationSignal) throws RemoteException {
- return MockContentProvider.this.query(url, projection, selection,
- selectionArgs, sortOrder);
+ public Cursor query(String callingPackage, Uri url, @Nullable String[] projection,
+ @Nullable Bundle queryArgs,
+ @Nullable ICancellationSignal cancellationSignal)
+ throws RemoteException {
+ return MockContentProvider.this.query(url, projection, queryArgs, null);
}
@Override
@@ -248,10 +249,12 @@
throw new UnsupportedOperationException("unimplemented mock method call");
}
+ @Override
public String[] getStreamTypes(Uri url, String mimeTypeFilter) {
throw new UnsupportedOperationException("unimplemented mock method call");
}
+ @Override
public AssetFileDescriptor openTypedAssetFile(Uri url, String mimeType, Bundle opts) {
throw new UnsupportedOperationException("unimplemented mock method call");
}
diff --git a/test-runner/src/android/test/mock/MockIContentProvider.java b/test-runner/src/android/test/mock/MockIContentProvider.java
index 09d45d1..112d7ee 100644
--- a/test-runner/src/android/test/mock/MockIContentProvider.java
+++ b/test-runner/src/android/test/mock/MockIContentProvider.java
@@ -16,6 +16,7 @@
package android.test.mock;
+import android.annotation.Nullable;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentValues;
@@ -41,45 +42,52 @@
* @hide - @hide because this exposes bulkQuery() and call(), which must also be hidden.
*/
public class MockIContentProvider implements IContentProvider {
+ @Override
public int bulkInsert(String callingPackage, Uri url, ContentValues[] initialValues) {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
@SuppressWarnings("unused")
public int delete(String callingPackage, Uri url, String selection, String[] selectionArgs)
throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public String getType(Uri url) {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
@SuppressWarnings("unused")
public Uri insert(String callingPackage, Uri url, ContentValues initialValues)
throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public ParcelFileDescriptor openFile(
String callingPackage, Uri url, String mode, ICancellationSignal signal,
IBinder callerToken) {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public AssetFileDescriptor openAssetFile(
String callingPackage, Uri uri, String mode, ICancellationSignal signal) {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public ContentProviderResult[] applyBatch(String callingPackage,
ArrayList<ContentProviderOperation> operations) {
throw new UnsupportedOperationException("unimplemented mock method");
}
- public Cursor query(String callingPackage, Uri url, String[] projection, String selection,
- String[] selectionArgs,
- String sortOrder, ICancellationSignal cancellationSignal) {
+ @Override
+ public Cursor query(String callingPackage, Uri url, @Nullable String[] projection,
+ @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -88,24 +96,29 @@
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public int update(String callingPackage, Uri url, ContentValues values, String selection,
String[] selectionArgs) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public Bundle call(String callingPackage, String method, String request, Bundle args)
throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public IBinder asBinder() {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
+ @Override
public AssetFileDescriptor openTypedAssetFile(String callingPackage, Uri url, String mimeType,
Bundle opts, ICancellationSignal signal) throws RemoteException, FileNotFoundException {
throw new UnsupportedOperationException("unimplemented mock method");
diff --git a/test-runner/src/junit/MODULE_LICENSE_CPL b/test-runner/src/junit/MODULE_LICENSE_CPL
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test-runner/src/junit/MODULE_LICENSE_CPL
diff --git a/test-runner/src/junit/README.android b/test-runner/src/junit/README.android
new file mode 100644
index 0000000..1384a1f
--- /dev/null
+++ b/test-runner/src/junit/README.android
@@ -0,0 +1,11 @@
+URL: https://github.com/junit-team/junit4
+License: Common Public License Version 1.0
+License File: cpl-v10.html
+
+This is JUnit 4.10 source that was previously part of the Android Public API.
+Where necessary it has been patched to be compatible (according to Android API
+requirements) with JUnit 3.8.
+
+These are copied here to ensure that the android.test.runner target remains
+compatible with the last version of the Android API (25) that contained these
+classes even when external/junit is upgraded to a later version.
diff --git a/test-runner/src/junit/cpl-v10.html b/test-runner/src/junit/cpl-v10.html
new file mode 100644
index 0000000..36aa208
--- /dev/null
+++ b/test-runner/src/junit/cpl-v10.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Common Public License - v 1.0</TITLE>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</HEAD>
+
+<BODY BGCOLOR="#FFFFFF" VLINK="#800000">
+
+
+<P ALIGN="CENTER"><B>Common Public License - v 1.0</B>
+<P><B></B><FONT SIZE="3"></FONT>
+<P><FONT SIZE="3"></FONT><FONT SIZE="2">THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"><B>1. DEFINITIONS</B></FONT>
+<P><FONT SIZE="2">"Contribution" means:</FONT>
+
+<UL><FONT SIZE="2">a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and<BR CLEAR="LEFT">
+b) in the case of each subsequent Contributor:</FONT></UL>
+
+
+<UL><FONT SIZE="2">i) changes to the Program, and</FONT></UL>
+
+
+<UL><FONT SIZE="2">ii) additions to the Program;</FONT></UL>
+
+
+<UL><FONT SIZE="2">where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. </FONT><FONT SIZE="2">A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. </FONT><FONT SIZE="2">Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. </FONT></UL>
+
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">"Contributor" means any person or entity that distributes the Program.</FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. </FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">"Program" means the Contributions distributed in accordance with this Agreement.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.</FONT>
+<P><FONT SIZE="2"><B></B></FONT>
+<P><FONT SIZE="2"><B>2. GRANT OF RIGHTS</B></FONT>
+
+<UL><FONT SIZE="2"></FONT><FONT SIZE="2">a) </FONT><FONT SIZE="2">Subject to the terms of this Agreement, each Contributor hereby grants</FONT><FONT SIZE="2"> Recipient a non-exclusive, worldwide, royalty-free copyright license to</FONT><FONT SIZE="2" COLOR="#FF0000"> </FONT><FONT SIZE="2">reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.</FONT></UL>
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+
+<UL><FONT SIZE="2"></FONT><FONT SIZE="2">b) Subject to the terms of this Agreement, each Contributor hereby grants </FONT><FONT SIZE="2">Recipient a non-exclusive, worldwide,</FONT><FONT SIZE="2" COLOR="#008000"> </FONT><FONT SIZE="2">royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. </FONT></UL>
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+
+<UL><FONT SIZE="2">c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.</FONT></UL>
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+
+<UL><FONT SIZE="2">d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. </FONT></UL>
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+<P><FONT SIZE="2"><B>3. REQUIREMENTS</B></FONT>
+<P><FONT SIZE="2"><B></B>A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:</FONT>
+
+<UL><FONT SIZE="2">a) it complies with the terms and conditions of this Agreement; and</FONT></UL>
+
+
+<UL><FONT SIZE="2">b) its license agreement:</FONT></UL>
+
+
+<UL><FONT SIZE="2">i) effectively disclaims</FONT><FONT SIZE="2"> on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; </FONT></UL>
+
+
+<UL><FONT SIZE="2">ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; </FONT></UL>
+
+
+<UL><FONT SIZE="2">iii)</FONT><FONT SIZE="2"> states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and</FONT></UL>
+
+
+<UL><FONT SIZE="2">iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.</FONT><FONT SIZE="2" COLOR="#0000FF"> </FONT><FONT SIZE="2" COLOR="#FF0000"></FONT></UL>
+
+
+<UL><FONT SIZE="2" COLOR="#FF0000"></FONT><FONT SIZE="2"></FONT></UL>
+
+<P><FONT SIZE="2">When the Program is made available in source code form:</FONT>
+
+<UL><FONT SIZE="2">a) it must be made available under this Agreement; and </FONT></UL>
+
+
+<UL><FONT SIZE="2">b) a copy of this Agreement must be included with each copy of the Program. </FONT></UL>
+
+<P><FONT SIZE="2"></FONT><FONT SIZE="2" COLOR="#0000FF"><STRIKE></STRIKE></FONT>
+<P><FONT SIZE="2" COLOR="#0000FF"><STRIKE></STRIKE></FONT><FONT SIZE="2">Contributors may not remove or alter any copyright notices contained within the Program. </FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. </FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"><B>4. COMMERCIAL DISTRIBUTION</B></FONT>
+<P><FONT SIZE="2">Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.</FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2" COLOR="#0000FF"></FONT>
+<P><FONT SIZE="2" COLOR="#0000FF"></FONT><FONT SIZE="2"><B>5. NO WARRANTY</B></FONT>
+<P><FONT SIZE="2">EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is</FONT><FONT SIZE="2"> solely responsible for determining the appropriateness of using and distributing </FONT><FONT SIZE="2">the Program</FONT><FONT SIZE="2"> and assumes all risks associated with its exercise of rights under this Agreement</FONT><FONT SIZE="2">, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, </FONT><FONT SIZE="2">programs or equipment, and unavailability or interruption of operations</FONT><FONT SIZE="2">. </FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"><B>6. DISCLAIMER OF LIABILITY</B></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES </FONT><FONT SIZE="2">(INCLUDING WITHOUT LIMITATION LOST PROFITS),</FONT><FONT SIZE="2"> HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"><B>7. GENERAL</B></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. </FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. </FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to </FONT><FONT SIZE="2">publish new versions (including revisions) of this Agreement from time to </FONT><FONT SIZE="2">time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. </FONT><FONT SIZE="2">Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new </FONT><FONT SIZE="2">version. </FONT><FONT SIZE="2">Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, </FONT><FONT SIZE="2">by implication, estoppel or otherwise</FONT><FONT SIZE="2">.</FONT><FONT SIZE="2"> All rights in the Program not expressly granted under this Agreement are reserved.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.</FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT>
+
+</BODY>
+
+</HTML>
\ No newline at end of file
diff --git a/test-runner/src/junit/runner/BaseTestRunner.java b/test-runner/src/junit/runner/BaseTestRunner.java
new file mode 100644
index 0000000..e7e0431
--- /dev/null
+++ b/test-runner/src/junit/runner/BaseTestRunner.java
@@ -0,0 +1,340 @@
+package junit.runner;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.text.NumberFormat;
+import java.util.Properties;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestListener;
+import junit.framework.TestSuite;
+
+/**
+ * Base class for all test runners.
+ * This class was born live on stage in Sardinia during XP2000.
+ */
+public abstract class BaseTestRunner implements TestListener {
+ public static final String SUITE_METHODNAME= "suite";
+
+ private static Properties fPreferences;
+ static int fgMaxMessageLength= 500;
+ static boolean fgFilterStack= true;
+ boolean fLoading= true;
+
+ /*
+ * Implementation of TestListener
+ */
+ public synchronized void startTest(Test test) {
+ testStarted(test.toString());
+ }
+
+ protected static void setPreferences(Properties preferences) {
+ fPreferences= preferences;
+ }
+
+ protected static Properties getPreferences() {
+ if (fPreferences == null) {
+ fPreferences= new Properties();
+ fPreferences.put("loading", "true");
+ fPreferences.put("filterstack", "true");
+ readPreferences();
+ }
+ return fPreferences;
+ }
+
+ public static void savePreferences() throws IOException {
+ FileOutputStream fos= new FileOutputStream(getPreferencesFile());
+ try {
+ getPreferences().store(fos, "");
+ } finally {
+ fos.close();
+ }
+ }
+
+ // android-changed remove 'static' qualifier for API compatibility
+ public void setPreference(String key, String value) {
+ getPreferences().put(key, value);
+ }
+
+ public synchronized void endTest(Test test) {
+ testEnded(test.toString());
+ }
+
+ public synchronized void addError(final Test test, final Throwable t) {
+ testFailed(TestRunListener.STATUS_ERROR, test, t);
+ }
+
+ public synchronized void addFailure(final Test test, final AssertionFailedError t) {
+ testFailed(TestRunListener.STATUS_FAILURE, test, t);
+ }
+
+ // TestRunListener implementation
+
+ public abstract void testStarted(String testName);
+
+ public abstract void testEnded(String testName);
+
+ public abstract void testFailed(int status, Test test, Throwable t);
+
+ /**
+ * Returns the Test corresponding to the given suite. This is
+ * a template method, subclasses override runFailed(), clearStatus().
+ */
+ public Test getTest(String suiteClassName) {
+ if (suiteClassName.length() <= 0) {
+ clearStatus();
+ return null;
+ }
+ Class<?> testClass= null;
+ try {
+ testClass= loadSuiteClass(suiteClassName);
+ } catch (ClassNotFoundException e) {
+ String clazz= e.getMessage();
+ if (clazz == null)
+ clazz= suiteClassName;
+ runFailed("Class not found \""+clazz+"\"");
+ return null;
+ } catch(Exception e) {
+ runFailed("Error: "+e.toString());
+ return null;
+ }
+ Method suiteMethod= null;
+ try {
+ suiteMethod= testClass.getMethod(SUITE_METHODNAME, new Class[0]);
+ } catch(Exception e) {
+ // try to extract a test suite automatically
+ clearStatus();
+ return new TestSuite(testClass);
+ }
+ if (! Modifier.isStatic(suiteMethod.getModifiers())) {
+ runFailed("Suite() method must be static");
+ return null;
+ }
+ Test test= null;
+ try {
+ test= (Test)suiteMethod.invoke(null, (Object[])new Class[0]); // static method
+ if (test == null)
+ return test;
+ }
+ catch (InvocationTargetException e) {
+ runFailed("Failed to invoke suite():" + e.getTargetException().toString());
+ return null;
+ }
+ catch (IllegalAccessException e) {
+ runFailed("Failed to invoke suite():" + e.toString());
+ return null;
+ }
+
+ clearStatus();
+ return test;
+ }
+
+ /**
+ * Returns the formatted string of the elapsed time.
+ */
+ public String elapsedTimeAsString(long runTime) {
+ return NumberFormat.getInstance().format((double)runTime/1000);
+ }
+
+ /**
+ * Processes the command line arguments and
+ * returns the name of the suite class to run or null
+ */
+ protected String processArguments(String[] args) {
+ String suiteName= null;
+ for (int i= 0; i < args.length; i++) {
+ if (args[i].equals("-noloading")) {
+ setLoading(false);
+ } else if (args[i].equals("-nofilterstack")) {
+ fgFilterStack= false;
+ } else if (args[i].equals("-c")) {
+ if (args.length > i+1)
+ suiteName= extractClassName(args[i+1]);
+ else
+ System.out.println("Missing Test class name");
+ i++;
+ } else {
+ suiteName= args[i];
+ }
+ }
+ return suiteName;
+ }
+
+ /**
+ * Sets the loading behaviour of the test runner
+ */
+ public void setLoading(boolean enable) {
+ fLoading= enable;
+ }
+ /**
+ * Extract the class name from a String in VA/Java style
+ */
+ public String extractClassName(String className) {
+ if(className.startsWith("Default package for"))
+ return className.substring(className.lastIndexOf(".")+1);
+ return className;
+ }
+
+ /**
+ * Truncates a String to the maximum length.
+ */
+ public static String truncate(String s) {
+ if (fgMaxMessageLength != -1 && s.length() > fgMaxMessageLength)
+ s= s.substring(0, fgMaxMessageLength)+"...";
+ return s;
+ }
+
+ /**
+ * Override to define how to handle a failed loading of
+ * a test suite.
+ */
+ protected abstract void runFailed(String message);
+
+ // BEGIN android-changed - add back getLoader() for API compatibility
+ /**
+ * Returns the loader to be used.
+ *
+ * @deprecated not present in JUnit4.10
+ */
+ public TestSuiteLoader getLoader() {
+ return new StandardTestSuiteLoader();
+ }
+ // END android-changed
+
+ /**
+ * Returns the loaded Class for a suite name.
+ */
+ protected Class<?> loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
+ return Class.forName(suiteClassName);
+ }
+
+ /**
+ * Clears the status message.
+ */
+ protected void clearStatus() { // Belongs in the GUI TestRunner class
+ }
+
+ protected boolean useReloadingTestSuiteLoader() {
+ return getPreference("loading").equals("true") && fLoading;
+ }
+
+ private static File getPreferencesFile() {
+ String home= System.getProperty("user.home");
+ return new File(home, "junit.properties");
+ }
+
+ private static void readPreferences() {
+ InputStream is= null;
+ try {
+ is= new FileInputStream(getPreferencesFile());
+ setPreferences(new Properties(getPreferences()));
+ getPreferences().load(is);
+ } catch (IOException e) {
+ try {
+ if (is != null)
+ is.close();
+ } catch (IOException e1) {
+ }
+ }
+ }
+
+ public static String getPreference(String key) {
+ return getPreferences().getProperty(key);
+ }
+
+ public static int getPreference(String key, int dflt) {
+ String value= getPreference(key);
+ int intValue= dflt;
+ if (value == null)
+ return intValue;
+ try {
+ intValue= Integer.parseInt(value);
+ } catch (NumberFormatException ne) {
+ }
+ return intValue;
+ }
+
+ /**
+ * Returns a filtered stack trace
+ */
+ public static String getFilteredTrace(Throwable t) {
+ StringWriter stringWriter= new StringWriter();
+ PrintWriter writer= new PrintWriter(stringWriter);
+ t.printStackTrace(writer);
+ StringBuffer buffer= stringWriter.getBuffer();
+ String trace= buffer.toString();
+ return BaseTestRunner.getFilteredTrace(trace);
+ }
+
+ // BEGIN android-changed - add back this method for API compatibility
+ /** @deprecated not present in JUnit4.10 */
+ public static boolean inVAJava() {
+ return false;
+ }
+ // END android-changed
+
+ /**
+ * Filters stack frames from internal JUnit classes
+ */
+ public static String getFilteredTrace(String stack) {
+ if (showStackRaw())
+ return stack;
+
+ StringWriter sw= new StringWriter();
+ PrintWriter pw= new PrintWriter(sw);
+ StringReader sr= new StringReader(stack);
+ // BEGIN android-changed
+ // Use a sensible default buffer size
+ BufferedReader br= new BufferedReader(sr, 1000);
+ // END android-changed
+
+ String line;
+ try {
+ while ((line= br.readLine()) != null) {
+ if (!filterLine(line))
+ pw.println(line);
+ }
+ } catch (Exception IOException) {
+ return stack; // return the stack unfiltered
+ }
+ return sw.toString();
+ }
+
+ protected static boolean showStackRaw() {
+ return !getPreference("filterstack").equals("true") || fgFilterStack == false;
+ }
+
+ static boolean filterLine(String line) {
+ String[] patterns= new String[] {
+ "junit.framework.TestCase",
+ "junit.framework.TestResult",
+ "junit.framework.TestSuite",
+ "junit.framework.Assert.", // don't filter AssertionFailure
+ "junit.swingui.TestRunner",
+ "junit.awtui.TestRunner",
+ "junit.textui.TestRunner",
+ "java.lang.reflect.Method.invoke("
+ };
+ for (int i= 0; i < patterns.length; i++) {
+ if (line.indexOf(patterns[i]) > 0)
+ return true;
+ }
+ return false;
+ }
+
+ static {
+ fgMaxMessageLength= getPreference("maxmessage", fgMaxMessageLength);
+ }
+
+}
diff --git a/test-runner/src/junit/runner/StandardTestSuiteLoader.java b/test-runner/src/junit/runner/StandardTestSuiteLoader.java
new file mode 100644
index 0000000..808963a
--- /dev/null
+++ b/test-runner/src/junit/runner/StandardTestSuiteLoader.java
@@ -0,0 +1,23 @@
+package junit.runner;
+
+// android-changed - class not present in upstream JUnit 4.10
+// added here to retain BaseTestRunner.getLoader API
+
+/**
+ * The standard test suite loader. It can only load the same class once.
+ * {@hide}
+ */
+public class StandardTestSuiteLoader implements TestSuiteLoader {
+ /**
+ * Uses the system class loader to load the test class
+ */
+ public Class load(String suiteClassName) throws ClassNotFoundException {
+ return Class.forName(suiteClassName);
+ }
+ /**
+ * Uses the system class loader to load the test class
+ */
+ public Class reload(Class aClass) throws ClassNotFoundException {
+ return aClass;
+ }
+}
diff --git a/test-runner/src/junit/runner/TestRunListener.java b/test-runner/src/junit/runner/TestRunListener.java
new file mode 100644
index 0000000..0e95819
--- /dev/null
+++ b/test-runner/src/junit/runner/TestRunListener.java
@@ -0,0 +1,20 @@
+package junit.runner;
+/**
+ * A listener interface for observing the
+ * execution of a test run. Unlike TestListener,
+ * this interface using only primitive objects,
+ * making it suitable for remote test execution.
+ * {@hide} - Not needed for 1.0 SDK
+ */
+ public interface TestRunListener {
+ /* test status constants*/
+ public static final int STATUS_ERROR= 1;
+ public static final int STATUS_FAILURE= 2;
+
+ public void testRunStarted(String testSuiteName, int testCount);
+ public void testRunEnded(long elapsedTime);
+ public void testRunStopped(long elapsedTime);
+ public void testStarted(String testName);
+ public void testEnded(String testName);
+ public void testFailed(int status, String testName, String trace);
+}
diff --git a/test-runner/src/junit/runner/TestSuiteLoader.java b/test-runner/src/junit/runner/TestSuiteLoader.java
new file mode 100644
index 0000000..9cc6d81
--- /dev/null
+++ b/test-runner/src/junit/runner/TestSuiteLoader.java
@@ -0,0 +1,11 @@
+package junit.runner;
+
+/**
+ * An interface to define how a test suite should be loaded.
+ *
+ */
+// TODO: deprecate
+public interface TestSuiteLoader {
+ abstract public Class load(String suiteClassName) throws ClassNotFoundException;
+ abstract public Class reload(Class aClass) throws ClassNotFoundException;
+}
diff --git a/test-runner/src/junit/runner/Version.java b/test-runner/src/junit/runner/Version.java
new file mode 100644
index 0000000..dd88c03
--- /dev/null
+++ b/test-runner/src/junit/runner/Version.java
@@ -0,0 +1,20 @@
+package junit.runner;
+
+/**
+ * This class defines the current version of JUnit
+ */
+public class Version {
+ private Version() {
+ // don't instantiate
+ }
+
+ public static String id() {
+ return "4.10";
+ }
+
+ // android-changed
+ /** @hide - not needed for public API */
+ public static void main(String[] args) {
+ System.out.println(id());
+ }
+}
diff --git a/test-runner/src/junit/runner/package-info.java b/test-runner/src/junit/runner/package-info.java
new file mode 100644
index 0000000..b746185
--- /dev/null
+++ b/test-runner/src/junit/runner/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Provides JUnit v3.x test runners.
+ */
+package junit.runner;
\ No newline at end of file
diff --git a/test-runner/src/junit/runner/package.html b/test-runner/src/junit/runner/package.html
new file mode 100644
index 0000000..f08fa70
--- /dev/null
+++ b/test-runner/src/junit/runner/package.html
@@ -0,0 +1,5 @@
+<HTML>
+<BODY>
+Utility classes supporting the junit test framework.
+</BODY>
+</HTML>
diff --git a/test-runner/src/junit/textui/ResultPrinter.java b/test-runner/src/junit/textui/ResultPrinter.java
new file mode 100644
index 0000000..b4914529
--- /dev/null
+++ b/test-runner/src/junit/textui/ResultPrinter.java
@@ -0,0 +1,144 @@
+
+package junit.textui;
+
+import java.io.PrintStream;
+// android-changed
+// The following line was removed for compatibility with Android libraries.
+// import java.text.NumberFormat;
+import java.util.Enumeration;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestFailure;
+import junit.framework.TestListener;
+import junit.framework.TestResult;
+import junit.runner.BaseTestRunner;
+
+public class ResultPrinter implements TestListener {
+ PrintStream fWriter;
+ int fColumn= 0;
+
+ public ResultPrinter(PrintStream writer) {
+ fWriter= writer;
+ }
+
+ /* API for use by textui.TestRunner
+ */
+
+ synchronized void print(TestResult result, long runTime) {
+ printHeader(runTime);
+ printErrors(result);
+ printFailures(result);
+ printFooter(result);
+ }
+
+ void printWaitPrompt() {
+ getWriter().println();
+ getWriter().println("<RETURN> to continue");
+ }
+
+ /* Internal methods
+ */
+
+ protected void printHeader(long runTime) {
+ getWriter().println();
+ getWriter().println("Time: "+elapsedTimeAsString(runTime));
+ }
+
+ protected void printErrors(TestResult result) {
+ printDefects(result.errors(), result.errorCount(), "error");
+ }
+
+ protected void printFailures(TestResult result) {
+ printDefects(result.failures(), result.failureCount(), "failure");
+ }
+
+ protected void printDefects(Enumeration<TestFailure> booBoos, int count, String type) {
+ if (count == 0) return;
+ if (count == 1)
+ getWriter().println("There was " + count + " " + type + ":");
+ else
+ getWriter().println("There were " + count + " " + type + "s:");
+ for (int i= 1; booBoos.hasMoreElements(); i++) {
+ printDefect(booBoos.nextElement(), i);
+ }
+ }
+
+ public void printDefect(TestFailure booBoo, int count) { // only public for testing purposes
+ printDefectHeader(booBoo, count);
+ printDefectTrace(booBoo);
+ }
+
+ protected void printDefectHeader(TestFailure booBoo, int count) {
+ // I feel like making this a println, then adding a line giving the throwable a chance to print something
+ // before we get to the stack trace.
+ getWriter().print(count + ") " + booBoo.failedTest());
+ }
+
+ protected void printDefectTrace(TestFailure booBoo) {
+ getWriter().print(BaseTestRunner.getFilteredTrace(booBoo.trace()));
+ }
+
+ protected void printFooter(TestResult result) {
+ if (result.wasSuccessful()) {
+ getWriter().println();
+ getWriter().print("OK");
+ getWriter().println (" (" + result.runCount() + " test" + (result.runCount() == 1 ? "": "s") + ")");
+
+ } else {
+ getWriter().println();
+ getWriter().println("FAILURES!!!");
+ getWriter().println("Tests run: "+result.runCount()+
+ ", Failures: "+result.failureCount()+
+ ", Errors: "+result.errorCount());
+ }
+ getWriter().println();
+ }
+
+
+ /**
+ * Returns the formatted string of the elapsed time.
+ * Duplicated from BaseTestRunner. Fix it.
+ */
+ protected String elapsedTimeAsString(long runTime) {
+ // android-changed
+ // The following line was altered for compatibility with
+ // Android libraries.
+ return Double.toString((double)runTime/1000);
+ }
+
+ public PrintStream getWriter() {
+ return fWriter;
+ }
+ /**
+ * @see junit.framework.TestListener#addError(Test, Throwable)
+ */
+ public void addError(Test test, Throwable t) {
+ getWriter().print("E");
+ }
+
+ /**
+ * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError)
+ */
+ public void addFailure(Test test, AssertionFailedError t) {
+ getWriter().print("F");
+ }
+
+ /**
+ * @see junit.framework.TestListener#endTest(Test)
+ */
+ public void endTest(Test test) {
+ }
+
+ /**
+ * @see junit.framework.TestListener#startTest(Test)
+ */
+ public void startTest(Test test) {
+ getWriter().print(".");
+ if (fColumn++ >= 40) {
+ getWriter().println();
+ fColumn= 0;
+ }
+ }
+
+}
diff --git a/test-runner/src/junit/textui/TestRunner.java b/test-runner/src/junit/textui/TestRunner.java
new file mode 100644
index 0000000..046448e
--- /dev/null
+++ b/test-runner/src/junit/textui/TestRunner.java
@@ -0,0 +1,203 @@
+package junit.textui;
+
+
+import java.io.PrintStream;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+import junit.runner.BaseTestRunner;
+import junit.runner.Version;
+
+/**
+ * A command line based tool to run tests.
+ * <pre>
+ * java junit.textui.TestRunner [-wait] TestCaseClass
+ * </pre>
+ *
+ * <p>TestRunner expects the name of a TestCase class as argument.
+ * If this class defines a static <code>suite</code> method it
+ * will be invoked and the returned test is run. Otherwise all
+ * the methods starting with "test" having no arguments are run.</p>
+ *
+ * <p> When the wait command line argument is given TestRunner
+ * waits until the users types RETURN.</p>
+ *
+ * <p>TestRunner prints a trace as the tests are executed followed by a
+ * summary at the end.</p>
+ */
+public class TestRunner extends BaseTestRunner {
+ private ResultPrinter fPrinter;
+
+ public static final int SUCCESS_EXIT= 0;
+ public static final int FAILURE_EXIT= 1;
+ public static final int EXCEPTION_EXIT= 2;
+
+ /**
+ * Constructs a TestRunner.
+ */
+ public TestRunner() {
+ this(System.out);
+ }
+
+ /**
+ * Constructs a TestRunner using the given stream for all the output
+ */
+ public TestRunner(PrintStream writer) {
+ this(new ResultPrinter(writer));
+ }
+
+ /**
+ * Constructs a TestRunner using the given ResultPrinter all the output
+ */
+ public TestRunner(ResultPrinter printer) {
+ fPrinter= printer;
+ }
+
+ /**
+ * Runs a suite extracted from a TestCase subclass.
+ */
+ static public void run(Class<? extends TestCase> testClass) {
+ run(new TestSuite(testClass));
+ }
+
+ /**
+ * Runs a single test and collects its results.
+ * This method can be used to start a test run
+ * from your program.
+ * <pre>
+ * public static void main (String[] args) {
+ * test.textui.TestRunner.run(suite());
+ * }
+ * </pre>
+ */
+ static public TestResult run(Test test) {
+ TestRunner runner= new TestRunner();
+ return runner.doRun(test);
+ }
+
+ /**
+ * Runs a single test and waits until the user
+ * types RETURN.
+ */
+ static public void runAndWait(Test suite) {
+ TestRunner aTestRunner= new TestRunner();
+ aTestRunner.doRun(suite, true);
+ }
+
+ @Override
+ public void testFailed(int status, Test test, Throwable t) {
+ }
+
+ @Override
+ public void testStarted(String testName) {
+ }
+
+ @Override
+ public void testEnded(String testName) {
+ }
+
+ /**
+ * Creates the TestResult to be used for the test run.
+ */
+ protected TestResult createTestResult() {
+ return new TestResult();
+ }
+
+ public TestResult doRun(Test test) {
+ return doRun(test, false);
+ }
+
+ public TestResult doRun(Test suite, boolean wait) {
+ TestResult result= createTestResult();
+ result.addListener(fPrinter);
+ long startTime= System.currentTimeMillis();
+ suite.run(result);
+ long endTime= System.currentTimeMillis();
+ long runTime= endTime-startTime;
+ fPrinter.print(result, runTime);
+
+ pause(wait);
+ return result;
+ }
+
+ protected void pause(boolean wait) {
+ if (!wait) return;
+ fPrinter.printWaitPrompt();
+ try {
+ System.in.read();
+ }
+ catch(Exception e) {
+ }
+ }
+
+ public static void main(String args[]) {
+ TestRunner aTestRunner= new TestRunner();
+ try {
+ TestResult r= aTestRunner.start(args);
+ if (!r.wasSuccessful())
+ System.exit(FAILURE_EXIT);
+ System.exit(SUCCESS_EXIT);
+ } catch(Exception e) {
+ System.err.println(e.getMessage());
+ System.exit(EXCEPTION_EXIT);
+ }
+ }
+
+ /**
+ * Starts a test run. Analyzes the command line arguments and runs the given
+ * test suite.
+ */
+ public TestResult start(String args[]) throws Exception {
+ String testCase= "";
+ String method= "";
+ boolean wait= false;
+
+ for (int i= 0; i < args.length; i++) {
+ if (args[i].equals("-wait"))
+ wait= true;
+ else if (args[i].equals("-c"))
+ testCase= extractClassName(args[++i]);
+ else if (args[i].equals("-m")) {
+ String arg= args[++i];
+ int lastIndex= arg.lastIndexOf('.');
+ testCase= arg.substring(0, lastIndex);
+ method= arg.substring(lastIndex + 1);
+ } else if (args[i].equals("-v"))
+ System.err.println("JUnit " + Version.id() + " by Kent Beck and Erich Gamma");
+ else
+ testCase= args[i];
+ }
+
+ if (testCase.equals(""))
+ throw new Exception("Usage: TestRunner [-wait] testCaseName, where name is the name of the TestCase class");
+
+ try {
+ if (!method.equals(""))
+ return runSingleMethod(testCase, method, wait);
+ Test suite= getTest(testCase);
+ return doRun(suite, wait);
+ } catch (Exception e) {
+ throw new Exception("Could not create and run test suite: " + e);
+ }
+ }
+
+ protected TestResult runSingleMethod(String testCase, String method, boolean wait) throws Exception {
+ Class<? extends TestCase> testClass= loadSuiteClass(testCase).asSubclass(TestCase.class);
+ Test test= TestSuite.createTest(testClass, method);
+ return doRun(test, wait);
+ }
+
+ @Override
+ protected void runFailed(String message) {
+ System.err.println(message);
+ System.exit(FAILURE_EXIT);
+ }
+
+ public void setPrinter(ResultPrinter printer) {
+ fPrinter= printer;
+ }
+
+
+}
\ No newline at end of file
diff --git a/test-runner/src/junit/textui/package-info.java b/test-runner/src/junit/textui/package-info.java
new file mode 100644
index 0000000..2dcc10c
--- /dev/null
+++ b/test-runner/src/junit/textui/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Provides JUnit v3.x command line based tool to run tests.
+ * {@hide}
+ */
+package junit.textui;
\ No newline at end of file
diff --git a/test-runner/src/junit/textui/package.html b/test-runner/src/junit/textui/package.html
new file mode 100644
index 0000000..723f2ae
--- /dev/null
+++ b/test-runner/src/junit/textui/package.html
@@ -0,0 +1,6 @@
+<HTML>
+<BODY>
+Utility classes supporting the junit test framework.
+{@hide} - Not needed for 1.0 SDK
+</BODY>
+</HTML>
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 3785cdc..b4f3d69 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -989,5 +989,15 @@
</intent-filter>
</activity>
+ <activity
+ android:name="PixelCopyWindow"
+ android:label="Readback/Window"
+ android:screenOrientation="fullSensor">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.test.hwui.TEST" />
+ </intent-filter>
+ </activity>
+
</application>
</manifest>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PixelCopyWindow.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PixelCopyWindow.java
new file mode 100644
index 0000000..a039fba
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PixelCopyWindow.java
@@ -0,0 +1,98 @@
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Paint.Style;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+import android.view.PixelCopy;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class PixelCopyWindow extends Activity {
+
+ private Handler mHandler;
+ private ImageView mImage;
+ private TextView mText;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mHandler = new Handler();
+
+ LinearLayout layout = new LinearLayout(this);
+ TextView text = new TextView(this);
+ text.setText("Hello, World!");
+ Button btn = new Button(this);
+ btn.setText("Screenshot!");
+ btn.setOnClickListener((v) -> takeScreenshot());
+ mImage = new ImageView(this);
+ mText = new TextView(this);
+
+ layout.setOrientation(LinearLayout.VERTICAL);
+ layout.addView(text);
+ layout.addView(btn);
+ layout.addView(mImage);
+ layout.addView(mText);
+ final float density = getResources().getDisplayMetrics().density;
+ layout.setBackground(new Drawable() {
+ Paint mPaint = new Paint();
+
+ @Override
+ public void draw(Canvas canvas) {
+ mPaint.setStyle(Style.STROKE);
+ mPaint.setStrokeWidth(4 * density);
+ mPaint.setColor(Color.BLUE);
+ final Rect bounds = getBounds();
+ canvas.drawRect(bounds, mPaint);
+ mPaint.setColor(Color.RED);
+ canvas.drawLine(bounds.centerX(), 0, bounds.centerX(), bounds.height(), mPaint);
+ mPaint.setColor(Color.GREEN);
+ canvas.drawLine(0, bounds.centerY(), bounds.width(), bounds.centerY(), mPaint);
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+ });
+ setContentView(layout);
+ }
+
+ private void takeScreenshot() {
+ View decor = getWindow().getDecorView();
+ Rect srcRect = new Rect();
+ decor.getGlobalVisibleRect(srcRect);
+ final Bitmap bitmap = Bitmap.createBitmap(
+ (int) (srcRect.width() * .25), (int) (srcRect.height() * .25), Config.ARGB_8888);
+ PixelCopy.request(getWindow(), srcRect, bitmap, (result) -> {
+ if (result != PixelCopy.SUCCESS) {
+ mText.setText("Copy failed, result: " + result);
+ mImage.setImageBitmap(null);
+ } else {
+ mText.setText("");
+ mImage.setImageBitmap(bitmap);
+ }
+ }, mHandler);
+ }
+}
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
index eda3f5e..dc3b337 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
@@ -227,7 +227,7 @@
public void testConfigBuilderUsesParents() throws Exception {
// Check that a builder with a parent uses the parent's values when non is set.
NetworkSecurityConfig config = new NetworkSecurityConfig.Builder()
- .setParent(NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N))
+ .setParent(NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N, false))
.build();
assert(!config.getTrustAnchors().isEmpty());
}
@@ -268,9 +268,9 @@
// Install the test CA.
store.installCertificate(TEST_CA_CERT);
NetworkSecurityConfig preNConfig =
- NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.M).build();
+ NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.M, false).build();
NetworkSecurityConfig nConfig =
- NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N).build();
+ NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N, false).build();
Set<TrustAnchor> preNAnchors = preNConfig.getTrustAnchors();
Set<TrustAnchor> nAnchors = nConfig.getTrustAnchors();
Set<X509Certificate> preNCerts = new HashSet<X509Certificate>();
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index 51adfe7..ff61754 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -661,9 +661,13 @@
// The IPv6 all nodes address ff02::1
private static final byte[] IPV6_ALL_NODES_ADDRESS =
{ (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+ private static final byte[] IPV6_ALL_ROUTERS_ADDRESS =
+ { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
+ private static final int ICMP6_ROUTER_SOLICITATION = 133;
private static final int ICMP6_ROUTER_ADVERTISEMENT = 134;
+ private static final int ICMP6_NEIGHBOR_SOLICITATION = 135;
private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
private static final int ICMP6_RA_HEADER_LEN = 16;
@@ -798,6 +802,12 @@
put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS);
assertDrop(program, packet.array());
+ // Verify ICMPv6 RS to any is dropped
+ packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION);
+ assertDrop(program, packet.array());
+ put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS);
+ assertDrop(program, packet.array());
+
apfFilter.shutdown();
}
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index 6a064d2..48d3159 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -39,13 +39,13 @@
import android.net.metrics.NetworkEvent;
import android.net.metrics.RaEvent;
import android.net.metrics.ValidationProbeEvent;
-
-import junit.framework.TestCase;
-
+import android.test.suitebuilder.annotation.SmallTest;
import java.util.Arrays;
+import junit.framework.TestCase;
public class IpConnectivityEventBuilderTest extends TestCase {
+ @SmallTest
public void testDefaultNetworkEventSerialization() {
ConnectivityMetricsEvent ev = describeIpEvent(
aType(DefaultNetworkEvent.class),
@@ -58,6 +58,8 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " time_ms: 1",
+ " transport: 0",
" default_network_event <",
" network_id <",
" network_id: 102",
@@ -70,13 +72,13 @@
" transport_types: 2",
" transport_types: 3",
" >",
- " time_ms: 1",
">",
"version: 2");
verifySerialization(want, ev);
}
+ @SmallTest
public void testDhcpClientEventSerialization() {
ConnectivityMetricsEvent ev = describeIpEvent(
aType(DhcpClientEvent.class),
@@ -87,19 +89,20 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " time_ms: 1",
+ " transport: 0",
" dhcp_event <",
" duration_ms: 192",
- " error_code: 0",
" if_name: \"wlan0\"",
" state_transition: \"SomeState\"",
" >",
- " time_ms: 1",
">",
"version: 2");
verifySerialization(want, ev);
}
+ @SmallTest
public void testDhcpErrorEventSerialization() {
ConnectivityMetricsEvent ev = describeIpEvent(
aType(DhcpErrorEvent.class),
@@ -109,19 +112,20 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " time_ms: 1",
+ " transport: 0",
" dhcp_event <",
" duration_ms: 0",
- " error_code: 50397184",
" if_name: \"wlan0\"",
- " state_transition: \"\"",
+ " error_code: 50397184",
" >",
- " time_ms: 1",
">",
"version: 2");
verifySerialization(want, ev);
}
+ @SmallTest
public void testDnsEventSerialization() {
ConnectivityMetricsEvent ev = describeIpEvent(
aType(DnsEvent.class),
@@ -133,6 +137,8 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " time_ms: 1",
+ " transport: 0",
" dns_lookup_batch <",
" event_types: 1",
" event_types: 1",
@@ -162,13 +168,13 @@
" return_codes: 200",
" return_codes: 178",
" >",
- " time_ms: 1",
">",
"version: 2");
verifySerialization(want, ev);
}
+ @SmallTest
public void testIpManagerEventSerialization() {
ConnectivityMetricsEvent ev = describeIpEvent(
aType(IpManagerEvent.class),
@@ -179,18 +185,20 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " time_ms: 1",
+ " transport: 0",
" ip_provisioning_event <",
" event_type: 1",
" if_name: \"wlan0\"",
" latency_ms: 5678",
" >",
- " time_ms: 1",
">",
"version: 2");
verifySerialization(want, ev);
}
+ @SmallTest
public void testIpReachabilityEventSerialization() {
ConnectivityMetricsEvent ev = describeIpEvent(
aType(IpReachabilityEvent.class),
@@ -200,17 +208,19 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " time_ms: 1",
+ " transport: 0",
" ip_reachability_event <",
" event_type: 512",
" if_name: \"wlan0\"",
" >",
- " time_ms: 1",
">",
"version: 2");
verifySerialization(want, ev);
}
+ @SmallTest
public void testNetworkEventSerialization() {
ConnectivityMetricsEvent ev = describeIpEvent(
aType(NetworkEvent.class),
@@ -221,6 +231,8 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " time_ms: 1",
+ " transport: 0",
" network_event <",
" event_type: 5",
" latency_ms: 20410",
@@ -228,13 +240,13 @@
" network_id: 100",
" >",
" >",
- " time_ms: 1",
">",
"version: 2");
verifySerialization(want, ev);
}
+ @SmallTest
public void testValidationProbeEventSerialization() {
ConnectivityMetricsEvent ev = describeIpEvent(
aType(ValidationProbeEvent.class),
@@ -247,6 +259,7 @@
"dropped_events: 0",
"events <",
" time_ms: 1",
+ " transport: 0",
" validation_probe_event <",
" latency_ms: 40730",
" network_id <",
@@ -261,6 +274,7 @@
verifySerialization(want, ev);
}
+ @SmallTest
public void testApfProgramEventSerialization() {
ConnectivityMetricsEvent ev = describeIpEvent(
aType(ApfProgramEvent.class),
@@ -273,6 +287,8 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " time_ms: 1",
+ " transport: 0",
" apf_program_event <",
" current_ras: 9",
" drop_multicast: true",
@@ -281,13 +297,13 @@
" lifetime: 200",
" program_length: 2048",
" >",
- " time_ms: 1",
">",
"version: 2");
verifySerialization(want, ev);
}
+ @SmallTest
public void testApfStatsSerialization() {
ConnectivityMetricsEvent ev = describeIpEvent(
aType(ApfStats.class),
@@ -303,6 +319,8 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " time_ms: 1",
+ " transport: 0",
" apf_statistics <",
" dropped_ras: 2",
" duration_ms: 45000",
@@ -313,13 +331,13 @@
" received_ras: 10",
" zero_lifetime_ras: 1",
" >",
- " time_ms: 1",
">",
"version: 2");
verifySerialization(want, ev);
}
+ @SmallTest
public void testRaEventSerialization() {
ConnectivityMetricsEvent ev = describeIpEvent(
aType(RaEvent.class),
@@ -333,6 +351,8 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " time_ms: 1",
+ " transport: 0",
" ra_event <",
" dnssl_lifetime: -1",
" prefix_preferred_lifetime: 300",
@@ -341,7 +361,6 @@
" route_info_lifetime: -1",
" router_lifetime: 2000",
" >",
- " time_ms: 1",
">",
"version: 2");
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index 78d16d9..60628ec 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -32,22 +32,19 @@
import android.net.metrics.RaEvent;
import android.net.metrics.ValidationProbeEvent;
import android.os.Parcelable;
+import android.test.suitebuilder.annotation.SmallTest;
import android.util.Base64;
-
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
-
-import junit.framework.TestCase;
-
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
+import junit.framework.TestCase;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
public class IpConnectivityMetricsTest extends TestCase {
static final IpReachabilityEvent FAKE_EV =
@@ -63,6 +60,7 @@
mService = new IpConnectivityMetrics(mCtx, (ctx) -> 2000);
}
+ @SmallTest
public void testLoggingEvents() throws Exception {
IpConnectivityLog logger = new IpConnectivityLog(mMockService);
@@ -76,6 +74,7 @@
assertEventsEqual(expectedEvent(3), got.get(2));
}
+ @SmallTest
public void testLoggingEventsWithMultipleCallers() throws Exception {
IpConnectivityLog logger = new IpConnectivityLog(mMockService);
@@ -103,6 +102,7 @@
}
}
+ @SmallTest
public void testBufferFlushing() {
String output1 = getdump("flush");
assertEquals("", output1);
@@ -115,6 +115,7 @@
assertEquals("", output3);
}
+ @SmallTest
public void testRateLimiting() {
final IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
final ApfProgramEvent ev = new ApfProgramEvent(0, 0, 0, 0, 0);
@@ -136,6 +137,7 @@
assertEquals("", output2);
}
+ @SmallTest
public void testEndToEndLogging() {
IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
@@ -156,22 +158,25 @@
String want = joinLines(
"dropped_events: 0",
"events <",
+ " time_ms: 100",
+ " transport: 0",
" ip_reachability_event <",
" event_type: 512",
" if_name: \"wlan0\"",
" >",
- " time_ms: 100",
">",
"events <",
+ " time_ms: 200",
+ " transport: 0",
" dhcp_event <",
" duration_ms: 192",
- " error_code: 0",
" if_name: \"wlan0\"",
" state_transition: \"SomeState\"",
" >",
- " time_ms: 200",
">",
"events <",
+ " time_ms: 300",
+ " transport: 0",
" default_network_event <",
" network_id <",
" network_id: 102",
@@ -184,18 +189,19 @@
" transport_types: 2",
" transport_types: 3",
" >",
- " time_ms: 300",
">",
"events <",
+ " time_ms: 400",
+ " transport: 0",
" ip_provisioning_event <",
" event_type: 1",
" if_name: \"wlan0\"",
" latency_ms: 5678",
" >",
- " time_ms: 400",
">",
"events <",
" time_ms: 500",
+ " transport: 0",
" validation_probe_event <",
" latency_ms: 40730",
" network_id <",
@@ -206,6 +212,8 @@
" >",
">",
"events <",
+ " time_ms: 600",
+ " transport: 0",
" apf_statistics <",
" dropped_ras: 2",
" duration_ms: 45000",
@@ -216,9 +224,10 @@
" received_ras: 10",
" zero_lifetime_ras: 1",
" >",
- " time_ms: 600",
">",
"events <",
+ " time_ms: 700",
+ " transport: 0",
" ra_event <",
" dnssl_lifetime: -1",
" prefix_preferred_lifetime: 300",
@@ -227,7 +236,6 @@
" route_info_lifetime: -1",
" router_lifetime: 2000",
" >",
- " time_ms: 700",
">",
"version: 2");
diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
new file mode 100644
index 0000000..813e928
--- /dev/null
+++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.telephony.TelephonyManager;
+import android.test.suitebuilder.annotation.SmallTest;
+import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import junit.framework.TestCase;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.*;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class NetworkNotificationManagerTest extends TestCase {
+
+ static final String NOTIFICATION_ID = NetworkNotificationManager.NOTIFICATION_ID;
+
+ static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities();
+ static final NetworkCapabilities WIFI_CAPABILITIES = new NetworkCapabilities();
+ static {
+ CELL_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ CELL_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+
+ WIFI_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+ WIFI_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ }
+
+ @Mock Context mCtx;
+ @Mock Resources mResources;
+ @Mock PackageManager mPm;
+ @Mock TelephonyManager mTelephonyManager;
+ @Mock NotificationManager mNotificationManager;
+ @Mock NetworkAgentInfo mWifiNai;
+ @Mock NetworkAgentInfo mCellNai;
+ @Mock NetworkInfo mNetworkInfo;
+ ArgumentCaptor<Notification> mCaptor;
+
+ NetworkNotificationManager mManager;
+
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mCaptor = ArgumentCaptor.forClass(Notification.class);
+ mWifiNai.networkCapabilities = WIFI_CAPABILITIES;
+ mWifiNai.networkInfo = mNetworkInfo;
+ mCellNai.networkCapabilities = CELL_CAPABILITIES;
+ mCellNai.networkInfo = mNetworkInfo;
+ when(mCtx.getResources()).thenReturn(mResources);
+ when(mCtx.getPackageManager()).thenReturn(mPm);
+ when(mCtx.getApplicationInfo()).thenReturn(new ApplicationInfo());
+ when(mResources.getColor(anyInt(), any())).thenReturn(0xFF607D8B);
+
+ mManager = new NetworkNotificationManager(mCtx, mTelephonyManager, mNotificationManager);
+ }
+
+ @SmallTest
+ public void testNotificationsShownAndCleared() {
+ final int NETWORK_ID_BASE = 100;
+ List<NotificationType> types = Arrays.asList(NotificationType.values());
+ List<Integer> ids = new ArrayList<>(types.size());
+ for (int i = 0; i < ids.size(); i++) {
+ ids.add(NETWORK_ID_BASE + i);
+ }
+ Collections.shuffle(ids);
+ Collections.shuffle(types);
+
+ for (int i = 0; i < ids.size(); i++) {
+ mManager.showNotification(ids.get(i), types.get(i), mWifiNai, mCellNai, null, false);
+ }
+
+ Collections.shuffle(ids);
+ for (int i = 0; i < ids.size(); i++) {
+ mManager.clearNotification(ids.get(i));
+ }
+
+ for (int i = 0; i < ids.size(); i++) {
+ final int expectedId = NETWORK_ID_BASE + i;
+ verify(mNotificationManager, times(1))
+ .notifyAsUser(eq(NOTIFICATION_ID), eq(expectedId), any(), any());
+ verify(mNotificationManager, times(1))
+ .cancelAsUser(eq(NOTIFICATION_ID), eq(expectedId), any());
+ }
+ }
+
+ @SmallTest
+ public void testNoInternetNotificationsNotShownForCellular() {
+ mManager.showNotification(100, NO_INTERNET, mCellNai, mWifiNai, null, false);
+ mManager.showNotification(101, LOST_INTERNET, mCellNai, mWifiNai, null, false);
+
+ verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
+
+ mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false);
+
+ verify(mNotificationManager, times(1))
+ .notifyAsUser(eq(NOTIFICATION_ID), eq(102), any(), any());
+ }
+
+ @SmallTest
+ public void testNotificationsNotShownIfNoInternetCapability() {
+ mWifiNai.networkCapabilities = new NetworkCapabilities();
+ mWifiNai.networkCapabilities .addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+ mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false);
+ mManager.showNotification(103, LOST_INTERNET, mWifiNai, mCellNai, null, false);
+ mManager.showNotification(104, NETWORK_SWITCH, mWifiNai, mCellNai, null, false);
+
+ verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
+ }
+}
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index 7d6f32b..28a2cb3 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -93,8 +93,7 @@
}
try {
- mWm.addAppToken(0, null, 0, 0, 0, false, false, 0, 0, false, false, null,
- Configuration.EMPTY, 0, false, false, 0, -1, false);
+ mWm.addAppToken(0, null, 0, 0, false, false, 0, false, false, false, 0, -1);
fail("IWindowManager.addAppToken did not throw SecurityException as"
+ " expected");
} catch (SecurityException e) {
@@ -104,7 +103,7 @@
}
try {
- mWm.setAppTask(null, 0, INVALID_STACK_ID, null, null, 0, false, false);
+ mWm.addAppToTask(null, 0);
fail("IWindowManager.setAppGroupId did not throw SecurityException as"
+ " expected");
} catch (SecurityException e) {
diff --git a/tools/aapt2/.clang-format b/tools/aapt2/.clang-format
index 545366a..71c5ef2 100644
--- a/tools/aapt2/.clang-format
+++ b/tools/aapt2/.clang-format
@@ -1,2 +1,3 @@
BasedOnStyle: Google
+ColumnLimit: 100
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index a3404e5..a2b216d 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -25,7 +25,7 @@
static const char* sMajorVersion = "2";
// Update minor version whenever a feature or flag is added.
-static const char* sMinorVersion = "3";
+static const char* sMinorVersion = "4";
int PrintVersion() {
std::cerr << "Android Asset Packaging Tool (aapt) " << sMajorVersion << "."
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 36a3494..4185937e6 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -216,6 +216,8 @@
manifest_action["supports-gl-texture"];
+ manifest_action["meta-data"] = meta_data_action;
+
// Application actions.
xml::XmlNodeAction& application_action = manifest_action["application"];
application_action.Action(OptionalNameIsJavaClassName);
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index e9bc64a..fc6970c 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -87,6 +87,23 @@
EXPECT_EQ(nullptr, Verify("<manifest package=\"@string/str\" />"));
}
+TEST_F(ManifestFixerTest, AllowMetaData) {
+ auto doc = Verify(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <meta-data />
+ <application>
+ <meta-data />
+ <activity android:name=".Hi"><meta-data /></activity>
+ <activity-alias android:name=".Ho"><meta-data /></activity-alias>
+ <receiver android:name=".OffToWork"><meta-data /></receiver>
+ <provider android:name=".We"><meta-data /></provider>
+ <service android:name=".Go"><meta-data /></service>
+ </application>
+ </manifest>)EOF");
+ ASSERT_NE(nullptr, doc);
+}
+
TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
ManifestFixerOptions options = {std::string("8"), std::string("22")};
diff --git a/tools/aapt2/readme.md b/tools/aapt2/readme.md
index ac411b1..8001033 100644
--- a/tools/aapt2/readme.md
+++ b/tools/aapt2/readme.md
@@ -1,5 +1,9 @@
# Android Asset Packaging Tool 2.0 (AAPT2) release notes
+## Version 2.4
+### `aapt2 link ...`
+- Supports `<meta-data>` tags in `<manifest>`.
+
## Version 2.3
### `aapt2`
- Support new `font` resource type.
diff --git a/tools/layoutlib/.idea/libraries/junit.xml b/tools/layoutlib/.idea/libraries/junit.xml
index c889f5f..ba46ebf 100644
--- a/tools/layoutlib/.idea/libraries/junit.xml
+++ b/tools/layoutlib/.idea/libraries/junit.xml
@@ -1,7 +1,7 @@
<component name="libraryTable">
<library name="junit">
<CLASSES>
- <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/junit_intermediates/javalib.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/junit-host_intermediates/javalib.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 9da65a6..35cf903 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -80,7 +80,7 @@
public BridgeTypedArray(Resources resources, BridgeContext context, int len,
boolean platformFile) {
- super(resources, null, null, 0);
+ super(resources);
mBridgeResources = resources;
mContext = context;
mPlatformFile = platformFile;
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index a0ded87..4b9815d 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -34,7 +34,6 @@
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.DisplayMetrics;
-import android.view.AppTransitionAnimationSpec;
import java.lang.Override;
@@ -78,11 +77,10 @@
// ---- unused implementation of IWindowManager ----
@Override
- public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, int arg4,
- boolean arg5, boolean arg6, int arg7, int arg8, boolean arg9, boolean arg10,
- Rect arg11, Configuration arg12, int arg13, boolean arg14, boolean arg15, int arg16,
- int arg17, boolean arg18)
- throws RemoteException {
+ public void addAppToken(int addPos, IApplicationToken token, int taskId,
+ int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int configChanges,
+ boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
+ int targetSdkVersion, int rotationAnimationHint) throws RemoteException {
// TODO Auto-generated method stub
}
@@ -327,9 +325,7 @@
}
@Override
- public void setAppTask(IBinder arg0, int arg1, int arg2, Rect arg3, Configuration arg4,
- int arg5, boolean arg6, boolean arg7)
- throws RemoteException {
+ public void addAppToTask(IBinder arg0, int arg1) throws RemoteException {
// TODO Auto-generated method stub
}
diff --git a/tools/layoutlib/bridge/src/android/view/SurfaceView.java b/tools/layoutlib/bridge/src/android/view/SurfaceView.java
index 1e7dfbe..ebb2af4 100644
--- a/tools/layoutlib/bridge/src/android/view/SurfaceView.java
+++ b/tools/layoutlib/bridge/src/android/view/SurfaceView.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.graphics.Region;
import android.util.AttributeSet;
/**
@@ -49,6 +50,19 @@
super(context, attrs, defStyleAttr, defStyleRes);
}
+ public boolean gatherTransparentRegion(Region region) {
+ return false;
+ }
+
+ public void setZOrderMediaOverlay(boolean isMediaOverlay) {
+ }
+
+ public void setZOrderOnTop(boolean onTop) {
+ }
+
+ public void setSecure(boolean isSecure) {
+ }
+
public SurfaceHolder getHolder() {
return mSurfaceHolder;
}
diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java
index ffce1a0..da1ab27 100644
--- a/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java
+++ b/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java
@@ -19,6 +19,7 @@
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+import android.graphics.Path;
import android.util.MathUtils;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
@@ -31,6 +32,7 @@
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;
+import android.view.animation.PathInterpolator;
/**
* Delegate used to provide new implementation of a select few methods of {@link
@@ -93,6 +95,16 @@
return sManager.addNewDelegate(new OvershootInterpolator(tension));
}
+ @LayoutlibDelegate
+ /*package*/ static long createPathInterpolator(float[] x, float[] y) {
+ Path path = new Path();
+ path.moveTo(x[0], y[0]);
+ for (int i = 1; i < x.length; i++) {
+ path.lineTo(x[i], y[i]);
+ }
+ return sManager.addNewDelegate(new PathInterpolator(path));
+ }
+
private static class LutInterpolator extends BaseInterpolator {
private final float[] mValues;
private final int mSize;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
index 3471165..c827f17 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
@@ -97,8 +97,8 @@
}
@Override
- public Cursor query(String callingPackage, Uri arg0, String[] arg1, String arg2, String[] arg3,
- String arg4, ICancellationSignal arg5) throws RemoteException {
+ public Cursor query(String callingPackage, Uri arg0, String[] arg1,
+ Bundle arg3, ICancellationSignal arg4) throws RemoteException {
// TODO Auto-generated method stub
return null;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
index 97698df..726ff22 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
@@ -166,13 +166,13 @@
FrameLayout contentRoot = new FrameLayout(getContext());
LayoutParams params = createLayoutParams(MATCH_PARENT, MATCH_PARENT);
int rule = mBuilder.isNavBarVertical() ? START_OF : ABOVE;
- if (mBuilder.hasNavBar() && mBuilder.solidBars()) {
+ if (mBuilder.hasSolidNavBar()) {
params.addRule(rule, getId(ID_NAV_BAR));
}
int below = -1;
if (mBuilder.mActionBarSize <= 0 && mBuilder.mTitleBarSize > 0) {
below = getId(ID_TITLE_BAR);
- } else if (mBuilder.hasStatusBar() && mBuilder.solidBars()) {
+ } else if (mBuilder.hasSolidStatusBar()) {
below = getId(ID_STATUS_BAR);
}
if (below != -1) {
@@ -241,10 +241,10 @@
}
LayoutParams layoutParams = createLayoutParams(MATCH_PARENT, MATCH_PARENT);
int rule = mBuilder.isNavBarVertical() ? START_OF : ABOVE;
- if (mBuilder.hasNavBar() && mBuilder.solidBars()) {
+ if (mBuilder.hasSolidNavBar()) {
layoutParams.addRule(rule, getId(ID_NAV_BAR));
}
- if (mBuilder.hasStatusBar() && mBuilder.solidBars()) {
+ if (mBuilder.hasSolidStatusBar()) {
layoutParams.addRule(BELOW, getId(ID_STATUS_BAR));
}
actionBar.getRootView().setLayoutParams(layoutParams);
@@ -257,10 +257,10 @@
int simulatedPlatformVersion) {
TitleBar titleBar = new TitleBar(context, title, simulatedPlatformVersion);
LayoutParams params = createLayoutParams(MATCH_PARENT, mBuilder.mTitleBarSize);
- if (mBuilder.hasStatusBar() && mBuilder.solidBars()) {
+ if (mBuilder.hasSolidStatusBar()) {
params.addRule(BELOW, getId(ID_STATUS_BAR));
}
- if (mBuilder.isNavBarVertical() && mBuilder.solidBars()) {
+ if (mBuilder.isNavBarVertical() && mBuilder.hasSolidNavBar()) {
params.addRule(START_OF, getId(ID_NAV_BAR));
}
titleBar.setLayoutParams(params);
@@ -419,11 +419,17 @@
}
/**
- * Return true if the status bar or nav bar are present, they are not translucent (i.e
- * content doesn't overlap with them).
+ * Return true if the nav bar is present and not translucent
*/
- private boolean solidBars() {
- return !(hasNavBar() && mTranslucentNav) && !(hasStatusBar() && mTranslucentStatus);
+ private boolean hasSolidNavBar() {
+ return hasNavBar() && !mTranslucentNav;
+ }
+
+ /**
+ * Return true if the status bar is present and not translucent
+ */
+ private boolean hasSolidStatusBar() {
+ return hasStatusBar() && !mTranslucentStatus;
}
private boolean hasNavBar() {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/libcore/io/BridgeBufferIterator.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/libcore/io/BridgeBufferIterator.java
index 7e361a1..96cba78 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/libcore/io/BridgeBufferIterator.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/libcore/io/BridgeBufferIterator.java
@@ -40,6 +40,11 @@
}
@Override
+ public int pos() {
+ return mByteBuffer.position();
+ }
+
+ @Override
public void skip(int byteCount) {
int newPosition = mByteBuffer.position() + byteCount;
assert newPosition <= mSize;
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners.png
new file mode 100644
index 0000000..868cd51
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent.png
new file mode 100644
index 0000000..601f711
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent_land.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent_land.png
new file mode 100644
index 0000000..0b8f1a9
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent_land.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/four_corners.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/four_corners.xml
new file mode 100644
index 0000000..c42284a
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/four_corners.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_centerHorizontal="true"
+ android:textSize="40sp"
+ android:text="Bottom Text" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:textSize="40sp"
+ android:text="Top text" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true"
+ android:textSize="40sp"
+ android:text="Start text" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_centerVertical="true"
+ android:textSize="40sp"
+ android:text="End text" />
+</RelativeLayout>
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index 24cbbca..c813a12 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -39,6 +39,7 @@
import com.android.resources.Density;
import com.android.resources.Navigation;
import com.android.resources.ResourceType;
+import com.android.resources.ScreenOrientation;
import com.android.tools.layoutlib.java.System_Delegate;
import com.android.utils.ILogger;
@@ -341,6 +342,31 @@
renderAndVerify("activity.xml", "activity.png");
}
+ @Test
+ public void testTranslucentBars() throws ClassNotFoundException {
+ LayoutLibTestCallback layoutLibCallback =
+ new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
+ layoutLibCallback.initResources();
+
+ LayoutPullParser parser = createLayoutPullParser("four_corners.xml");
+ SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
+ layoutLibCallback, "Theme.Material.Light.NoActionBar.TranslucentDecor", false,
+ RenderingMode.NORMAL, 22);
+ renderAndVerify(params, "four_corners_translucent.png");
+
+ parser = createLayoutPullParser("four_corners.xml");
+ params = getSessionParams(parser, ConfigGenerator.NEXUS_5_LAND,
+ layoutLibCallback, "Theme.Material.Light.NoActionBar.TranslucentDecor", false,
+ RenderingMode.NORMAL, 22);
+ renderAndVerify(params, "four_corners_translucent_land.png");
+
+ parser = createLayoutPullParser("four_corners.xml");
+ params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
+ layoutLibCallback, "Theme.Material.Light.NoActionBar", false,
+ RenderingMode.NORMAL, 22);
+ renderAndVerify(params, "four_corners.png");
+ }
+
private static void gc() {
// See RuntimeUtil#gc in jlibs (http://jlibs.in/)
Object obj = new Object();
diff --git a/tools/preload2/Android.mk b/tools/preload2/Android.mk
index 769db6b..d3ee1d3 100644
--- a/tools/preload2/Android.mk
+++ b/tools/preload2/Android.mk
@@ -17,6 +17,8 @@
LOCAL_MODULE:= preload2
include $(BUILD_HOST_JAVA_LIBRARY)
+# Copy to build artifacts
+$(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE):$(LOCAL_MODULE).jar)
# Copy the preload-tool shell script to the host's bin directory.
include $(CLEAR_VARS)
diff --git a/tools/streaming_proto/main.cpp b/tools/streaming_proto/main.cpp
index 5435728..5b4ba04 100644
--- a/tools/streaming_proto/main.cpp
+++ b/tools/streaming_proto/main.cpp
@@ -94,7 +94,7 @@
* Figure out the name of the file we are generating.
*/
static string
-make_file_name(const FileDescriptorProto& file_descriptor)
+make_file_name(const FileDescriptorProto& file_descriptor, const string& class_name)
{
string const package = make_java_package(file_descriptor);
string result;
@@ -103,7 +103,7 @@
result += '/';
}
- result += make_outer_class_name(file_descriptor);
+ result += class_name;
result += ".java";
return result;
@@ -320,10 +320,16 @@
/**
* Write the contents of a file.
+ *
+ * If there are enums and generate_outer is false, invalid java code will be generated.
*/
static void
-write_file(stringstream& text, const FileDescriptorProto& file_descriptor)
+write_file(CodeGeneratorResponse* response, const FileDescriptorProto& file_descriptor,
+ const string& filename, bool generate_outer,
+ const vector<EnumDescriptorProto>& enums, const vector<DescriptorProto>& messages)
{
+ stringstream text;
+
string const package_name = make_java_package(file_descriptor);
string const outer_class_name = make_outer_class_name(file_descriptor);
@@ -338,27 +344,92 @@
}
// This bit of policy is android api rules specific: Raw proto classes
- // must never be in the API, but they should all be available for testing.
+ // must never be in the API
text << "/** @hide */" << endl;
- text << "@android.annotation.TestApi" << endl;
+// text << "@android.annotation.TestApi" << endl;
- text << "public final class " << outer_class_name << " {" << endl;
- text << endl;
+ if (generate_outer) {
+ text << "public final class " << outer_class_name << " {" << endl;
+ text << endl;
+ }
- int N;
- const string indented = indent_more("");
+ size_t N;
+ const string indented = generate_outer ? indent_more("") : string();
+ N = enums.size();
+ for (size_t i=0; i<N; i++) {
+ write_enum(text, enums[i], indented);
+ }
+
+ N = messages.size();
+ for (size_t i=0; i<N; i++) {
+ write_message(text, messages[i], indented);
+ }
+
+ if (generate_outer) {
+ text << "}" << endl;
+ }
+
+ CodeGeneratorResponse::File* file_response = response->add_file();
+ file_response->set_name(filename);
+ file_response->set_content(text.str());
+}
+
+/**
+ * Write one file per class. Put all of the enums into the "outer" class.
+ */
+static void
+write_multiple_files(CodeGeneratorResponse* response, const FileDescriptorProto& file_descriptor)
+{
+ // If there is anything to put in the outer class file, create one
+ if (file_descriptor.enum_type_size() > 0) {
+ vector<EnumDescriptorProto> enums;
+ int N = file_descriptor.enum_type_size();
+ for (int i=0; i<N; i++) {
+ enums.push_back(file_descriptor.enum_type(i));
+ }
+
+ vector<DescriptorProto> messages;
+
+ write_file(response, file_descriptor,
+ make_file_name(file_descriptor, make_outer_class_name(file_descriptor)),
+ true, enums, messages);
+ }
+
+ // For each of the message types, make a file
+ int N = file_descriptor.message_type_size();
+ for (int i=0; i<N; i++) {
+ vector<EnumDescriptorProto> enums;
+
+ vector<DescriptorProto> messages;
+ messages.push_back(file_descriptor.message_type(i));
+
+ write_file(response, file_descriptor,
+ make_file_name(file_descriptor, file_descriptor.message_type(i).name()),
+ false, enums, messages);
+ }
+}
+
+static void
+write_single_file(CodeGeneratorResponse* response, const FileDescriptorProto& file_descriptor)
+{
+ int N;
+
+ vector<EnumDescriptorProto> enums;
N = file_descriptor.enum_type_size();
for (int i=0; i<N; i++) {
- write_enum(text, file_descriptor.enum_type(i), indented);
+ enums.push_back(file_descriptor.enum_type(i));
}
+ vector<DescriptorProto> messages;
N = file_descriptor.message_type_size();
for (int i=0; i<N; i++) {
- write_message(text, file_descriptor.message_type(i), indented);
+ messages.push_back(file_descriptor.message_type(i));
}
- text << "}" << endl;
+ write_file(response, file_descriptor,
+ make_file_name(file_descriptor, make_outer_class_name(file_descriptor)),
+ true, enums, messages);
}
/**
@@ -383,16 +454,11 @@
for (int i=0; i<N; i++) {
const FileDescriptorProto& file_descriptor = request.proto_file(i);
if (should_generate_for_file(request, file_descriptor.name())) {
- // Generate the text
- stringstream text;
- write_file(text, file_descriptor);
-
- // Put the text in the response
- CodeGeneratorResponse::File* file_response = response.add_file();
- file_response->set_name(make_file_name(file_descriptor));
- file_response->set_content(text.str());
-
- cerr << "writing file: " << file_response->name() << endl;
+ if (file_descriptor.options().java_multiple_files()) {
+ write_multiple_files(&response, file_descriptor);
+ } else {
+ write_single_file(&response, file_descriptor);
+ }
}
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 82d41e3..43e6246 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -98,10 +98,22 @@
*/
public static final int OSEN = 5;
+ /**
+ * IEEE 802.11r Fast BSS Transition with PSK authentication.
+ * @hide
+ */
+ public static final int FT_PSK = 6;
+
+ /**
+ * IEEE 802.11r Fast BSS Transition with EAP authentication.
+ * @hide
+ */
+ public static final int FT_EAP = 7;
+
public static final String varName = "key_mgmt";
public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X",
- "WPA2_PSK", "OSEN" };
+ "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP" };
}
/**
@@ -734,50 +746,6 @@
@SystemApi
public int numAssociation;
- /**
- * @hide
- * Number of time user disabled WiFi while associated to this configuration with Low RSSI.
- */
- public int numUserTriggeredWifiDisableLowRSSI;
-
- /**
- * @hide
- * Number of time user disabled WiFi while associated to this configuration with Bad RSSI.
- */
- public int numUserTriggeredWifiDisableBadRSSI;
-
- /**
- * @hide
- * Number of time user disabled WiFi while associated to this configuration
- * and RSSI was not HIGH.
- */
- public int numUserTriggeredWifiDisableNotHighRSSI;
-
- /**
- * @hide
- * Number of ticks associated to this configuration with Low RSSI.
- */
- public int numTicksAtLowRSSI;
-
- /**
- * @hide
- * Number of ticks associated to this configuration with Bad RSSI.
- */
- public int numTicksAtBadRSSI;
-
- /**
- * @hide
- * Number of ticks associated to this configuration
- * and RSSI was not HIGH.
- */
- public int numTicksAtNotHighRSSI;
- /**
- * @hide
- * Number of time user (WifiManager) triggered association to this configuration.
- * TODO: count this only for Wifi Settings uuid, so as to not count 3rd party apps
- */
- public int numUserTriggeredJoinAttempts;
-
/** @hide
* Boost given to RSSI on a home network for the purpose of calculating the score
* This adds stickiness to home networks, as defined by:
@@ -1618,16 +1586,6 @@
sbuf.append('\n');
}
}
- sbuf.append("triggeredLow: ").append(this.numUserTriggeredWifiDisableLowRSSI);
- sbuf.append(" triggeredBad: ").append(this.numUserTriggeredWifiDisableBadRSSI);
- sbuf.append(" triggeredNotHigh: ").append(this.numUserTriggeredWifiDisableNotHighRSSI);
- sbuf.append('\n');
- sbuf.append("ticksLow: ").append(this.numTicksAtLowRSSI);
- sbuf.append(" ticksBad: ").append(this.numTicksAtBadRSSI);
- sbuf.append(" ticksNotHigh: ").append(this.numTicksAtNotHighRSSI);
- sbuf.append('\n');
- sbuf.append("triggeredJoin: ").append(this.numUserTriggeredJoinAttempts);
- sbuf.append('\n');
return sbuf.toString();
}
@@ -1934,13 +1892,6 @@
numScorerOverride = source.numScorerOverride;
numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork;
numAssociation = source.numAssociation;
- numUserTriggeredWifiDisableLowRSSI = source.numUserTriggeredWifiDisableLowRSSI;
- numUserTriggeredWifiDisableBadRSSI = source.numUserTriggeredWifiDisableBadRSSI;
- numUserTriggeredWifiDisableNotHighRSSI = source.numUserTriggeredWifiDisableNotHighRSSI;
- numTicksAtLowRSSI = source.numTicksAtLowRSSI;
- numTicksAtBadRSSI = source.numTicksAtBadRSSI;
- numTicksAtNotHighRSSI = source.numTicksAtNotHighRSSI;
- numUserTriggeredJoinAttempts = source.numUserTriggeredJoinAttempts;
userApproved = source.userApproved;
numNoInternetAccessReports = source.numNoInternetAccessReports;
noInternetAccessExpected = source.noInternetAccessExpected;
@@ -2006,13 +1957,6 @@
dest.writeInt(numScorerOverride);
dest.writeInt(numScorerOverrideAndSwitchedNetwork);
dest.writeInt(numAssociation);
- dest.writeInt(numUserTriggeredWifiDisableLowRSSI);
- dest.writeInt(numUserTriggeredWifiDisableBadRSSI);
- dest.writeInt(numUserTriggeredWifiDisableNotHighRSSI);
- dest.writeInt(numTicksAtLowRSSI);
- dest.writeInt(numTicksAtBadRSSI);
- dest.writeInt(numTicksAtNotHighRSSI);
- dest.writeInt(numUserTriggeredJoinAttempts);
dest.writeInt(userApproved);
dest.writeInt(numNoInternetAccessReports);
dest.writeInt(noInternetAccessExpected ? 1 : 0);
@@ -2078,13 +2022,6 @@
config.numScorerOverride = in.readInt();
config.numScorerOverrideAndSwitchedNetwork = in.readInt();
config.numAssociation = in.readInt();
- config.numUserTriggeredWifiDisableLowRSSI = in.readInt();
- config.numUserTriggeredWifiDisableBadRSSI = in.readInt();
- config.numUserTriggeredWifiDisableNotHighRSSI = in.readInt();
- config.numTicksAtLowRSSI = in.readInt();
- config.numTicksAtBadRSSI = in.readInt();
- config.numTicksAtNotHighRSSI = in.readInt();
- config.numUserTriggeredJoinAttempts = in.readInt();
config.userApproved = in.readInt();
config.numNoInternetAccessReports = in.readInt();
config.noInternetAccessExpected = in.readInt() != 0;
diff --git a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
new file mode 100755
index 0000000..c328748
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2014 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.net.wifi;
+
+import android.Manifest.permission;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.net.INetworkScoreCache;
+import android.net.NetworkKey;
+import android.net.ScoredNetwork;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * {@link INetworkScoreCache} implementation for Wifi Networks.
+ *
+ * @hide
+ */
+public class WifiNetworkScoreCache extends INetworkScoreCache.Stub {
+ private static final String TAG = "WifiNetworkScoreCache";
+ private static final boolean DBG = false;
+
+ // A Network scorer returns a score in the range [-128, +127]
+ // We treat the lowest possible score as though there were no score, effectively allowing the
+ // scorer to provide an RSSI threshold below which a network should not be used.
+ public static final int INVALID_NETWORK_SCORE = Byte.MIN_VALUE;
+ private final Context mContext;
+
+ // The key is of the form "<ssid>"<bssid>
+ // TODO: What about SSIDs that can't be encoded as UTF-8?
+ private final Map<String, ScoredNetwork> mNetworkCache;
+
+ public WifiNetworkScoreCache(Context context) {
+ mContext = context;
+ mNetworkCache = new HashMap<String, ScoredNetwork>();
+ }
+
+ @Override public final void updateScores(List<ScoredNetwork> networks) {
+ if (networks == null) {
+ return;
+ }
+ Log.e(TAG, "updateScores list size=" + networks.size());
+
+ synchronized(mNetworkCache) {
+ for (ScoredNetwork network : networks) {
+ String networkKey = buildNetworkKey(network);
+ if (networkKey == null) continue;
+ mNetworkCache.put(networkKey, network);
+ }
+ }
+ }
+
+ @Override public final void clearScores() {
+ synchronized (mNetworkCache) {
+ mNetworkCache.clear();
+ }
+ }
+
+ /**
+ * Returns whether there is any score info for the given ScanResult.
+ *
+ * This includes null-score info, so it should only be used when determining whether to request
+ * scores from the network scorer.
+ */
+ public boolean isScoredNetwork(ScanResult result) {
+ return getScoredNetwork(result) != null;
+ }
+
+ /**
+ * Returns whether there is a non-null score curve for the given ScanResult.
+ *
+ * A null score curve has special meaning - we should never connect to an ephemeral network if
+ * the score curve is null.
+ */
+ public boolean hasScoreCurve(ScanResult result) {
+ ScoredNetwork network = getScoredNetwork(result);
+ return network != null && network.rssiCurve != null;
+ }
+
+ public int getNetworkScore(ScanResult result) {
+
+ int score = INVALID_NETWORK_SCORE;
+
+ ScoredNetwork network = getScoredNetwork(result);
+ if (network != null && network.rssiCurve != null) {
+ score = network.rssiCurve.lookupScore(result.level);
+ if (DBG) {
+ Log.e(TAG, "getNetworkScore found scored network " + network.networkKey
+ + " score " + Integer.toString(score)
+ + " RSSI " + result.level);
+ }
+ }
+ return score;
+ }
+
+ /**
+ * Returns the ScoredNetwork metered hint for a given ScanResult.
+ *
+ * If there is no ScoredNetwork associated with the ScanResult then false will be returned.
+ */
+ public boolean getMeteredHint(ScanResult result) {
+ ScoredNetwork network = getScoredNetwork(result);
+ return network != null && network.meteredHint;
+ }
+
+ public int getNetworkScore(ScanResult result, boolean isActiveNetwork) {
+
+ int score = INVALID_NETWORK_SCORE;
+
+ ScoredNetwork network = getScoredNetwork(result);
+ if (network != null && network.rssiCurve != null) {
+ score = network.rssiCurve.lookupScore(result.level, isActiveNetwork);
+ if (DBG) {
+ Log.e(TAG, "getNetworkScore found scored network " + network.networkKey
+ + " score " + Integer.toString(score)
+ + " RSSI " + result.level
+ + " isActiveNetwork " + isActiveNetwork);
+ }
+ }
+ return score;
+ }
+
+ private ScoredNetwork getScoredNetwork(ScanResult result) {
+ String key = buildNetworkKey(result);
+ if (key == null) return null;
+
+ //find it
+ synchronized(mNetworkCache) {
+ ScoredNetwork network = mNetworkCache.get(key);
+ return network;
+ }
+ }
+
+ private String buildNetworkKey(ScoredNetwork network) {
+ if (network == null || network.networkKey == null) return null;
+ if (network.networkKey.wifiKey == null) return null;
+ if (network.networkKey.type == NetworkKey.TYPE_WIFI) {
+ String key = network.networkKey.wifiKey.ssid;
+ if (key == null) return null;
+ if (network.networkKey.wifiKey.bssid != null) {
+ key = key + network.networkKey.wifiKey.bssid;
+ }
+ return key;
+ }
+ return null;
+ }
+
+ private String buildNetworkKey(ScanResult result) {
+ if (result == null || result.SSID == null) {
+ return null;
+ }
+ StringBuilder key = new StringBuilder("\"");
+ key.append(result.SSID);
+ key.append("\"");
+ if (result.BSSID != null) {
+ key.append(result.BSSID);
+ }
+ return key.toString();
+ }
+
+ @Override protected final void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
+ writer.println("WifiNetworkScoreCache");
+ writer.println(" All score curves:");
+ for (Map.Entry<String, ScoredNetwork> entry : mNetworkCache.entrySet()) {
+ ScoredNetwork scoredNetwork = entry.getValue();
+ writer.println(" " + entry.getKey() + ": " + scoredNetwork.rssiCurve
+ + ", meteredHint=" + scoredNetwork.meteredHint);
+ }
+ writer.println(" Current network scores:");
+ WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ for (ScanResult scanResult : wifiManager.getScanResults()) {
+ writer.println(" " + buildNetworkKey(scanResult) + ": " + getNetworkScore(scanResult));
+ }
+ }
+
+}
diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
index bf35445..0fe69a8 100644
--- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
@@ -405,7 +405,7 @@
* single match session (corresponding to the same publish action on the
* peer) reported to the host (using the
* {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], byte[])}). The options are: only report the first match and ignore the rest
+ * byte[], List)}). The options are: only report the first match and ignore the rest
* {@link SubscribeConfig#MATCH_STYLE_FIRST_ONLY} or report every single
* match {@link SubscribeConfig#MATCH_STYLE_ALL} (the default).
*
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java b/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
index 95d128d..092aa34 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
@@ -70,8 +70,8 @@
/**
* Returns the maximum length of byte array that can be used to specify a Aware match filter.
* Restricts the parameters of the
- * {@link PublishConfig.Builder#setMatchFilter(java.util.List<byte[]>)} and
- * {@link SubscribeConfig.Builder#setMatchFilter(java.util.List<byte[]>)}.
+ * {@link PublishConfig.Builder#setMatchFilter(java.util.List)} and
+ * {@link SubscribeConfig.Builder#setMatchFilter(java.util.List)}.
*
* @return A positive integer, maximum legngth of byte array for Aware discovery match filter.
*/
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java b/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
index 451d8a5..2812ad4 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
@@ -140,7 +140,7 @@
* Sends a message to the specified destination. Aware messages are transmitted in the context
* of a discovery session - executed subsequent to a publish/subscribe
* {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], java.util.List<byte[]>)} event.
+ * byte[], java.util.List)} event.
* <p>
* Aware messages are not guaranteed delivery. Callbacks on
* {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully,
@@ -154,7 +154,7 @@
*
* @param peerHandle The peer's handle for the message. Must be a result of an
* {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], java.util.List<byte[]>)} or
+ * byte[], java.util.List)} or
* {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
* byte[])} events.
* @param messageId An arbitrary integer used by the caller to identify the message. The same
@@ -187,7 +187,7 @@
* Sends a message to the specified destination. Aware messages are transmitted in the context
* of a discovery session - executed subsequent to a publish/subscribe
* {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], java.util.List<byte[]>)} event.
+ * byte[], java.util.List)} event.
* <p>
* Aware messages are not guaranteed delivery. Callbacks on
* {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully,
@@ -203,7 +203,7 @@
*
* @param peerHandle The peer's handle for the message. Must be a result of an
* {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], java.util.List<byte[]>)} or
+ * byte[], java.util.List)} or
* {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
* byte[])} events.
* @param messageId An arbitrary integer used by the caller to identify the message. The same
@@ -220,7 +220,7 @@
/**
* Start a ranging operation with the specified peers. The peer IDs are obtained from an
* {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], java.util.List<byte[]>)} or
+ * byte[], java.util.List)} or
* {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
* byte[])} operation - can
* only range devices which are part of an ongoing discovery session.
@@ -266,7 +266,7 @@
*
* @param peerHandle The peer's handle obtained through
* {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], java.util.List<byte[]>)} or
+ * byte[], java.util.List)} or
* {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
* byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
* from only that peer. A RESPONDER may specified a null - indicating that
diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk
index 5850fee..eac49d2 100644
--- a/wifi/tests/Android.mk
+++ b/wifi/tests/Android.mk
@@ -50,6 +50,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
+ guava \
mockito-target-minus-junit4 \
frameworks-base-testutils \
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
new file mode 100644
index 0000000..5f949747
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.net.wifi;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import android.os.Parcel;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiConfiguration}.
+ */
+public class WifiConfigurationTest {
+
+ @Before
+ public void setUp() {
+ }
+
+ /**
+ * Check that parcel marshalling/unmarshalling works
+ *
+ * Create and populate a WifiConfiguration.
+ * Marshall and unmashall it, and expect to recover a copy of the original.
+ * Marshall the resulting object, and expect the bytes to match the
+ * first marshall result.
+ */
+ @Test
+ public void testWifiConfigurationParcel() {
+ String cookie = "C O.o |<IE";
+ WifiConfiguration config = new WifiConfiguration();
+ config.setPasspointManagementObjectTree(cookie);
+ Parcel parcelW = Parcel.obtain();
+ config.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ WifiConfiguration reconfig = WifiConfiguration.CREATOR.createFromParcel(parcelR);
+
+ // lacking a useful config.equals, check one field near the end.
+ assertEquals(cookie, reconfig.getMoTree());
+
+ Parcel parcelWW = Parcel.obtain();
+ reconfig.writeToParcel(parcelWW, 0);
+ byte[] rebytes = parcelWW.marshall();
+ parcelWW.recycle();
+
+ assertArrayEquals(bytes, rebytes);
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java
new file mode 100644
index 0000000..f8549b9
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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.net.wifi;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.NetworkKey;
+import android.net.RssiCurve;
+import android.net.ScoredNetwork;
+import android.net.WifiKey;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Rule;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Unit tests for {@link WifiNetworkScoreCache}. */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class WifiNetworkScoreCacheTest {
+
+ @Mock public Context mockContext; // isn't used, can be null
+ @Mock private RssiCurve mockRssiCurve;
+
+ public static final String SSID = "ssid";
+ public static final String FORMATTED_SSID = "\"" + SSID + "\"";
+ public static final String BSSID = "AA:AA:AA:AA:AA:AA";
+
+ public static final WifiKey VALID_KEY = new WifiKey(FORMATTED_SSID, BSSID);
+
+ public static final ScanResult VALID_SCAN_RESULT = buildScanResult(SSID, BSSID);
+
+ private ScoredNetwork mValidScoredNetwork;
+ private WifiNetworkScoreCache mScoreCache =
+ new WifiNetworkScoreCache(mockContext);
+
+ private static ScanResult buildScanResult(String ssid, String bssid) {
+ return new ScanResult(
+ WifiSsid.createFromAsciiEncoded(ssid),
+ bssid,
+ "" /* caps */,
+ 0 /* level */,
+ 0 /* frequency */,
+ 0 /* tsf */,
+ 0 /* distCm */,
+ 0 /* distSdCm*/);
+ }
+
+ private static ScoredNetwork buildScoredNetwork(WifiKey key, RssiCurve curve) {
+ return new ScoredNetwork(new NetworkKey(key), curve);
+ }
+
+ // Called from setup
+ private void initializeCacheWithValidScoredNetwork() {
+ mScoreCache.updateScores(ImmutableList.of(mValidScoredNetwork));
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mValidScoredNetwork = buildScoredNetwork(VALID_KEY, mockRssiCurve);
+ mScoreCache = new WifiNetworkScoreCache(mockContext);
+ initializeCacheWithValidScoredNetwork();
+ }
+
+
+ @Test
+ public void isScoredNetworkShouldReturnTrueAfterUpdateScoresIsCalled() {
+ assertTrue(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT));
+ }
+
+ @Test
+ public void isScoredNetworkShouldReturnFalseAfterClearScoresIsCalled() {
+ mScoreCache.clearScores();
+ assertFalse(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT));
+ }
+
+ @Test
+ public void updateScoresShouldAddNewNetwork() {
+ WifiKey key2 = new WifiKey("\"ssid2\"", BSSID);
+ ScoredNetwork network2 = buildScoredNetwork(key2, mockRssiCurve);
+ ScanResult result2 = buildScanResult("ssid2", BSSID);
+
+ mScoreCache.updateScores(ImmutableList.of(network2));
+
+ assertTrue(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT));
+ assertTrue(mScoreCache.isScoredNetwork(result2));
+ }
+
+ @Test
+ public void hasScoreCurveShouldReturnTrue() {
+ assertTrue(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT));
+ }
+
+ @Test
+ public void hasScoreCurveShouldReturnFalseWhenNoCachedNetwork() {
+ ScanResult unscored = buildScanResult("fake", BSSID);
+ assertFalse(mScoreCache.hasScoreCurve(unscored));
+ }
+
+ @Test
+ public void hasScoreCurveShouldReturnFalseWhenScoredNetworkHasNoCurve() {
+ ScoredNetwork noCurve = buildScoredNetwork(VALID_KEY, null /* rssiCurve */);
+ mScoreCache.updateScores(ImmutableList.of(noCurve));
+
+ assertFalse(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT));
+ }
+
+ @Test
+ public void getNetworkScoreShouldReturnScore() {
+ final byte score = 50;
+ final int rssi = -70;
+ ScanResult result = new ScanResult(VALID_SCAN_RESULT);
+ result.level = rssi;
+
+ when(mockRssiCurve.lookupScore(rssi)).thenReturn(score);
+
+ assertEquals(score, mScoreCache.getNetworkScore(result));
+ }
+
+ @Test
+ public void getMeteredHintShouldReturnFalse() {
+ assertFalse(mScoreCache.getMeteredHint(VALID_SCAN_RESULT));
+ }
+
+ @Test
+ public void getMeteredHintShouldReturnTrue() {
+ ScoredNetwork network =
+ new ScoredNetwork(new NetworkKey(VALID_KEY), mockRssiCurve, true /* metered Hint */);
+ mScoreCache.updateScores(ImmutableList.of(network));
+
+ assertTrue(mScoreCache.getMeteredHint(VALID_SCAN_RESULT));
+ }
+}