summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt6
-rw-r--r--api/system-lint-baseline.txt8
-rw-r--r--core/api/current.txt1
-rw-r--r--core/api/system-current.txt6
-rw-r--r--core/api/system-lint-baseline.txt6
-rw-r--r--core/java/android/uwb/AngleMeasurement.java28
-rw-r--r--core/java/android/uwb/AngleOfArrivalMeasurement.java27
-rw-r--r--core/java/android/uwb/DistanceMeasurement.java29
-rw-r--r--core/java/android/uwb/RangingMeasurement.java30
-rw-r--r--core/java/android/uwb/RangingParams.java38
-rw-r--r--core/java/android/uwb/RangingReport.java27
-rw-r--r--core/java/android/uwb/TEST_MAPPING7
-rw-r--r--core/java/android/window/DisplayAreaOrganizer.java4
-rw-r--r--core/java/android/window/IDisplayAreaOrganizerController.aidl4
-rw-r--r--core/tests/uwbtests/Android.bp28
-rw-r--r--core/tests/uwbtests/AndroidManifest.xml31
-rw-r--r--core/tests/uwbtests/AndroidTest.xml32
-rw-r--r--core/tests/uwbtests/src/android/uwb/AngleMeasurementTest.java85
-rw-r--r--core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java89
-rw-r--r--core/tests/uwbtests/src/android/uwb/DistanceMeasurementTest.java87
-rw-r--r--core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java95
-rw-r--r--core/tests/uwbtests/src/android/uwb/RangingParamsTest.java102
-rw-r--r--core/tests/uwbtests/src/android/uwb/RangingReportTest.java90
-rw-r--r--core/tests/uwbtests/src/android/uwb/UwbAddressTest.java79
-rw-r--r--core/tests/uwbtests/src/android/uwb/UwbTestUtils.java92
-rw-r--r--graphics/java/android/graphics/Typeface.java6
-rw-r--r--media/java/android/media/MediaCas.java86
-rw-r--r--media/java/android/media/MediaPlayer.java106
-rw-r--r--services/core/java/com/android/server/RescueParty.java50
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java6
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java20
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/LockTaskController.java104
-rw-r--r--services/core/java/com/android/server/wm/RecentTasks.java4
-rw-r--r--services/core/java/com/android/server/wm/Task.java47
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java50
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java80
-rw-r--r--telephony/java/android/telephony/data/DataCallResponse.java6
-rw-r--r--tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java6
-rw-r--r--tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java6
-rw-r--r--tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java6
-rw-r--r--tests/Codegen/src/com/android/codegentest/SampleDataClass.java6
-rw-r--r--tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java6
-rw-r--r--tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java18
-rw-r--r--tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java6
-rw-r--r--tools/codegen/src/com/android/codegen/ClassInfo.kt2
-rw-r--r--tools/codegen/src/com/android/codegen/InputSignaturesComputation.kt2
-rw-r--r--tools/codegen/src/com/android/codegen/SharedConstants.kt2
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"