diff options
50 files changed, 1394 insertions, 267 deletions
diff --git a/api/current.txt b/api/current.txt index 524f9a0da49e..4fdbc08e9021 100644 --- a/api/current.txt +++ b/api/current.txt @@ -25278,6 +25278,7 @@ package android.media { public final class MediaCas implements java.lang.AutoCloseable { ctor public MediaCas(int) throws android.media.MediaCasException.UnsupportedCasException; ctor public MediaCas(@NonNull android.content.Context, int, @Nullable String, int) throws android.media.MediaCasException.UnsupportedCasException; + ctor public MediaCas(@NonNull android.content.Context, int, @Nullable String, int, @Nullable android.os.Handler, @Nullable android.media.MediaCas.EventListener) throws android.media.MediaCasException.UnsupportedCasException; method public void close(); method public static android.media.MediaCas.PluginDescriptor[] enumeratePlugins(); method protected void finalize(); diff --git a/api/system-current.txt b/api/system-current.txt index 095d628d9b78..9cf09264fed1 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4423,11 +4423,11 @@ package android.media { } public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation { - method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnRtpRxNoticeListener(@NonNull android.content.Context, @NonNull android.media.MediaPlayer.OnRtpRxNoticeListener, @Nullable android.os.Handler); + method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnImsRxNoticeListener(@Nullable android.media.MediaPlayer.OnImsRxNoticeListener, @Nullable android.os.Handler); } - public static interface MediaPlayer.OnRtpRxNoticeListener { - method public void onRtpRxNotice(@NonNull android.media.MediaPlayer, int, @NonNull int[]); + public static interface MediaPlayer.OnImsRxNoticeListener { + method public void onImsRxNotice(@NonNull android.media.MediaPlayer, @NonNull byte[]); } public final class MediaRecorder.AudioSource { diff --git a/api/system-lint-baseline.txt b/api/system-lint-baseline.txt index 3ef1f354d9e8..773ecd034a8e 100644 --- a/api/system-lint-baseline.txt +++ b/api/system-lint-baseline.txt @@ -41,8 +41,8 @@ BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(jav Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.net.IpSecTransform.Builder.buildTunnelModeTransform(java.net.InetAddress,android.net.IpSecManager.SecurityParameterIndex) -ExecutorRegistration: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler): - Registration methods should have overload that accepts delivery Executor: `setOnRtpRxNoticeListener` +ExecutorRegistration: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler): + Registration methods should have overload that accepts delivery Executor: `setOnImsRxNoticeListener` ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#deletePersistentGroup(android.net.wifi.p2p.WifiP2pManager.Channel, int, android.net.wifi.p2p.WifiP2pManager.ActionListener): ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#factoryReset(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener): @@ -377,8 +377,8 @@ SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android. SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler): SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioTrack.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions -SamShouldBeLast: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler): - SAM-compatible parameters (such as parameter 2, "listener", in android.media.MediaPlayer.setOnRtpRxNoticeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions +SamShouldBeLast: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler): + SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaPlayer.setOnImsRxNoticeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions SamShouldBeLast: android.media.MediaRecorder#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler): SamShouldBeLast: android.media.MediaRecorder#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback): diff --git a/core/api/current.txt b/core/api/current.txt index 2cd01a6e60a2..0516f6303960 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -25260,6 +25260,7 @@ package android.media { public final class MediaCas implements java.lang.AutoCloseable { ctor public MediaCas(int) throws android.media.MediaCasException.UnsupportedCasException; ctor public MediaCas(@NonNull android.content.Context, int, @Nullable String, int) throws android.media.MediaCasException.UnsupportedCasException; + ctor public MediaCas(@NonNull android.content.Context, int, @Nullable String, int, @Nullable android.os.Handler, @Nullable android.media.MediaCas.EventListener) throws android.media.MediaCasException.UnsupportedCasException; method public void close(); method public static android.media.MediaCas.PluginDescriptor[] enumeratePlugins(); method protected void finalize(); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 2bb477e0837f..b37f7386ab70 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -4363,11 +4363,11 @@ package android.media { } public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation { - method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnRtpRxNoticeListener(@NonNull android.content.Context, @NonNull android.media.MediaPlayer.OnRtpRxNoticeListener, @Nullable android.os.Handler); + method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnImsRxNoticeListener(@Nullable android.media.MediaPlayer.OnImsRxNoticeListener, @Nullable android.os.Handler); } - public static interface MediaPlayer.OnRtpRxNoticeListener { - method public void onRtpRxNotice(@NonNull android.media.MediaPlayer, int, @NonNull int[]); + public static interface MediaPlayer.OnImsRxNoticeListener { + method public void onImsRxNotice(@NonNull android.media.MediaPlayer, @NonNull byte[]); } public final class MediaRecorder.AudioSource { diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt index a3fb06cbd92f..4db55e7e07eb 100644 --- a/core/api/system-lint-baseline.txt +++ b/core/api/system-lint-baseline.txt @@ -6,8 +6,7 @@ ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions(): BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex): Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.net.IpSecTransform.Builder.buildTunnelModeTransform(java.net.InetAddress,android.net.IpSecManager.SecurityParameterIndex) -ExecutorRegistration: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler): - Registration methods should have overload that accepts delivery Executor: `setOnRtpRxNoticeListener` +ExecutorRegistration: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler): GenericException: android.app.prediction.AppPredictor#finalize(): @@ -183,8 +182,7 @@ SamShouldBeLast: android.media.AudioRecordingMonitor#registerAudioRecordingCallb SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler): -SamShouldBeLast: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler): - SAM-compatible parameters (such as parameter 2, "listener", in android.media.MediaPlayer.setOnRtpRxNoticeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions +SamShouldBeLast: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler): SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler): diff --git a/core/java/android/uwb/AngleMeasurement.java b/core/java/android/uwb/AngleMeasurement.java index cf32b922078e..33bc121d8555 100644 --- a/core/java/android/uwb/AngleMeasurement.java +++ b/core/java/android/uwb/AngleMeasurement.java @@ -20,6 +20,8 @@ import android.annotation.FloatRange; import android.os.Parcel; import android.os.Parcelable; +import java.util.Objects; + /** * Angle measurement * @@ -75,6 +77,32 @@ public final class AngleMeasurement implements Parcelable { return mConfidenceLevel; } + /** + * @hide + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof AngleMeasurement) { + AngleMeasurement other = (AngleMeasurement) obj; + return mRadians == other.getRadians() + && mErrorRadians == other.getErrorRadians() + && mConfidenceLevel == other.getConfidenceLevel(); + } + return false; + } + + /** + * @hide + */ + @Override + public int hashCode() { + return Objects.hash(mRadians, mErrorRadians, mConfidenceLevel); + } + @Override public int describeContents() { return 0; diff --git a/core/java/android/uwb/AngleOfArrivalMeasurement.java b/core/java/android/uwb/AngleOfArrivalMeasurement.java index 646bd42cef2a..cd5af691ed51 100644 --- a/core/java/android/uwb/AngleOfArrivalMeasurement.java +++ b/core/java/android/uwb/AngleOfArrivalMeasurement.java @@ -21,6 +21,8 @@ import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; +import java.util.Objects; + /** * Represents an angle of arrival measurement between two devices using Ultra Wideband * @@ -72,6 +74,31 @@ public final class AngleOfArrivalMeasurement implements Parcelable { return mAltitudeAngleMeasurement; } + /** + * @hide + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof AngleOfArrivalMeasurement) { + AngleOfArrivalMeasurement other = (AngleOfArrivalMeasurement) obj; + return mAzimuthAngleMeasurement.equals(other.getAzimuth()) + && mAltitudeAngleMeasurement.equals(other.getAltitude()); + } + return false; + } + + /** + * @hide + */ + @Override + public int hashCode() { + return Objects.hash(mAzimuthAngleMeasurement, mAltitudeAngleMeasurement); + } + @Override public int describeContents() { return 0; diff --git a/core/java/android/uwb/DistanceMeasurement.java b/core/java/android/uwb/DistanceMeasurement.java index 9561be449a19..c959840c51ba 100644 --- a/core/java/android/uwb/DistanceMeasurement.java +++ b/core/java/android/uwb/DistanceMeasurement.java @@ -17,9 +17,12 @@ package android.uwb; import android.annotation.FloatRange; +import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; +import java.util.Objects; + /** * A data point for the distance measurement * @@ -71,6 +74,32 @@ public final class DistanceMeasurement implements Parcelable { return mConfidenceLevel; } + /** + * @hide + */ + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof DistanceMeasurement) { + DistanceMeasurement other = (DistanceMeasurement) obj; + return mMeters == other.getMeters() + && mErrorMeters == other.getErrorMeters() + && mConfidenceLevel == other.getConfidenceLevel(); + } + return false; + } + + /** + * @hide + */ + @Override + public int hashCode() { + return Objects.hash(mMeters, mErrorMeters, mConfidenceLevel); + } + @Override public int describeContents() { return 0; diff --git a/core/java/android/uwb/RangingMeasurement.java b/core/java/android/uwb/RangingMeasurement.java index d4d7fb23959a..f1c316289653 100644 --- a/core/java/android/uwb/RangingMeasurement.java +++ b/core/java/android/uwb/RangingMeasurement.java @@ -26,6 +26,7 @@ import android.os.SystemClock; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Objects; /** * Representation of a ranging measurement between the local device and a remote device @@ -129,6 +130,35 @@ public final class RangingMeasurement implements Parcelable { return mAngleOfArrivalMeasurement; } + /** + * @hide + */ + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof RangingMeasurement) { + RangingMeasurement other = (RangingMeasurement) obj; + return mRemoteDeviceAddress.equals(other.getRemoteDeviceAddress()) + && mStatus == other.getStatus() + && mElapsedRealtimeNanos == other.getElapsedRealtimeNanos() + && mDistanceMeasurement.equals(other.getDistance()) + && mAngleOfArrivalMeasurement.equals(other.getAngleOfArrival()); + } + return false; + } + + /** + * @hide + */ + @Override + public int hashCode() { + return Objects.hash(mRemoteDeviceAddress, mStatus, mElapsedRealtimeNanos, + mDistanceMeasurement, mAngleOfArrivalMeasurement); + } + @Override public int describeContents() { return 0; diff --git a/core/java/android/uwb/RangingParams.java b/core/java/android/uwb/RangingParams.java index c5d4807859b5..f23d9ed0dd3a 100644 --- a/core/java/android/uwb/RangingParams.java +++ b/core/java/android/uwb/RangingParams.java @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; /** @@ -201,6 +202,43 @@ public final class RangingParams implements Parcelable { return new PersistableBundle(mSpecificationParameters); } + /** + * @hide + */ + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof RangingParams) { + RangingParams other = (RangingParams) obj; + + return mIsInitiator == other.mIsInitiator + && mIsController == other.mIsController + && mSamplePeriod.equals(other.mSamplePeriod) + && mLocalDeviceAddress.equals(other.mLocalDeviceAddress) + && mRemoteDeviceAddresses.equals(other.mRemoteDeviceAddresses) + && mChannelNumber == other.mChannelNumber + && mTransmitPreambleCodeIndex == other.mTransmitPreambleCodeIndex + && mReceivePreambleCodeIndex == other.mReceivePreambleCodeIndex + && mStsPhyPacketType == other.mStsPhyPacketType + && mSpecificationParameters.size() == other.mSpecificationParameters.size() + && mSpecificationParameters.kindofEquals(other.mSpecificationParameters); + } + return false; + } + + /** + * @hide + */ + @Override + public int hashCode() { + return Objects.hash(mIsInitiator, mIsController, mSamplePeriod, mLocalDeviceAddress, + mRemoteDeviceAddresses, mChannelNumber, mTransmitPreambleCodeIndex, + mReceivePreambleCodeIndex, mStsPhyPacketType, mSpecificationParameters); + } + @Override public int describeContents() { return 0; diff --git a/core/java/android/uwb/RangingReport.java b/core/java/android/uwb/RangingReport.java index 1d340b4b0358..45180bfa6981 100644 --- a/core/java/android/uwb/RangingReport.java +++ b/core/java/android/uwb/RangingReport.java @@ -17,11 +17,13 @@ package android.uwb; import android.annotation.NonNull; +import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * This class contains the UWB ranging data @@ -50,6 +52,31 @@ public final class RangingReport implements Parcelable { return mRangingMeasurements; } + /** + * @hide + */ + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof RangingReport) { + RangingReport other = (RangingReport) obj; + return mRangingMeasurements.equals(other.getMeasurements()); + } + + return false; + } + + /** + * @hide + */ + @Override + public int hashCode() { + return Objects.hash(mRangingMeasurements); + } + @Override public int describeContents() { return 0; diff --git a/core/java/android/uwb/TEST_MAPPING b/core/java/android/uwb/TEST_MAPPING new file mode 100644 index 000000000000..9e50bd64d089 --- /dev/null +++ b/core/java/android/uwb/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit": [ + { + "name": "UwbManagerTests" + } + ] +}
\ No newline at end of file diff --git a/core/java/android/window/DisplayAreaOrganizer.java b/core/java/android/window/DisplayAreaOrganizer.java index 6ec093e045fa..bc3e35ccb8a9 100644 --- a/core/java/android/window/DisplayAreaOrganizer.java +++ b/core/java/android/window/DisplayAreaOrganizer.java @@ -88,9 +88,11 @@ public class DisplayAreaOrganizer extends WindowOrganizer { public static final int FEATURE_VENDOR_FIRST = FEATURE_SYSTEM_LAST + 1; /** - * Registers a DisplayAreaOrganizer to manage display areas for a given feature. + * Registers a DisplayAreaOrganizer to manage display areas for a given feature. A feature can + * not be registered by multiple organizers at the same time. * * @return a list of display areas that should be managed by the organizer. + * @throws IllegalStateException if the feature has already been registered. */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) @CallSuper diff --git a/core/java/android/window/IDisplayAreaOrganizerController.aidl b/core/java/android/window/IDisplayAreaOrganizerController.aidl index 8943847073c7..edabcf8ad0de 100644 --- a/core/java/android/window/IDisplayAreaOrganizerController.aidl +++ b/core/java/android/window/IDisplayAreaOrganizerController.aidl @@ -24,9 +24,11 @@ import android.window.IDisplayAreaOrganizer; interface IDisplayAreaOrganizerController { /** - * Registers a DisplayAreaOrganizer to manage display areas for a given feature. + * Registers a DisplayAreaOrganizer to manage display areas for a given feature. A feature can + * not be registered by multiple organizers at the same time. * * @return a list of display areas that should be managed by the organizer. + * @throws IllegalStateException if the feature has already been registered. */ ParceledListSlice<DisplayAreaAppearedInfo> registerOrganizer(in IDisplayAreaOrganizer organizer, int displayAreaFeature); diff --git a/core/tests/uwbtests/Android.bp b/core/tests/uwbtests/Android.bp new file mode 100644 index 000000000000..c41c346b131a --- /dev/null +++ b/core/tests/uwbtests/Android.bp @@ -0,0 +1,28 @@ +// Copyright 2020 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. + +android_test { + name: "UwbManagerTests", + static_libs: [ + "androidx.test.ext.junit", + "androidx.test.rules", + ], + libs: [ + "android.test.runner", + ], + srcs: ["src/**/*.java"], + platform_apis: true, + certificate: "platform", + test_suites: ["device-tests"], +} diff --git a/core/tests/uwbtests/AndroidManifest.xml b/core/tests/uwbtests/AndroidManifest.xml new file mode 100644 index 000000000000..dc991ff636d2 --- /dev/null +++ b/core/tests/uwbtests/AndroidManifest.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="android.uwb"> + + <application> + <uses-library android:name="android.test.runner" /> + </application> + + <!-- This is a self-instrumenting test package. --> + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="android.uwb" + android:label="UWB Manager Tests"> + </instrumentation> + +</manifest> + diff --git a/core/tests/uwbtests/AndroidTest.xml b/core/tests/uwbtests/AndroidTest.xml new file mode 100644 index 000000000000..ff4b668cc625 --- /dev/null +++ b/core/tests/uwbtests/AndroidTest.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<configuration description="Config for UWB Manager test cases"> + <option name="test-suite-tag" value="apct"/> + <option name="test-suite-tag" value="apct-instrumentation"/> + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="cleanup-apks" value="true" /> + <option name="test-file-name" value="UwbManagerTests.apk" /> + </target_preparer> + + <option name="test-suite-tag" value="apct"/> + <option name="test-tag" value="UwbManagerTests"/> + + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="android.uwb" /> + <option name="hidden-api-checks" value="false"/> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/> + </test> +</configuration> diff --git a/core/tests/uwbtests/src/android/uwb/AngleMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/AngleMeasurementTest.java new file mode 100644 index 000000000000..7769c28202f2 --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/AngleMeasurementTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2020 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.uwb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.os.Parcel; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test of {@link AngleMeasurement}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class AngleMeasurementTest { + private static final double EPSILON = 0.00000000001; + + @Test + public void testBuilder() { + double radians = 0.1234; + double errorRadians = 0.5678; + double confidence = 0.5; + + AngleMeasurement.Builder builder = new AngleMeasurement.Builder(); + tryBuild(builder, false); + + builder.setRadians(radians); + tryBuild(builder, false); + + builder.setErrorRadians(errorRadians); + tryBuild(builder, false); + + builder.setConfidenceLevel(confidence); + AngleMeasurement measurement = tryBuild(builder, true); + + assertEquals(measurement.getRadians(), radians, 0); + assertEquals(measurement.getErrorRadians(), errorRadians, 0); + assertEquals(measurement.getConfidenceLevel(), confidence, 0); + } + + private AngleMeasurement tryBuild(AngleMeasurement.Builder builder, boolean expectSuccess) { + AngleMeasurement measurement = null; + try { + measurement = builder.build(); + if (!expectSuccess) { + fail("Expected AngleMeasurement.Builder.build() to fail, but it succeeded"); + } + } catch (IllegalStateException e) { + if (expectSuccess) { + fail("Expected AngleMeasurement.Builder.build() to succeed, but it failed"); + } + } + return measurement; + } + + @Test + public void testParcel() { + Parcel parcel = Parcel.obtain(); + AngleMeasurement measurement = UwbTestUtils.getAngleMeasurement(); + measurement.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + AngleMeasurement fromParcel = AngleMeasurement.CREATOR.createFromParcel(parcel); + assertEquals(measurement, fromParcel); + } +} diff --git a/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java new file mode 100644 index 000000000000..077b08f41b59 --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java @@ -0,0 +1,89 @@ +/* + * Copyright 2020 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.uwb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.os.Parcel; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test of {@link AngleOfArrivalMeasurement}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class AngleOfArrivalMeasurementTest { + + @Test + public void testBuilder() { + AngleMeasurement azimuth = UwbTestUtils.getAngleMeasurement(); + AngleMeasurement altitude = UwbTestUtils.getAngleMeasurement(); + + AngleOfArrivalMeasurement.Builder builder = new AngleOfArrivalMeasurement.Builder(); + tryBuild(builder, false); + + builder.setAltitudeAngleMeasurement(altitude); + tryBuild(builder, false); + + builder.setAzimuthAngleMeasurement(azimuth); + AngleOfArrivalMeasurement measurement = tryBuild(builder, true); + + assertEquals(azimuth, measurement.getAzimuth()); + assertEquals(altitude, measurement.getAltitude()); + } + + private AngleMeasurement getAngleMeasurement(double radian, double error, double confidence) { + return new AngleMeasurement.Builder() + .setRadians(radian) + .setErrorRadians(error) + .setConfidenceLevel(confidence) + .build(); + } + + private AngleOfArrivalMeasurement tryBuild(AngleOfArrivalMeasurement.Builder builder, + boolean expectSuccess) { + AngleOfArrivalMeasurement measurement = null; + try { + measurement = builder.build(); + if (!expectSuccess) { + fail("Expected AngleOfArrivalMeasurement.Builder.build() to fail"); + } + } catch (IllegalStateException e) { + if (expectSuccess) { + fail("Expected AngleOfArrivalMeasurement.Builder.build() to succeed"); + } + } + return measurement; + } + + @Test + public void testParcel() { + Parcel parcel = Parcel.obtain(); + AngleOfArrivalMeasurement measurement = UwbTestUtils.getAngleOfArrivalMeasurement(); + measurement.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + AngleOfArrivalMeasurement fromParcel = + AngleOfArrivalMeasurement.CREATOR.createFromParcel(parcel); + assertEquals(measurement, fromParcel); + } +} diff --git a/core/tests/uwbtests/src/android/uwb/DistanceMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/DistanceMeasurementTest.java new file mode 100644 index 000000000000..439c884723be --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/DistanceMeasurementTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2020 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.uwb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.os.Parcel; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test of {@link DistanceMeasurement}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class DistanceMeasurementTest { + private static final double EPSILON = 0.00000000001; + + @Test + public void testBuilder() { + double meters = 0.12; + double error = 0.54; + double confidence = 0.99; + + DistanceMeasurement.Builder builder = new DistanceMeasurement.Builder(); + tryBuild(builder, false); + + builder.setMeters(meters); + tryBuild(builder, false); + + builder.setErrorMeters(error); + tryBuild(builder, false); + + builder.setConfidenceLevel(confidence); + DistanceMeasurement measurement = tryBuild(builder, true); + + assertEquals(meters, measurement.getMeters(), 0); + assertEquals(error, measurement.getErrorMeters(), 0); + assertEquals(confidence, measurement.getConfidenceLevel(), 0); + } + + private DistanceMeasurement tryBuild(DistanceMeasurement.Builder builder, + boolean expectSuccess) { + DistanceMeasurement measurement = null; + try { + measurement = builder.build(); + if (!expectSuccess) { + fail("Expected DistanceMeasurement.Builder.build() to fail"); + } + } catch (IllegalStateException e) { + if (expectSuccess) { + fail("Expected DistanceMeasurement.Builder.build() to succeed"); + } + } + return measurement; + } + + @Test + public void testParcel() { + Parcel parcel = Parcel.obtain(); + DistanceMeasurement measurement = UwbTestUtils.getDistanceMeasurement(); + measurement.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + DistanceMeasurement fromParcel = + DistanceMeasurement.CREATOR.createFromParcel(parcel); + assertEquals(measurement, fromParcel); + } +} diff --git a/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java new file mode 100644 index 000000000000..a7559d86221e --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2020 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.uwb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.os.Parcel; +import android.os.SystemClock; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test of {@link RangingMeasurement}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class RangingMeasurementTest { + + @Test + public void testBuilder() { + int status = RangingMeasurement.RANGING_STATUS_SUCCESS; + UwbAddress address = UwbTestUtils.getUwbAddress(false); + long time = SystemClock.elapsedRealtimeNanos(); + AngleOfArrivalMeasurement angleMeasurement = UwbTestUtils.getAngleOfArrivalMeasurement(); + DistanceMeasurement distanceMeasurement = UwbTestUtils.getDistanceMeasurement(); + + RangingMeasurement.Builder builder = new RangingMeasurement.Builder(); + + builder.setStatus(status); + tryBuild(builder, false); + + builder.setElapsedRealtimeNanos(time); + tryBuild(builder, false); + + builder.setAngleOfArrivalMeasurement(angleMeasurement); + tryBuild(builder, false); + + builder.setDistanceMeasurement(distanceMeasurement); + tryBuild(builder, false); + + builder.setRemoteDeviceAddress(address); + RangingMeasurement measurement = tryBuild(builder, true); + + assertEquals(status, measurement.getStatus()); + assertEquals(address, measurement.getRemoteDeviceAddress()); + assertEquals(time, measurement.getElapsedRealtimeNanos()); + assertEquals(angleMeasurement, measurement.getAngleOfArrival()); + assertEquals(distanceMeasurement, measurement.getDistance()); + } + + private RangingMeasurement tryBuild(RangingMeasurement.Builder builder, + boolean expectSuccess) { + RangingMeasurement measurement = null; + try { + measurement = builder.build(); + if (!expectSuccess) { + fail("Expected RangingMeasurement.Builder.build() to fail"); + } + } catch (IllegalStateException e) { + if (expectSuccess) { + fail("Expected DistanceMeasurement.Builder.build() to succeed"); + } + } + return measurement; + } + + @Test + public void testParcel() { + Parcel parcel = Parcel.obtain(); + RangingMeasurement measurement = UwbTestUtils.getRangingMeasurement(); + measurement.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + RangingMeasurement fromParcel = RangingMeasurement.CREATOR.createFromParcel(parcel); + assertEquals(measurement, fromParcel); + } +} diff --git a/core/tests/uwbtests/src/android/uwb/RangingParamsTest.java b/core/tests/uwbtests/src/android/uwb/RangingParamsTest.java new file mode 100644 index 000000000000..c1fa5a5f6080 --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/RangingParamsTest.java @@ -0,0 +1,102 @@ +/* + * Copyright 2020 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.uwb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import android.os.Parcel; +import android.os.PersistableBundle; +import android.util.Log; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.time.Duration; + +/** + * Test of {@link RangingParams}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class RangingParamsTest { + + @Test + public void testParams_Build() { + UwbAddress local = UwbAddress.fromBytes(new byte[] {(byte) 0xA0, (byte) 0x57}); + UwbAddress remote = UwbAddress.fromBytes(new byte[] {(byte) 0x4D, (byte) 0x8C}); + int channel = 9; + int rxPreamble = 16; + int txPreamble = 21; + boolean isController = true; + boolean isInitiator = false; + @RangingParams.StsPhyPacketType int stsPhyType = RangingParams.STS_PHY_PACKET_TYPE_SP2; + Duration samplePeriod = Duration.ofSeconds(1, 234); + PersistableBundle specParams = new PersistableBundle(); + specParams.putString("protocol", "some_protocol"); + + RangingParams params = new RangingParams.Builder() + .setChannelNumber(channel) + .setReceivePreambleCodeIndex(rxPreamble) + .setTransmitPreambleCodeIndex(txPreamble) + .setLocalDeviceAddress(local) + .addRemoteDeviceAddress(remote) + .setIsController(isController) + .setIsInitiator(isInitiator) + .setSamplePeriod(samplePeriod) + .setStsPhPacketType(stsPhyType) + .setSpecificationParameters(specParams) + .build(); + + assertEquals(params.getLocalDeviceAddress(), local); + assertEquals(params.getRemoteDeviceAddresses().size(), 1); + assertEquals(params.getRemoteDeviceAddresses().get(0), remote); + assertEquals(params.getChannelNumber(), channel); + assertEquals(params.isController(), isController); + assertEquals(params.isInitiator(), isInitiator); + assertEquals(params.getRxPreambleIndex(), rxPreamble); + assertEquals(params.getTxPreambleIndex(), txPreamble); + assertEquals(params.getStsPhyPacketType(), stsPhyType); + assertEquals(params.getSamplingPeriod(), samplePeriod); + assertTrue(params.getSpecificationParameters().kindofEquals(specParams)); + } + + @Test + public void testParcel() { + Parcel parcel = Parcel.obtain(); + RangingParams params = new RangingParams.Builder() + .setChannelNumber(9) + .setReceivePreambleCodeIndex(16) + .setTransmitPreambleCodeIndex(21) + .setLocalDeviceAddress(UwbTestUtils.getUwbAddress(false)) + .addRemoteDeviceAddress(UwbTestUtils.getUwbAddress(true)) + .setIsController(false) + .setIsInitiator(true) + .setSamplePeriod(Duration.ofSeconds(2)) + .setStsPhPacketType(RangingParams.STS_PHY_PACKET_TYPE_SP1) + .build(); + params.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + RangingParams fromParcel = RangingParams.CREATOR.createFromParcel(parcel); + Log.w("bstack", "original: " + params.toString()); + Log.w("bstack", "parcel: " + fromParcel.toString()); + assertEquals(params, fromParcel); + } +} diff --git a/core/tests/uwbtests/src/android/uwb/RangingReportTest.java b/core/tests/uwbtests/src/android/uwb/RangingReportTest.java new file mode 100644 index 000000000000..64c48ba4b6f4 --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/RangingReportTest.java @@ -0,0 +1,90 @@ +/* + * Copyright 2020 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.uwb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.os.Parcel; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; + +/** + * Test of {@link RangingReport}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class RangingReportTest { + + @Test + public void testBuilder() { + List<RangingMeasurement> measurements = UwbTestUtils.getRangingMeasurements(5); + + RangingReport.Builder builder = new RangingReport.Builder(); + builder.addMeasurements(measurements); + RangingReport report = tryBuild(builder, true); + verifyMeasurementsEqual(measurements, report.getMeasurements()); + + + builder = new RangingReport.Builder(); + for (RangingMeasurement measurement : measurements) { + builder.addMeasurement(measurement); + } + report = tryBuild(builder, true); + verifyMeasurementsEqual(measurements, report.getMeasurements()); + } + + private void verifyMeasurementsEqual(List<RangingMeasurement> expected, + List<RangingMeasurement> actual) { + assertEquals(expected.size(), actual.size()); + for (int i = 0; i < expected.size(); i++) { + assertEquals(expected.get(i), actual.get(i)); + } + } + + private RangingReport tryBuild(RangingReport.Builder builder, + boolean expectSuccess) { + RangingReport report = null; + try { + report = builder.build(); + if (!expectSuccess) { + fail("Expected RangingReport.Builder.build() to fail"); + } + } catch (IllegalStateException e) { + if (expectSuccess) { + fail("Expected RangingReport.Builder.build() to succeed"); + } + } + return report; + } + + @Test + public void testParcel() { + Parcel parcel = Parcel.obtain(); + RangingReport report = UwbTestUtils.getRangingReports(5); + report.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + RangingReport fromParcel = RangingReport.CREATOR.createFromParcel(parcel); + assertEquals(report, fromParcel); + } +} diff --git a/core/tests/uwbtests/src/android/uwb/UwbAddressTest.java b/core/tests/uwbtests/src/android/uwb/UwbAddressTest.java new file mode 100644 index 000000000000..ccc88a9a5399 --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/UwbAddressTest.java @@ -0,0 +1,79 @@ +/* + * Copyright 2020 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.uwb; + +import static org.junit.Assert.assertEquals; + +import android.os.Parcel; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test of {@link UwbAddress}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class UwbAddressTest { + + @Test + public void testFromBytes_Short() { + runFromBytes(UwbAddress.SHORT_ADDRESS_BYTE_LENGTH); + } + + @Test + public void testFromBytes_Extended() { + runFromBytes(UwbAddress.EXTENDED_ADDRESS_BYTE_LENGTH); + } + + private void runFromBytes(int len) { + byte[] addressBytes = getByteArray(len); + UwbAddress address = UwbAddress.fromBytes(addressBytes); + assertEquals(address.size(), len); + assertEquals(addressBytes, address.toBytes()); + } + + private byte[] getByteArray(int len) { + byte[] res = new byte[len]; + for (int i = 0; i < len; i++) { + res[i] = (byte) i; + } + return res; + } + + @Test + public void testParcel_Short() { + runParcel(true); + } + + @Test + public void testParcel_Extended() { + runParcel(false); + } + + private void runParcel(boolean useShortAddress) { + Parcel parcel = Parcel.obtain(); + UwbAddress address = UwbTestUtils.getUwbAddress(useShortAddress); + address.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + UwbAddress fromParcel = UwbAddress.CREATOR.createFromParcel(parcel); + assertEquals(address, fromParcel); + } +} diff --git a/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java b/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java new file mode 100644 index 000000000000..62e0b629539b --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java @@ -0,0 +1,92 @@ +/* + * Copyright 2020 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.uwb; + +import android.os.SystemClock; + +import java.util.ArrayList; +import java.util.List; + +public class UwbTestUtils { + private UwbTestUtils() {} + + public static AngleMeasurement getAngleMeasurement() { + return new AngleMeasurement.Builder() + .setRadians(getDoubleInRange(-Math.PI, Math.PI)) + .setErrorRadians(getDoubleInRange(0, Math.PI)) + .setConfidenceLevel(getDoubleInRange(0, 1)) + .build(); + } + + public static AngleOfArrivalMeasurement getAngleOfArrivalMeasurement() { + return new AngleOfArrivalMeasurement.Builder() + .setAltitudeAngleMeasurement(getAngleMeasurement()) + .setAzimuthAngleMeasurement(getAngleMeasurement()) + .build(); + } + + public static DistanceMeasurement getDistanceMeasurement() { + return new DistanceMeasurement.Builder() + .setMeters(getDoubleInRange(0, 100)) + .setErrorMeters(getDoubleInRange(0, 10)) + .setConfidenceLevel(getDoubleInRange(0, 1)) + .build(); + } + + public static RangingMeasurement getRangingMeasurement() { + return getRangingMeasurement(getUwbAddress(false)); + } + + public static RangingMeasurement getRangingMeasurement(UwbAddress address) { + return new RangingMeasurement.Builder() + .setDistanceMeasurement(getDistanceMeasurement()) + .setAngleOfArrivalMeasurement(getAngleOfArrivalMeasurement()) + .setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()) + .setRemoteDeviceAddress(address != null ? address : getUwbAddress(false)) + .setStatus(RangingMeasurement.RANGING_STATUS_SUCCESS) + .build(); + } + + public static List<RangingMeasurement> getRangingMeasurements(int num) { + List<RangingMeasurement> result = new ArrayList<>(); + for (int i = 0; i < num; i++) { + result.add(getRangingMeasurement()); + } + return result; + } + + public static RangingReport getRangingReports(int numMeasurements) { + RangingReport.Builder builder = new RangingReport.Builder(); + for (int i = 0; i < numMeasurements; i++) { + builder.addMeasurement(getRangingMeasurement()); + } + return builder.build(); + } + + private static double getDoubleInRange(double min, double max) { + return min + (max - min) * Math.random(); + } + + public static UwbAddress getUwbAddress(boolean isShortAddress) { + byte[] addressBytes = new byte[isShortAddress ? UwbAddress.SHORT_ADDRESS_BYTE_LENGTH : + UwbAddress.EXTENDED_ADDRESS_BYTE_LENGTH]; + for (int i = 0; i < addressBytes.length; i++) { + addressBytes[i] = (byte) getDoubleInRange(1, 255); + } + return UwbAddress.fromBytes(addressBytes); + } +} diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index b143be7b4d6a..441c16322645 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -327,7 +327,7 @@ public class Typeface { * 1) Create Typeface from ttf file. * <pre> * <code> - * Typeface.Builder buidler = new Typeface.Builder("your_font_file.ttf"); + * Typeface.Builder builder = new Typeface.Builder("your_font_file.ttf"); * Typeface typeface = builder.build(); * </code> * </pre> @@ -335,7 +335,7 @@ public class Typeface { * 2) Create Typeface from ttc file in assets directory. * <pre> * <code> - * Typeface.Builder buidler = new Typeface.Builder(getAssets(), "your_font_file.ttc"); + * Typeface.Builder builder = new Typeface.Builder(getAssets(), "your_font_file.ttc"); * builder.setTtcIndex(2); // Set index of font collection. * Typeface typeface = builder.build(); * </code> @@ -344,7 +344,7 @@ public class Typeface { * 3) Create Typeface with variation settings. * <pre> * <code> - * Typeface.Builder buidler = new Typeface.Builder("your_font_file.ttf"); + * Typeface.Builder builder = new Typeface.Builder("your_font_file.ttf"); * builder.setFontVariationSettings("'wght' 700, 'slnt' 20, 'ital' 1"); * builder.setWeight(700); // Tell the system that this is a bold font. * builder.setItalic(true); // Tell the system that this is an italic style font. diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java index 4b208ce1ec37..5c1f89313ec0 100644 --- a/media/java/android/media/MediaCas.java +++ b/media/java/android/media/MediaCas.java @@ -676,17 +676,9 @@ public final class MediaCas implements AutoCloseable { return null; } - /** - * Instantiate a CA system of the specified system id. - * - * @param CA_system_id The system id of the CA system. - * - * @throws UnsupportedCasException if the device does not support the - * specified CA system. - */ - public MediaCas(int CA_system_id) throws UnsupportedCasException { + private void createPlugin(int casSystemId) throws UnsupportedCasException { try { - mCasSystemId = CA_system_id; + mCasSystemId = casSystemId; mUserId = ActivityManager.getCurrentUser(); IMediaCasService service = getService(); android.hardware.cas.V1_2.IMediaCasService serviceV12 = @@ -696,16 +688,16 @@ public final class MediaCas implements AutoCloseable { android.hardware.cas.V1_1.IMediaCasService.castFrom(service); if (serviceV11 == null) { Log.d(TAG, "Used cas@1_0 interface to create plugin"); - mICas = service.createPlugin(CA_system_id, mBinder); + mICas = service.createPlugin(casSystemId, mBinder); } else { Log.d(TAG, "Used cas@1.1 interface to create plugin"); - mICas = mICasV11 = serviceV11.createPluginExt(CA_system_id, mBinder); + mICas = mICasV11 = serviceV11.createPluginExt(casSystemId, mBinder); } } else { Log.d(TAG, "Used cas@1.2 interface to create plugin"); mICas = mICasV11 = mICasV12 = android.hardware.cas.V1_2.ICas - .castFrom(serviceV12.createPluginExt(CA_system_id, mBinder)); + .castFrom(serviceV12.createPluginExt(casSystemId, mBinder)); } } catch(Exception e) { Log.e(TAG, "Failed to create plugin: " + e); @@ -713,11 +705,37 @@ public final class MediaCas implements AutoCloseable { } finally { if (mICas == null) { throw new UnsupportedCasException( - "Unsupported CA_system_id " + CA_system_id); + "Unsupported casSystemId " + casSystemId); } } } + private void registerClient(@NonNull Context context, + @Nullable String tvInputServiceSessionId, @PriorityHintUseCaseType int priorityHint) { + + mTunerResourceManager = (TunerResourceManager) + context.getSystemService(Context.TV_TUNER_RESOURCE_MGR_SERVICE); + if (mTunerResourceManager != null) { + int[] clientId = new int[1]; + ResourceClientProfile profile = + new ResourceClientProfile(tvInputServiceSessionId, priorityHint); + mTunerResourceManager.registerClientProfile( + profile, context.getMainExecutor(), mResourceListener, clientId); + mClientId = clientId[0]; + } + } + /** + * Instantiate a CA system of the specified system id. + * + * @param casSystemId The system id of the CA system. + * + * @throws UnsupportedCasException if the device does not support the + * specified CA system. + */ + public MediaCas(int casSystemId) throws UnsupportedCasException { + createPlugin(casSystemId); + } + /** * Instantiate a CA system of the specified system id. * @@ -733,19 +751,35 @@ public final class MediaCas implements AutoCloseable { public MediaCas(@NonNull Context context, int casSystemId, @Nullable String tvInputServiceSessionId, @PriorityHintUseCaseType int priorityHint) throws UnsupportedCasException { - this(casSystemId); - Objects.requireNonNull(context, "context must not be null"); - mTunerResourceManager = (TunerResourceManager) - context.getSystemService(Context.TV_TUNER_RESOURCE_MGR_SERVICE); - if (mTunerResourceManager != null) { - int[] clientId = new int[1]; - ResourceClientProfile profile = - new ResourceClientProfile(tvInputServiceSessionId, priorityHint); - mTunerResourceManager.registerClientProfile( - profile, context.getMainExecutor(), mResourceListener, clientId); - mClientId = clientId[0]; - } + createPlugin(casSystemId); + registerClient(context, tvInputServiceSessionId, priorityHint); + } + /** + * Instantiate a CA system of the specified system id with EvenListener. + * + * @param context the context of the caller. + * @param casSystemId The system id of the CA system. + * @param tvInputServiceSessionId The Id of the session opened in TV Input Service (TIS) + * {@link android.media.tv.TvInputService#onCreateSession(String, String)} + * @param priorityHint priority hint from the use case type for new created CAS system. + * @param listener the event listener to be set. + * @param handler the handler whose looper the event listener will be called on. + * If handler is null, we'll try to use current thread's looper, or the main + * looper. If neither are available, an internal thread will be created instead. + * + * @throws UnsupportedCasException if the device does not support the + * specified CA system. + */ + public MediaCas(@NonNull Context context, int casSystemId, + @Nullable String tvInputServiceSessionId, + @PriorityHintUseCaseType int priorityHint, + @Nullable Handler handler, @Nullable EventListener listener) + throws UnsupportedCasException { + Objects.requireNonNull(context, "context must not be null"); + setEventListener(listener, handler); + createPlugin(casSystemId); + registerClient(context, tvInputServiceSessionId, priorityHint); } IHwBinder getBinder() { diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 655454466b3d..42e39101de13 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -16,9 +16,6 @@ package android.media; -import static android.Manifest.permission.BIND_IMS_SERVICE; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; - import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -86,7 +83,6 @@ import java.util.BitSet; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Scanner; import java.util.Set; import java.util.UUID; @@ -2113,8 +2109,8 @@ public class MediaPlayer extends PlayerBase mOnInfoListener = null; mOnVideoSizeChangedListener = null; mOnTimedTextListener = null; - mOnRtpRxNoticeListener = null; - mOnRtpRxNoticeHandler = null; + mOnImsRxNoticeListener = null; + mOnImsRxNoticeHandler = null; synchronized (mTimeProviderLock) { if (mTimeProvider != null) { mTimeProvider.close(); @@ -3327,7 +3323,7 @@ public class MediaPlayer extends PlayerBase private static final int MEDIA_META_DATA = 202; private static final int MEDIA_DRM_INFO = 210; private static final int MEDIA_TIME_DISCONTINUITY = 211; - private static final int MEDIA_RTP_RX_NOTICE = 300; + private static final int MEDIA_IMS_RX_NOTICE = 300; private static final int MEDIA_AUDIO_ROUTING_CHANGED = 10000; private TimeProvider mTimeProvider; @@ -3637,34 +3633,31 @@ public class MediaPlayer extends PlayerBase } return; - case MEDIA_RTP_RX_NOTICE: - final OnRtpRxNoticeListener rtpRxNoticeListener = mOnRtpRxNoticeListener; - final Handler rtpRxNoticeHandler = mOnRtpRxNoticeHandler; - if (rtpRxNoticeListener == null) { + case MEDIA_IMS_RX_NOTICE: + final OnImsRxNoticeListener imsRxNoticeListener; + final Handler imsRxNoticeHandler; + imsRxNoticeListener = mOnImsRxNoticeListener; + imsRxNoticeHandler = mOnImsRxNoticeHandler; + if (imsRxNoticeListener == null) { return; } if (msg.obj instanceof Parcel) { Parcel parcel = (Parcel) msg.obj; - parcel.setDataPosition(0); - int noticeType; - int[] data; + byte[] event; try { - noticeType = parcel.readInt(); - int numOfArgs = parcel.dataAvail() / 4; - data = new int[numOfArgs]; - for (int i = 0; i < numOfArgs; i++) { - data[i] = parcel.readInt(); - } + event = parcel.marshall(); } finally { parcel.recycle(); } - if (rtpRxNoticeHandler == null) { - rtpRxNoticeListener.onRtpRxNotice(mMediaPlayer, noticeType, data); + if (imsRxNoticeHandler == null) { + imsRxNoticeListener.onImsRxNotice(mMediaPlayer, event); } else { - rtpRxNoticeHandler.post( - () -> - rtpRxNoticeListener - .onRtpRxNotice(mMediaPlayer, noticeType, data)); + imsRxNoticeHandler.post(new Runnable() { + @Override + public void run() { + imsRxNoticeListener.onImsRxNotice(mMediaPlayer, event); + } + }); } } return; @@ -4110,18 +4103,18 @@ public class MediaPlayer extends PlayerBase /** * Interface definition of a callback to be invoked when - * RTP Rx connection has a notice. + * IMS Rx connection has a notice. * - * @see #setOnRtpRxNoticeListener + * @see MediaPlayer.setOnImsRxNoticeListener * * @hide */ @SystemApi - public interface OnRtpRxNoticeListener + public interface OnImsRxNoticeListener { /** - * Called when an RTP Rx connection has a notice. - * <p> + * Called to indicate an IMS event noticed from native media frameworks. + * <p></p> * Basic format. All TYPE and ARG are 4 bytes unsigned integer in native byte order. * <pre>{@code * 0 4 8 12 @@ -4176,14 +4169,14 @@ public class MediaPlayer extends PlayerBase * TYPE 205 - Transport layer Feedback message. (RFC-5104 Sec.4.2) * 0 4 8 12 * +----------------+---------------+----------------+----------------+ - * | 205 |FB type(1 or 3)| SSRC | Value | + * | 205 | SSRC | FB type(1 or 3)| value | * +----------------+---------------+----------------+----------------+ + * SSRC + * - Remote side's SSRC value of the media sender (RFC-3550 Sec.5.1) * Feedback (FB) type: determines the type of the event. * - if 1, we received a NACK request from the remote side. * - if 3, we received a TMMBR (Temporary Maximum Media Stream Bit Rate Request) from * the remote side. - * SSRC - * - Remote side's SSRC value of the media sender (RFC-3550 Sec.5.1) * Value: the FCI (Feedback Control Information) depending on the value of FB type * - if FB type is 1, the Generic NACK as specified in RFC-4585 Sec.6.2.1 * - if FB type is 3, the TMMBR as specified in RFC-5104 Sec.4.2.1.1 @@ -4192,13 +4185,13 @@ public class MediaPlayer extends PlayerBase * TYPE 206 - Payload-specific Feedback message. (RFC-5104 Sec.4.3) * 0 4 8 * +----------------+---------------+----------------+ - * | 206 |FB type(1 or 4)| SSRC | + * | 206 | SSRC | FB type(1 or 4)| * +----------------+---------------+----------------+ + * SSRC + * - Remote side's SSRC value of the media sender (RFC-3550 Sec.5.1) * Feedback (FB) type: determines the type of the event. * - if 1, we received a PLI request from the remote side. * - if 4, we received a FIR request from the remote side. - * SSRC - * - Remote side's SSRC value of the media sender (RFC-3550 Sec.5.1) * * * TYPE 300 - CVO (RTP Extension) message. @@ -4219,39 +4212,34 @@ public class MediaPlayer extends PlayerBase * }</pre> * * @param mp the {@code MediaPlayer} associated with this callback. - * @param noticeType TYPE of the event. - * @param params RTP Rx media data serialized as int[] array. + * @param event an IMS media event serialized as byte[] array. */ - void onRtpRxNotice(@NonNull MediaPlayer mp, int noticeType, @NonNull int[] params); + void onImsRxNotice(@NonNull MediaPlayer mp, @NonNull byte[] event); } /** - * Sets the listener to be invoked when an RTP Rx connection has a notice. - * The listener is required if MediaPlayer is configured for RTPSource by - * MediaPlayer.setDataSource(String8 rtpParams) of mediaplayer.h. + * Register a callback to be invoked when IMS Rx connection has a notice. + * The callback required if mediaplayer configured for RTPSource by + * MediaPlayer.setDataSource(String8 rtpParams) of mediaplayer.h * - * @see OnRtpRxNoticeListener + * @see MediaPlayer.OnImsRxNoticeListener * - * @param listener the listener called after a notice from RTP Rx - * @param handler the {@link Handler} that receives RTP Tx events + * @param listener the callback that will be run + * @param handler Specifies Handler object for the thread on which to execute + * the callback. If null, the handler on the main looper will be used. * * @hide */ @SystemApi @RequiresPermission("android.permission.BIND_IMS_SERVICE") - public void setOnRtpRxNoticeListener( - @NonNull Context context, - @NonNull OnRtpRxNoticeListener listener, @Nullable Handler handler) { - Objects.requireNonNull(context); - Preconditions.checkArgument( - context.checkSelfPermission(BIND_IMS_SERVICE) == PERMISSION_GRANTED, - "android.permission.BIND_IMS_SERVICE permission not granted."); - mOnRtpRxNoticeListener = Objects.requireNonNull(listener); - mOnRtpRxNoticeHandler = handler; - } - - private OnRtpRxNoticeListener mOnRtpRxNoticeListener; - private Handler mOnRtpRxNoticeHandler; + public void setOnImsRxNoticeListener( + @Nullable OnImsRxNoticeListener listener, @Nullable Handler handler) { + mOnImsRxNoticeListener = listener; + mOnImsRxNoticeHandler = handler; + } + + private OnImsRxNoticeListener mOnImsRxNoticeListener; + private Handler mOnImsRxNoticeHandler; /** * Register a callback to be invoked when a selected track has timed metadata available. diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java index 9fc8f0b5a3c3..ef6dab5a45fb 100644 --- a/services/core/java/com/android/server/RescueParty.java +++ b/services/core/java/com/android/server/RescueParty.java @@ -56,6 +56,7 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -100,6 +101,10 @@ public class RescueParty { private static final String PROP_VIRTUAL_DEVICE = "ro.hardware.virtual_device"; private static final String PROP_DEVICE_CONFIG_DISABLE_FLAG = "persist.device_config.configuration.disable_rescue_party"; + private static final String PROP_DISABLE_FACTORY_RESET_FLAG = + "persist.device_config.configuration.disable_rescue_party_factory_reset"; + // The DeviceConfig namespace containing all RescueParty switches. + private static final String NAMESPACE_CONFIGURATION = "configuration"; private static final int PERSISTENT_MASK = ApplicationInfo.FLAG_PERSISTENT | ApplicationInfo.FLAG_SYSTEM; @@ -215,6 +220,10 @@ public class RescueParty { if (SettingsToPropertiesMapper.isNativeFlagsResetPerformed()) { String[] resetNativeCategories = SettingsToPropertiesMapper.getResetNativeCategories(); for (int i = 0; i < resetNativeCategories.length; i++) { + // Don't let RescueParty reset the namespace for RescueParty switches. + if (NAMESPACE_CONFIGURATION.equals(resetNativeCategories[i])) { + continue; + } DeviceConfig.resetToDefaults(Settings.RESET_MODE_TRUSTED_DEFAULTS, resetNativeCategories[i]); } @@ -225,8 +234,10 @@ public class RescueParty { * Get the next rescue level. This indicates the next level of mitigation that may be taken. */ private static int getNextRescueLevel() { + int maxRescueLevel = SystemProperties.getBoolean(PROP_DISABLE_FACTORY_RESET_FLAG, false) + ? LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS : LEVEL_FACTORY_RESET; return MathUtils.constrain(SystemProperties.getInt(PROP_RESCUE_LEVEL, LEVEL_NONE) + 1, - LEVEL_NONE, LEVEL_FACTORY_RESET); + LEVEL_NONE, maxRescueLevel); } /** @@ -349,12 +360,30 @@ public class RescueParty { private static void resetDeviceConfig(Context context, int resetMode, @Nullable String failedPackage) { if (!shouldPerformScopedResets() || failedPackage == null) { - DeviceConfig.resetToDefaults(resetMode, /*namespace=*/ null); + resetAllAffectedNamespaces(context, resetMode); } else { performScopedReset(context, resetMode, failedPackage); } } + private static void resetAllAffectedNamespaces(Context context, int resetMode) { + RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context); + Set<String> allAffectedNamespaces = rescuePartyObserver.getAllAffectedNamespaceSet(); + + Slog.w(TAG, + "Performing reset for all affected namespaces: " + + Arrays.toString(allAffectedNamespaces.toArray())); + Iterator<String> it = allAffectedNamespaces.iterator(); + while (it.hasNext()) { + String namespace = it.next(); + // Don't let RescueParty reset the namespace for RescueParty switches. + if (NAMESPACE_CONFIGURATION.equals(namespace)) { + continue; + } + DeviceConfig.resetToDefaults(resetMode, namespace); + } + } + private static boolean shouldPerformScopedResets() { int rescueLevel = MathUtils.constrain( SystemProperties.getInt(PROP_RESCUE_LEVEL, LEVEL_NONE), @@ -367,16 +396,21 @@ public class RescueParty { RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context); Set<String> affectedNamespaces = rescuePartyObserver.getAffectedNamespaceSet( failedPackage); - if (affectedNamespaces == null) { - DeviceConfig.resetToDefaults(resetMode, /*namespace=*/ null); - } else { + // If we can't find namespaces affected for current package, + // skip this round of reset. + if (affectedNamespaces != null) { Slog.w(TAG, "Performing scoped reset for package: " + failedPackage + ", affected namespaces: " + Arrays.toString(affectedNamespaces.toArray())); Iterator<String> it = affectedNamespaces.iterator(); while (it.hasNext()) { - DeviceConfig.resetToDefaults(resetMode, it.next()); + String namespace = it.next(); + // Don't let RescueParty reset the namespace for RescueParty switches. + if (NAMESPACE_CONFIGURATION.equals(namespace)) { + continue; + } + DeviceConfig.resetToDefaults(resetMode, namespace); } } } @@ -514,6 +548,10 @@ public class RescueParty { return mCallingPackageNamespaceSetMap.get(failedPackage); } + private synchronized Set<String> getAllAffectedNamespaceSet() { + return new HashSet<String>(mNamespaceCallingPackageSetMap.keySet()); + } + private synchronized Set<String> getCallingPackagesSet(String namespace) { return mNamespaceCallingPackageSetMap.get(namespace); } diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index a068d2b7c823..4dea3c09cc31 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -63,6 +63,9 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS import static com.android.server.wm.ActivityTaskManagerService.ANIMATE; import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_SUPERVISOR_STACK_MSG; import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE; +import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_ALLOWLISTED; +import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE; +import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS; import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; @@ -70,9 +73,6 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; import static com.android.server.wm.Task.ActivityState.PAUSED; import static com.android.server.wm.Task.ActivityState.PAUSING; import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK; -import static com.android.server.wm.Task.LOCK_TASK_AUTH_ALLOWLISTED; -import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE; -import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; import static com.android.server.wm.Task.REPARENT_KEEP_STACK_AT_FRONT; import static com.android.server.wm.Task.TAG_CLEANUP; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 910a1a2c69b2..f92f231758a4 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1665,11 +1665,6 @@ class ActivityStarter { final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null) ? mSourceRecord.getTask() : null; setNewTask(taskToAffiliate); - if (mService.getLockTaskController().isLockTaskModeViolation( - mStartActivity.getTask())) { - Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity); - return START_RETURN_LOCK_TASK_MODE_VIOLATION; - } } else if (mAddingToTask) { addOrReparentStartingActivity(targetTask, "adding to task"); } @@ -1848,10 +1843,17 @@ class ActivityStarter { final boolean isNewClearTask = (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK); - if (!newTask && mService.getLockTaskController().isLockTaskModeViolation(targetTask, - isNewClearTask)) { - Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity); - return START_RETURN_LOCK_TASK_MODE_VIOLATION; + if (!newTask) { + if (mService.getLockTaskController().isLockTaskModeViolation(targetTask, + isNewClearTask)) { + Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity); + return START_RETURN_LOCK_TASK_MODE_VIOLATION; + } + } else { + if (mService.getLockTaskController().isNewTaskLockTaskModeViolation(mStartActivity)) { + Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity); + return START_RETURN_LOCK_TASK_MODE_VIOLATION; + } } return START_SUCCESS; diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 581b367aab32..df915a64e482 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -117,13 +117,13 @@ import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEI import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE; import static com.android.server.wm.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG; import static com.android.server.wm.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG; +import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_DONT_LOCK; import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE; import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION; import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_ONLY; import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS; import static com.android.server.wm.Task.ActivityState.DESTROYED; import static com.android.server.wm.Task.ActivityState.DESTROYING; -import static com.android.server.wm.Task.LOCK_TASK_AUTH_DONT_LOCK; import static com.android.server.wm.Task.REPARENT_KEEP_STACK_AT_FRONT; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java index b33c2f2823a5..5b7b5a122b42 100644 --- a/services/core/java/com/android/server/wm/LockTaskController.java +++ b/services/core/java/com/android/server/wm/LockTaskController.java @@ -24,6 +24,8 @@ import static android.content.Context.DEVICE_POLICY_SERVICE; import static android.content.Context.STATUS_BAR_SERVICE; import static android.content.Intent.ACTION_CALL_EMERGENCY; import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS; +import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT; +import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED; import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER; import static android.os.UserHandle.USER_ALL; import static android.os.UserHandle.USER_CURRENT; @@ -33,11 +35,6 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; -import static com.android.server.wm.Task.LOCK_TASK_AUTH_ALLOWLISTED; -import static com.android.server.wm.Task.LOCK_TASK_AUTH_DONT_LOCK; -import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE; -import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; -import static com.android.server.wm.Task.LOCK_TASK_AUTH_PINNABLE; import android.annotation.NonNull; import android.annotation.Nullable; @@ -129,6 +126,18 @@ public class LockTaskController { /** Tag used for disabling of keyguard */ private static final String LOCK_TASK_TAG = "Lock-to-App"; + /** Can't be put in lockTask mode. */ + static final int LOCK_TASK_AUTH_DONT_LOCK = 0; + /** Can enter app pinning with user approval. Can never start over existing lockTask task. */ + static final int LOCK_TASK_AUTH_PINNABLE = 1; + /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */ + static final int LOCK_TASK_AUTH_LAUNCHABLE = 2; + /** Can enter lockTask without user approval. Can start over existing lockTask task. */ + static final int LOCK_TASK_AUTH_ALLOWLISTED = 3; + /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing + * lockTask task. */ + static final int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4; + private final IBinder mToken = new LockTaskToken(); private final ActivityStackSupervisor mSupervisor; private final Context mContext; @@ -265,11 +274,10 @@ public class LockTaskController { } /** - * @return whether the requested task is allowed to be locked (either allowlisted, or declares - * lockTaskMode="always" in the manifest). + * @return whether the requested task auth is allowed to be locked. */ - boolean isTaskAllowlisted(Task task) { - switch(task.mLockTaskAuth) { + static boolean isTaskAuthAllowlisted(int lockTaskAuth) { + switch(lockTaskAuth) { case LOCK_TASK_AUTH_ALLOWLISTED: case LOCK_TASK_AUTH_LAUNCHABLE: case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: @@ -293,7 +301,30 @@ public class LockTaskController { * @return whether the requested task is disallowed to be launched. */ boolean isLockTaskModeViolation(Task task, boolean isNewClearTask) { - if (isLockTaskModeViolationInternal(task, isNewClearTask)) { + // TODO: Double check what's going on here. If the task is already in lock task mode, it's + // likely allowlisted, so will return false below. + if (isTaskLocked(task) && !isNewClearTask) { + // If the task is already at the top and won't be cleared, then allow the operation + } else if (isLockTaskModeViolationInternal(task, task.mUserId, task.intent, + task.mLockTaskAuth)) { + showLockTaskToast(); + return true; + } + return false; + } + + /** + * @param activity an activity that is going to be started in a new task as the root activity. + * @return whether the given activity is allowed to be launched. + */ + boolean isNewTaskLockTaskModeViolation(ActivityRecord activity) { + // Use the belong task (if any) to perform the lock task checks + if (activity.getTask() != null) { + return isLockTaskModeViolation(activity.getTask()); + } + + int auth = getLockTaskAuth(activity, null /* task */); + if (isLockTaskModeViolationInternal(activity, activity.mUserId, activity.intent, auth)) { showLockTaskToast(); return true; } @@ -310,25 +341,19 @@ public class LockTaskController { return mLockTaskModeTasks.get(0); } - private boolean isLockTaskModeViolationInternal(Task task, boolean isNewClearTask) { - // TODO: Double check what's going on here. If the task is already in lock task mode, it's - // likely allowlisted, so will return false below. - if (isTaskLocked(task) && !isNewClearTask) { - // If the task is already at the top and won't be cleared, then allow the operation - return false; - } - + private boolean isLockTaskModeViolationInternal(WindowContainer wc, int userId, + Intent intent, int taskAuth) { // Allow recents activity if enabled by policy - if (task.isActivityTypeRecents() && isRecentsAllowed(task.mUserId)) { + if (wc.isActivityTypeRecents() && isRecentsAllowed(userId)) { return false; } // Allow emergency calling when the device is protected by a locked keyguard - if (isKeyguardAllowed(task.mUserId) && isEmergencyCallTask(task)) { + if (isKeyguardAllowed(userId) && isEmergencyCallIntent(intent)) { return false; } - return !(isTaskAllowlisted(task) || mLockTaskModeTasks.isEmpty()); + return !(isTaskAuthAllowlisted(taskAuth) || mLockTaskModeTasks.isEmpty()); } private boolean isRecentsAllowed(int userId) { @@ -360,8 +385,7 @@ public class LockTaskController { return isPackageAllowlisted(userId, packageName); } - private boolean isEmergencyCallTask(Task task) { - final Intent intent = task.intent; + private boolean isEmergencyCallIntent(Intent intent) { if (intent == null) { return false; } @@ -697,6 +721,40 @@ public class LockTaskController { } } + int getLockTaskAuth(@Nullable ActivityRecord rootActivity, @Nullable Task task) { + if (rootActivity == null && task == null) { + return LOCK_TASK_AUTH_DONT_LOCK; + } + if (rootActivity == null) { + return LOCK_TASK_AUTH_PINNABLE; + } + + final String pkg = (task == null || task.realActivity == null) ? null + : task.realActivity.getPackageName(); + final int userId = task != null ? task.mUserId : rootActivity.mUserId; + int lockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK; + switch (rootActivity.lockTaskLaunchMode) { + case LOCK_TASK_LAUNCH_MODE_DEFAULT: + lockTaskAuth = isPackageAllowlisted(userId, pkg) + ? LOCK_TASK_AUTH_ALLOWLISTED : LOCK_TASK_AUTH_PINNABLE; + break; + + case LOCK_TASK_LAUNCH_MODE_NEVER: + lockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK; + break; + + case LOCK_TASK_LAUNCH_MODE_ALWAYS: + lockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV; + break; + + case LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED: + lockTaskAuth = isPackageAllowlisted(userId, pkg) + ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE; + break; + } + return lockTaskAuth; + } + boolean isPackageAllowlisted(int userId, String pkg) { if (pkg == null) { return false; diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java index 37f9082f22ee..45cd35977168 100644 --- a/services/core/java/com/android/server/wm/RecentTasks.java +++ b/services/core/java/com/android/server/wm/RecentTasks.java @@ -658,8 +658,8 @@ class RecentTasks { } for (int i = mTasks.size() - 1; i >= 0; --i) { final Task task = mTasks.get(i); - if (task.mUserId == userId - && !mService.getLockTaskController().isTaskAllowlisted(task)) { + if (task.mUserId == userId && !mService.getLockTaskController().isTaskAuthAllowlisted( + task.mLockTaskAuth)) { remove(task); } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 9273bf71f673..54a66cce9b25 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -43,10 +43,6 @@ import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT; import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY; import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING; import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; -import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS; -import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT; -import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED; -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; @@ -120,6 +116,11 @@ import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_ import static com.android.server.wm.IdentifierProto.HASH_CODE; import static com.android.server.wm.IdentifierProto.TITLE; import static com.android.server.wm.IdentifierProto.USER_ID; +import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_ALLOWLISTED; +import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_DONT_LOCK; +import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE; +import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; +import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_PINNABLE; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; import static com.android.server.wm.Task.ActivityState.PAUSED; import static com.android.server.wm.Task.ActivityState.PAUSING; @@ -407,17 +408,6 @@ class Task extends WindowContainer<WindowContainer> { boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity // was changed. - /** Can't be put in lockTask mode. */ - final static int LOCK_TASK_AUTH_DONT_LOCK = 0; - /** Can enter app pinning with user approval. Can never start over existing lockTask task. */ - final static int LOCK_TASK_AUTH_PINNABLE = 1; - /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */ - final static int LOCK_TASK_AUTH_LAUNCHABLE = 2; - /** Can enter lockTask without user approval. Can start over existing lockTask task. */ - final static int LOCK_TASK_AUTH_ALLOWLISTED = 3; - /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing - * lockTask task. */ - final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4; int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE; int mLockTaskUid = -1; // The uid of the application that called startLockTask(). @@ -1941,32 +1931,7 @@ class Task extends WindowContainer<WindowContainer> { } private void setLockTaskAuth(@Nullable ActivityRecord r) { - if (r == null) { - mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE; - return; - } - - final String pkg = (realActivity != null) ? realActivity.getPackageName() : null; - final LockTaskController lockTaskController = mAtmService.getLockTaskController(); - switch (r.lockTaskLaunchMode) { - case LOCK_TASK_LAUNCH_MODE_DEFAULT: - mLockTaskAuth = lockTaskController.isPackageAllowlisted(mUserId, pkg) - ? LOCK_TASK_AUTH_ALLOWLISTED : LOCK_TASK_AUTH_PINNABLE; - break; - - case LOCK_TASK_LAUNCH_MODE_NEVER: - mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK; - break; - - case LOCK_TASK_LAUNCH_MODE_ALWAYS: - mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV; - break; - - case LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED: - mLockTaskAuth = lockTaskController.isPackageAllowlisted(mUserId, pkg) - ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE; - break; - } + mLockTaskAuth = mAtmService.getLockTaskController().getLockTaskAuth(r, this); ProtoLog.d(WM_DEBUG_LOCKTASK, "setLockTaskAuth: task=%s mLockTaskAuth=%s", this, lockTaskAuthToString()); } diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java index 736a7be5e39e..2c92ae44d63a 100644 --- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java @@ -27,9 +27,11 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static com.android.server.RescueParty.LEVEL_FACTORY_RESET; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import android.content.ContentResolver; @@ -79,8 +81,11 @@ public class RescuePartyTest { private static final String CALLING_PACKAGE2 = "com.package.name2"; private static final String NAMESPACE1 = "namespace1"; private static final String NAMESPACE2 = "namespace2"; + private static final String NAMESPACE3 = "namespace3"; private static final String PROP_DEVICE_CONFIG_DISABLE_FLAG = "persist.device_config.configuration.disable_rescue_party"; + private static final String PROP_DISABLE_FACTORY_RESET_FLAG = + "persist.device_config.configuration.disable_rescue_party_factory_reset"; private MockitoSession mSession; private HashMap<String, String> mSystemSettingsMap; @@ -183,27 +188,38 @@ public class RescuePartyTest { @Test public void testBootLoopDetectionWithExecutionForAllRescueLevels() { + RescueParty.onSettingsProviderPublished(mMockContext); + verify(() -> Settings.Config.registerMonitorCallback(eq(mMockContentResolver), + mMonitorCallbackCaptor.capture())); + noteBoot(); verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, /*resetNamespaces=*/ null); assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS, SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE)); + // Record DeviceConfig accesses + RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext); + RemoteCallback monitorCallback = mMonitorCallbackCaptor.getValue(); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE1)); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE2)); + + final String[] expectedAllResetNamespaces = new String[]{NAMESPACE1, NAMESPACE2}; + noteBoot(); - verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES, /*resetNamespaces=*/ null); + verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES, expectedAllResetNamespaces); assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES, SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE)); noteBoot(); - verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, /*resetNamespaces=*/ null); + verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, expectedAllResetNamespaces); assertEquals(RescueParty.LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS, SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE)); noteBoot(); - verify(() -> RecoverySystem.rebootPromptAndWipeUserData(mMockContext, RescueParty.TAG)); assertEquals(LEVEL_FACTORY_RESET, SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE)); } @@ -230,7 +246,6 @@ public class RescuePartyTest { notePersistentAppCrash(); - verify(() -> RecoverySystem.rebootPromptAndWipeUserData(mMockContext, RescueParty.TAG)); assertEquals(LEVEL_FACTORY_RESET, SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE)); } @@ -247,6 +262,7 @@ public class RescuePartyTest { monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE1)); monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE2)); monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE2, NAMESPACE2)); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE2, NAMESPACE3)); // Fake DeviceConfig value changes monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE1)); verify(mMockPackageWatchdog).startObservingHealth(observer, @@ -255,10 +271,15 @@ public class RescuePartyTest { verify(mMockPackageWatchdog, times(2)).startObservingHealth(eq(observer), mPackageListCaptor.capture(), eq(RescueParty.DEFAULT_OBSERVING_DURATION_MS)); + monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE3)); + verify(mMockPackageWatchdog).startObservingHealth(observer, + Arrays.asList(CALLING_PACKAGE2), RescueParty.DEFAULT_OBSERVING_DURATION_MS); assertTrue(mPackageListCaptor.getValue().containsAll( Arrays.asList(CALLING_PACKAGE1, CALLING_PACKAGE2))); // Perform and verify scoped resets final String[] expectedResetNamespaces = new String[]{NAMESPACE1, NAMESPACE2}; + final String[] expectedAllResetNamespaces = + new String[]{NAMESPACE1, NAMESPACE2, NAMESPACE3}; observer.execute(new VersionedPackage( CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_CRASH); verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, expectedResetNamespaces); @@ -273,13 +294,12 @@ public class RescuePartyTest { observer.execute(new VersionedPackage( CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING); - verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, /*resetNamespaces=*/null); + verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, expectedAllResetNamespaces); assertEquals(RescueParty.LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS, SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE)); observer.execute(new VersionedPackage( CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_CRASH); - verify(() -> RecoverySystem.rebootPromptAndWipeUserData(mMockContext, RescueParty.TAG)); assertTrue(RescueParty.isAttemptingFactoryReset()); } @@ -288,7 +308,6 @@ public class RescuePartyTest { for (int i = 0; i < LEVEL_FACTORY_RESET; i++) { noteBoot(); } - verify(() -> RecoverySystem.rebootPromptAndWipeUserData(mMockContext, RescueParty.TAG)); assertTrue(RescueParty.isAttemptingFactoryReset()); } @@ -337,12 +356,25 @@ public class RescuePartyTest { assertEquals(RescuePartyObserver.getInstance(mMockContext).execute(sFailingPackage, PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING), false); - // Restore the property value initalized in SetUp() + // Restore the property value initialized in SetUp() SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(true)); SystemProperties.set(PROP_DEVICE_CONFIG_DISABLE_FLAG, Boolean.toString(false)); } @Test + public void testDisablingFactoryResetByDeviceConfigFlag() { + SystemProperties.set(PROP_DISABLE_FACTORY_RESET_FLAG, Boolean.toString(true)); + + for (int i = 0; i < LEVEL_FACTORY_RESET; i++) { + noteBoot(); + } + assertFalse(RescueParty.isAttemptingFactoryReset()); + + // Restore the property value initialized in SetUp() + SystemProperties.set(PROP_DISABLE_FACTORY_RESET_FLAG, ""); + } + + @Test public void testHealthCheckLevels() { RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext); @@ -437,7 +469,7 @@ public class RescuePartyTest { eq(resetMode), anyInt())); // Verify DeviceConfig resets if (resetNamespaces == null) { - verify(() -> DeviceConfig.resetToDefaults(resetMode, /*namespace=*/ null)); + verify(() -> DeviceConfig.resetToDefaults(anyInt(), anyString()), never()); } else { for (String namespace : resetNamespaces) { verify(() -> DeviceConfig.resetToDefaults(resetMode, namespace)); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index 3bd8c2766ee2..a7ced1df6125 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -486,7 +486,7 @@ public class ActivityStarterTests extends WindowTestsBase { final ActivityStarter starter = prepareStarter(0); final LockTaskController lockTaskController = mAtm.getLockTaskController(); - doReturn(true).when(lockTaskController).isLockTaskModeViolation(any()); + doReturn(true).when(lockTaskController).isNewTaskLockTaskModeViolation(any()); final int result = starter.setReason("testTaskModeViolation").execute(); diff --git a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java index 044f81986517..bf718a7c4528 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java @@ -50,6 +50,11 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; +import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_ALLOWLISTED; +import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_DONT_LOCK; +import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE; +import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; +import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_PINNABLE; import static com.android.server.wm.LockTaskController.STATUS_BAR_MASK_LOCKED; import static com.android.server.wm.LockTaskController.STATUS_BAR_MASK_PINNED; @@ -169,7 +174,7 @@ public class LockTaskControllerTest { @Test public void testStartLockTaskMode_once() throws Exception { // GIVEN a task record with allowlisted auth - Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED); // WHEN calling setLockTaskMode for LOCKED mode without resuming mLockTaskController.startLockTaskMode(tr, false, TEST_UID); @@ -186,8 +191,8 @@ public class LockTaskControllerTest { @Test public void testStartLockTaskMode_twice() throws Exception { // GIVEN two task records with allowlisted auth - Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); - Task tr2 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED); + Task tr2 = getTask(LOCK_TASK_AUTH_ALLOWLISTED); // WHEN calling setLockTaskMode for LOCKED mode on both tasks mLockTaskController.startLockTaskMode(tr1, false, TEST_UID); @@ -206,7 +211,7 @@ public class LockTaskControllerTest { @Test public void testStartLockTaskMode_pinningRequest() { // GIVEN a task record that is not allowlisted, i.e. with pinned auth - Task tr = getTask(Task.LOCK_TASK_AUTH_PINNABLE); + Task tr = getTask(LOCK_TASK_AUTH_PINNABLE); // WHEN calling startLockTaskMode mLockTaskController.startLockTaskMode(tr, false, TEST_UID); @@ -218,7 +223,7 @@ public class LockTaskControllerTest { @Test public void testStartLockTaskMode_pinnedBySystem() throws Exception { // GIVEN a task record with pinned auth - Task tr = getTask(Task.LOCK_TASK_AUTH_PINNABLE); + Task tr = getTask(LOCK_TASK_AUTH_PINNABLE); // WHEN the system calls startLockTaskMode mLockTaskController.startLockTaskMode(tr, true, SYSTEM_UID); @@ -237,41 +242,39 @@ public class LockTaskControllerTest { @Test public void testLockTaskViolation() { // GIVEN one task record with allowlisted auth that is in lock task mode - Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr, false, TEST_UID); // THEN it's not a lock task violation to try and launch this task without clearing assertFalse(mLockTaskController.isLockTaskModeViolation(tr, false)); // THEN it's a lock task violation to launch another task that is not allowlisted - assertTrue(mLockTaskController.isLockTaskModeViolation(getTask( - Task.LOCK_TASK_AUTH_PINNABLE))); + assertTrue(mLockTaskController.isLockTaskModeViolation(getTask(LOCK_TASK_AUTH_PINNABLE))); // THEN it's a lock task violation to launch another task that is disallowed from lock task - assertTrue(mLockTaskController.isLockTaskModeViolation(getTask( - Task.LOCK_TASK_AUTH_DONT_LOCK))); + assertTrue(mLockTaskController.isLockTaskModeViolation(getTask(LOCK_TASK_AUTH_DONT_LOCK))); // THEN it's no a lock task violation to launch another task that is allowlisted assertFalse(mLockTaskController.isLockTaskModeViolation(getTask( - Task.LOCK_TASK_AUTH_ALLOWLISTED))); + LOCK_TASK_AUTH_ALLOWLISTED))); assertFalse(mLockTaskController.isLockTaskModeViolation(getTask( - Task.LOCK_TASK_AUTH_LAUNCHABLE))); + LOCK_TASK_AUTH_LAUNCHABLE))); // THEN it's not a lock task violation to launch another task that is priv launchable assertFalse(mLockTaskController.isLockTaskModeViolation(getTask( - Task.LOCK_TASK_AUTH_LAUNCHABLE_PRIV))); + LOCK_TASK_AUTH_LAUNCHABLE_PRIV))); } @Test public void testLockTaskViolation_emergencyCall() { // GIVEN one task record with allowlisted auth that is in lock task mode - Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr, false, TEST_UID); // GIVEN tasks necessary for emergency calling Task keypad = getTask(new Intent().setComponent(EMERGENCY_DIALER_COMPONENT), - Task.LOCK_TASK_AUTH_PINNABLE); + LOCK_TASK_AUTH_PINNABLE); Task callAction = getTask(new Intent(Intent.ACTION_CALL_EMERGENCY), - Task.LOCK_TASK_AUTH_PINNABLE); - Task dialer = getTask("com.example.dialer", Task.LOCK_TASK_AUTH_PINNABLE); + LOCK_TASK_AUTH_PINNABLE); + Task dialer = getTask("com.example.dialer", LOCK_TASK_AUTH_PINNABLE); when(mTelecomManager.getSystemDialerPackage()) .thenReturn(dialer.intent.getComponent().getPackageName()); @@ -295,7 +298,7 @@ public class LockTaskControllerTest { @Test public void testStopLockTaskMode() throws Exception { // GIVEN one task record with allowlisted auth that is in lock task mode - Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr, false, TEST_UID); // WHEN the same caller calls stopLockTaskMode @@ -312,7 +315,7 @@ public class LockTaskControllerTest { @Test(expected = SecurityException.class) public void testStopLockTaskMode_differentCaller() { // GIVEN one task record with allowlisted auth that is in lock task mode - Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr, false, TEST_UID); // WHEN a different caller calls stopLockTaskMode @@ -324,7 +327,7 @@ public class LockTaskControllerTest { @Test public void testStopLockTaskMode_systemCaller() { // GIVEN one task record with allowlisted auth that is in lock task mode - Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr, false, TEST_UID); // WHEN system calls stopLockTaskMode @@ -337,8 +340,8 @@ public class LockTaskControllerTest { @Test public void testStopLockTaskMode_twoTasks() throws Exception { // GIVEN two task records with allowlisted auth that is in lock task mode - Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); - Task tr2 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED); + Task tr2 = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr1, false, TEST_UID); mLockTaskController.startLockTaskMode(tr2, false, TEST_UID); @@ -358,8 +361,8 @@ public class LockTaskControllerTest { @Test public void testStopLockTaskMode_rootTask() throws Exception { // GIVEN two task records with allowlisted auth that is in lock task mode - Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); - Task tr2 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED); + Task tr2 = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr1, false, TEST_UID); mLockTaskController.startLockTaskMode(tr2, false, TEST_UID); @@ -379,7 +382,7 @@ public class LockTaskControllerTest { @Test public void testStopLockTaskMode_pinned() throws Exception { // GIVEN one task records that is in pinned mode - Task tr = getTask(Task.LOCK_TASK_AUTH_PINNABLE); + Task tr = getTask(LOCK_TASK_AUTH_PINNABLE); mLockTaskController.startLockTaskMode(tr, true, SYSTEM_UID); // GIVEN that the keyguard is required to show after unlocking Settings.Secure.putInt(mContext.getContentResolver(), @@ -406,8 +409,8 @@ public class LockTaskControllerTest { @Test public void testClearLockedTasks() throws Exception { // GIVEN two task records with allowlisted auth that is in lock task mode - Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); - Task tr2 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED); + Task tr2 = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr1, false, TEST_UID); mLockTaskController.startLockTaskMode(tr2, false, TEST_UID); @@ -434,7 +437,7 @@ public class LockTaskControllerTest { .thenReturn(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED); // AND there is a task record - Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr1, true, TEST_UID); // WHEN calling clearLockedTasks on the root task @@ -454,7 +457,7 @@ public class LockTaskControllerTest { .thenReturn(true); // AND there is a task record - Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr1, true, TEST_UID); // WHEN calling clearLockedTasks on the root task @@ -471,7 +474,7 @@ public class LockTaskControllerTest { Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, 1, mContext.getUserId()); // AND there is a task record - Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr1, true, TEST_UID); // WHEN calling clearLockedTasks on the root task @@ -488,7 +491,7 @@ public class LockTaskControllerTest { Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, 0, mContext.getUserId()); // AND there is a task record - Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr1, true, TEST_UID); // WHEN calling clearLockedTasks on the root task @@ -574,7 +577,7 @@ public class LockTaskControllerTest { @Test public void testUpdateLockTaskFeatures() throws Exception { // GIVEN a locked task - Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr, false, TEST_UID); // THEN lock task mode should be started with default status bar masks @@ -616,7 +619,7 @@ public class LockTaskControllerTest { @Test public void testUpdateLockTaskFeatures_differentUser() throws Exception { // GIVEN a locked task - Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr, false, TEST_UID); // THEN lock task mode should be started with default status bar masks @@ -638,7 +641,7 @@ public class LockTaskControllerTest { @Test public void testUpdateLockTaskFeatures_keyguard() { // GIVEN a locked task - Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr, false, TEST_UID); // THEN keyguard should be disabled @@ -704,7 +707,7 @@ public class LockTaskControllerTest { TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT)); // Start lock task mode - Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED); + Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED); mLockTaskController.startLockTaskMode(tr, false, TEST_UID); // WHEN LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK is not enabled @@ -758,14 +761,13 @@ public class LockTaskControllerTest { * @param isAppAware {@code true} if the app has marked if allowlisted in its manifest */ private Task getTaskForUpdate(String pkg, boolean isAppAware) { - final int authIfAllowlisted = isAppAware - ? Task.LOCK_TASK_AUTH_LAUNCHABLE - : Task.LOCK_TASK_AUTH_ALLOWLISTED; + final int authIfAllowlisted = + isAppAware ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_ALLOWLISTED; Task tr = getTask(pkg, authIfAllowlisted); doAnswer((invocation) -> { boolean isAllowlisted = mLockTaskController.isPackageAllowlisted(TEST_USER_ID, pkg); - tr.mLockTaskAuth = isAllowlisted ? authIfAllowlisted : Task.LOCK_TASK_AUTH_PINNABLE; + tr.mLockTaskAuth = isAllowlisted ? authIfAllowlisted : LOCK_TASK_AUTH_PINNABLE; return null; }).when(tr).setLockTaskAuth(); return tr; diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java index 3e2a6eec37c4..b054dfcab2b6 100644 --- a/telephony/java/android/telephony/data/DataCallResponse.java +++ b/telephony/java/android/telephony/data/DataCallResponse.java @@ -240,6 +240,12 @@ public final class DataCallResponse implements Parcelable { */ @Deprecated public int getSuggestedRetryTime() { + // To match the pre-deprecated getSuggestedRetryTime() behavior. + if (mSuggestedRetryTime == RETRY_INTERVAL_UNDEFINED) { + return 0; + } else if (mSuggestedRetryTime > Integer.MAX_VALUE) { + return Integer.MAX_VALUE; + } return (int) mSuggestedRetryTime; } diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java index 1adbc2dc182c..322bbffe5be2 100644 --- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java +++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java @@ -32,7 +32,7 @@ public class HierrarchicalDataClassBase implements Parcelable { - // Code below generated by codegen v1.0.18. + // Code below generated by codegen v1.0.19. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -98,8 +98,8 @@ public class HierrarchicalDataClassBase implements Parcelable { }; @DataClass.Generated( - time = 1603836848866L, - codegenVersion = "1.0.18", + time = 1604435620553L, + codegenVersion = "1.0.19", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java", inputSignatures = "private int mBaseData\nclass HierrarchicalDataClassBase extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genSetters=true)") @Deprecated diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java index a4fdcd18aa3d..a8ae72deba3d 100644 --- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java +++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java @@ -46,7 +46,7 @@ public class HierrarchicalDataClassChild extends HierrarchicalDataClassBase { - // Code below generated by codegen v1.0.18. + // Code below generated by codegen v1.0.19. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -120,8 +120,8 @@ public class HierrarchicalDataClassChild extends HierrarchicalDataClassBase { }; @DataClass.Generated( - time = 1603836849753L, - codegenVersion = "1.0.18", + time = 1604435621500L, + codegenVersion = "1.0.19", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java", inputSignatures = "private @android.annotation.NonNull java.lang.String mChildData\nclass HierrarchicalDataClassChild extends com.android.codegentest.HierrarchicalDataClassBase implements []\n@com.android.internal.util.DataClass(genParcelable=true, genConstructor=false, genSetters=true)") @Deprecated diff --git a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java index f0d728e2f604..ca4278df4da7 100644 --- a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java +++ b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java @@ -54,7 +54,7 @@ public class ParcelAllTheThingsDataClass implements Parcelable { - // Code below generated by codegen v1.0.18. + // Code below generated by codegen v1.0.19. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -412,8 +412,8 @@ public class ParcelAllTheThingsDataClass implements Parcelable { } @DataClass.Generated( - time = 1603836847927L, - codegenVersion = "1.0.18", + time = 1604435619612L, + codegenVersion = "1.0.19", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java", inputSignatures = " @android.annotation.NonNull java.lang.String[] mStringArray\n @android.annotation.NonNull int[] mIntArray\n @android.annotation.NonNull java.util.List<java.lang.String> mStringList\n @android.annotation.NonNull java.util.Map<java.lang.String,com.android.codegentest.SampleWithCustomBuilder> mMap\n @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.String> mStringMap\n @android.annotation.NonNull android.util.SparseArray<com.android.codegentest.SampleWithCustomBuilder> mSparseArray\n @android.annotation.NonNull android.util.SparseIntArray mSparseIntArray\n @java.lang.SuppressWarnings({\"WeakerAccess\"}) @android.annotation.Nullable java.lang.Boolean mNullableBoolean\nclass ParcelAllTheThingsDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)") @Deprecated diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java index a3f458beebcc..ce1e043a2cd7 100644 --- a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java +++ b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java @@ -344,7 +344,7 @@ public final class SampleDataClass implements Parcelable { - // Code below generated by codegen v1.0.18. + // Code below generated by codegen v1.0.19. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -1874,8 +1874,8 @@ public final class SampleDataClass implements Parcelable { } @DataClass.Generated( - time = 1603836845952L, - codegenVersion = "1.0.18", + time = 1604435617581L, + codegenVersion = "1.0.19", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleDataClass.java", inputSignatures = "public static final java.lang.String STATE_NAME_UNDEFINED\npublic static final java.lang.String STATE_NAME_ON\npublic static final java.lang.String STATE_NAME_OFF\npublic static final int STATE_ON\npublic static final int STATE_OFF\npublic static final int STATE_UNDEFINED\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_AUGMENTED_REQUEST\nprivate int mNum\nprivate int mNum2\nprivate int mNum4\nprivate @android.annotation.Nullable java.lang.String mName\nprivate @android.annotation.NonNull java.lang.String mName2\nprivate @android.annotation.NonNull java.lang.String mName4\nprivate @android.annotation.Nullable android.view.accessibility.AccessibilityNodeInfo mOtherParcelable\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.codegentest.MyDateParcelling.class) @android.annotation.NonNull java.util.Date mDate\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForPattern.class) @android.annotation.NonNull java.util.regex.Pattern mPattern\nprivate @android.annotation.NonNull java.util.List<android.net.LinkAddress> mLinkAddresses2\nprivate @com.android.internal.util.DataClass.PluralOf(\"linkAddress\") @android.annotation.NonNull java.util.ArrayList<android.net.LinkAddress> mLinkAddresses\nprivate @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses4\nprivate @com.android.codegentest.SampleDataClass.StateName @android.annotation.NonNull java.lang.String mStateName\nprivate @com.android.codegentest.SampleDataClass.RequestFlags int mFlags\nprivate @com.android.codegentest.SampleDataClass.State int mState\npublic @android.annotation.NonNull java.lang.CharSequence charSeq\nprivate final @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses5\nprivate transient android.net.LinkAddress[] mLinkAddresses6\ntransient int[] mTmpStorage\nprivate @android.annotation.StringRes int mStringRes\nprivate @android.annotation.IntRange(from=0L, to=6L) int mDayOfWeek\nprivate @android.annotation.Size(2L) @android.annotation.NonNull @com.android.internal.util.DataClass.Each @android.annotation.FloatRange(from=0.0) float[] mCoords\nprivate static java.lang.String defaultName4()\nprivate int[] lazyInitTmpStorage()\npublic android.net.LinkAddress[] getLinkAddresses4()\nprivate boolean patternEquals(java.util.regex.Pattern)\nprivate int patternHashCode()\nprivate void onConstructed()\npublic void dump(java.io.PrintWriter)\nclass SampleDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=true, genEqualsHashCode=true, genToString=true, genForEachField=true, genSetters=true)") @Deprecated diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java index e3567044d361..5bbbf41184d4 100644 --- a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java +++ b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java @@ -85,7 +85,7 @@ public class SampleWithCustomBuilder implements Parcelable { - // Code below generated by codegen v1.0.18. + // Code below generated by codegen v1.0.19. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -253,8 +253,8 @@ public class SampleWithCustomBuilder implements Parcelable { } @DataClass.Generated( - time = 1603836846970L, - codegenVersion = "1.0.18", + time = 1604435618584L, + codegenVersion = "1.0.19", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java", inputSignatures = " long delayAmount\n @android.annotation.NonNull java.util.concurrent.TimeUnit delayUnit\n long creationTimestamp\nprivate static java.util.concurrent.TimeUnit unparcelDelayUnit(android.os.Parcel)\nprivate void parcelDelayUnit(android.os.Parcel,int)\nclass SampleWithCustomBuilder extends java.lang.Object implements [android.os.Parcelable]\nabstract com.android.codegentest.SampleWithCustomBuilder.Builder setDelayAmount(long)\npublic abstract com.android.codegentest.SampleWithCustomBuilder.Builder setDelayUnit(java.util.concurrent.TimeUnit)\npublic com.android.codegentest.SampleWithCustomBuilder.Builder setDelay(long,java.util.concurrent.TimeUnit)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)\nabstract com.android.codegentest.SampleWithCustomBuilder.Builder setDelayAmount(long)\npublic abstract com.android.codegentest.SampleWithCustomBuilder.Builder setDelayUnit(java.util.concurrent.TimeUnit)\npublic com.android.codegentest.SampleWithCustomBuilder.Builder setDelay(long,java.util.concurrent.TimeUnit)\nclass BaseBuilder extends java.lang.Object implements []") @Deprecated diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java b/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java index 07ec31ddc5e6..c76216496fd8 100644 --- a/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java +++ b/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java @@ -36,7 +36,7 @@ public class SampleWithNestedDataClasses { - // Code below generated by codegen v1.0.18. + // Code below generated by codegen v1.0.19. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -135,8 +135,8 @@ public class SampleWithNestedDataClasses { }; @DataClass.Generated( - time = 1603836851627L, - codegenVersion = "1.0.18", + time = 1604435623368L, + codegenVersion = "1.0.19", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java", inputSignatures = " @android.annotation.NonNull java.lang.String mBar\nclass NestedDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)") @Deprecated @@ -160,7 +160,7 @@ public class SampleWithNestedDataClasses { - // Code below generated by codegen v1.0.18. + // Code below generated by codegen v1.0.19. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -259,8 +259,8 @@ public class SampleWithNestedDataClasses { }; @DataClass.Generated( - time = 1603836851635L, - codegenVersion = "1.0.18", + time = 1604435623377L, + codegenVersion = "1.0.19", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java", inputSignatures = " @android.annotation.NonNull long mBaz2\nclass NestedDataClass3 extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)") @Deprecated @@ -274,7 +274,7 @@ public class SampleWithNestedDataClasses { - // Code below generated by codegen v1.0.18. + // Code below generated by codegen v1.0.19. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -373,8 +373,8 @@ public class SampleWithNestedDataClasses { }; @DataClass.Generated( - time = 1603836851640L, - codegenVersion = "1.0.18", + time = 1604435623381L, + codegenVersion = "1.0.19", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java", inputSignatures = " @android.annotation.NonNull java.lang.String mBaz\nclass NestedDataClass2 extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)") @Deprecated diff --git a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java index 5cbc6b30d1fc..0813dbe411c7 100644 --- a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java +++ b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java @@ -59,7 +59,7 @@ public class StaleDataclassDetectorFalsePositivesTest { - // Code below generated by codegen v1.0.18. + // Code below generated by codegen v1.0.19. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -84,8 +84,8 @@ public class StaleDataclassDetectorFalsePositivesTest { } @DataClass.Generated( - time = 1603836850677L, - codegenVersion = "1.0.18", + time = 1604435622426L, + codegenVersion = "1.0.19", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java", inputSignatures = "private @android.annotation.Nullable java.util.List<java.util.Set<?>> mUsesWildcards\npublic @android.annotation.NonNull java.lang.String someMethod(int)\nclass StaleDataclassDetectorFalsePositivesTest extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=false)") @Deprecated diff --git a/tools/codegen/src/com/android/codegen/ClassInfo.kt b/tools/codegen/src/com/android/codegen/ClassInfo.kt index bf95a2eb2193..056898c9eca1 100644 --- a/tools/codegen/src/com/android/codegen/ClassInfo.kt +++ b/tools/codegen/src/com/android/codegen/ClassInfo.kt @@ -1,12 +1,14 @@ package com.android.codegen import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration +import com.github.javaparser.ast.body.TypeDeclaration open class ClassInfo(val classAst: ClassOrInterfaceDeclaration, val fileInfo: FileInfo) { val fileAst = fileInfo.fileAst val nestedClasses = classAst.members.filterIsInstance<ClassOrInterfaceDeclaration>() + val nestedTypes = classAst.members.filterIsInstance<TypeDeclaration<*>>() val superInterfaces = classAst.implementedTypes.map { it.asString() } val superClass = classAst.extendedTypes.getOrNull(0) diff --git a/tools/codegen/src/com/android/codegen/InputSignaturesComputation.kt b/tools/codegen/src/com/android/codegen/InputSignaturesComputation.kt index 69ff18d3f6ab..1aea57514855 100644 --- a/tools/codegen/src/com/android/codegen/InputSignaturesComputation.kt +++ b/tools/codegen/src/com/android/codegen/InputSignaturesComputation.kt @@ -128,7 +128,7 @@ private fun ClassPrinter.getFullClassName(className: String): String { if (classAst.nameAsString == className) return thisPackagePrefix + classAst.nameAsString - nestedClasses.find { + nestedTypes.find { it.nameAsString == className }?.let { return thisClassPrefix + it.nameAsString } diff --git a/tools/codegen/src/com/android/codegen/SharedConstants.kt b/tools/codegen/src/com/android/codegen/SharedConstants.kt index ca658a972209..147f18c35e5c 100644 --- a/tools/codegen/src/com/android/codegen/SharedConstants.kt +++ b/tools/codegen/src/com/android/codegen/SharedConstants.kt @@ -1,7 +1,7 @@ package com.android.codegen const val CODEGEN_NAME = "codegen" -const val CODEGEN_VERSION = "1.0.18" +const val CODEGEN_VERSION = "1.0.19" const val CANONICAL_BUILDER_CLASS = "Builder" const val BASE_BUILDER_CLASS = "BaseBuilder" |