summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--apex/jobscheduler/framework/Android.bp1
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobInfo.java2
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobParameters.java3
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobWorkItem.java2
-rw-r--r--apex/media/framework/java/android/media/MediaController2.java3
-rw-r--r--api/current.txt19
-rwxr-xr-xapi/system-current.txt84
-rw-r--r--api/test-current.txt2
-rw-r--r--core/java/android/app/ActivityThread.java66
-rw-r--r--core/java/android/app/ClientTransactionHandler.java8
-rw-r--r--core/java/android/app/DownloadManager.java35
-rw-r--r--core/java/android/app/LocalActivityManager.java2
-rw-r--r--core/java/android/app/servertransaction/StartActivityItem.java (renamed from core/java/android/app/servertransaction/WindowVisibilityItem.java)61
-rw-r--r--core/java/android/app/servertransaction/StopActivityItem.java20
-rw-r--r--core/java/android/app/servertransaction/TransactionExecutor.java6
-rw-r--r--core/java/android/app/servertransaction/TransactionExecutorHelper.java3
-rw-r--r--core/java/android/content/ContentProvider.java78
-rw-r--r--core/java/android/content/ContentProviderOperation.java2
-rw-r--r--core/java/android/content/ContentProviderResult.java8
-rw-r--r--core/java/android/content/ContentResolver.java68
-rw-r--r--core/java/android/content/pm/parsing/ApkLiteParseUtils.java2
-rw-r--r--core/java/android/content/pm/parsing/ComponentParseUtils.java2
-rw-r--r--core/java/android/database/sqlite/SQLiteQueryBuilder.java44
-rw-r--r--core/java/android/hardware/input/IInputManager.aidl7
-rw-r--r--core/java/android/hardware/input/InputManager.java36
-rw-r--r--core/java/android/hardware/usb/UsbManager.java12
-rw-r--r--core/java/android/net/ConnectivityManager.java87
-rw-r--r--core/java/android/net/IConnectivityManager.aidl8
-rw-r--r--core/java/android/net/NetworkProvider.java166
-rw-r--r--core/java/android/net/NetworkStats.java219
-rw-r--r--core/java/android/net/TrafficStats.java2
-rw-r--r--core/java/android/net/netstats/provider/AbstractNetworkStatsProvider.java70
-rw-r--r--core/java/android/net/netstats/provider/INetworkStatsProvider.aidl28
-rw-r--r--core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl31
-rw-r--r--core/java/android/net/netstats/provider/NetworkStatsProviderCallback.java98
-rw-r--r--core/java/android/net/netstats/provider/NetworkStatsProviderWrapper.java48
-rw-r--r--core/java/android/os/Parcel.java106
-rw-r--r--core/java/android/os/ParcelFileDescriptor.java25
-rw-r--r--core/java/android/os/Process.java6
-rw-r--r--core/java/android/os/ZygoteProcess.java2
-rw-r--r--core/java/android/os/storage/StorageManager.java206
-rw-r--r--core/java/android/os/storage/StorageVolume.java11
-rw-r--r--core/java/android/provider/DocumentsContract.java4
-rw-r--r--core/java/android/provider/Settings.java6
-rw-r--r--core/java/android/service/autofill/FillResponse.java10
-rw-r--r--core/java/android/view/InsetsAnimationControlImpl.java4
-rw-r--r--core/java/android/view/InsetsController.java8
-rw-r--r--core/java/android/view/SurfaceControl.java28
-rw-r--r--core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java81
-rw-r--r--core/java/com/android/internal/infra/AndroidFuture.java90
-rw-r--r--core/java/com/android/internal/os/Zygote.java5
-rw-r--r--core/java/com/android/internal/os/ZygoteArguments.java2
-rw-r--r--core/java/com/android/server/SystemConfig.java15
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp12
-rw-r--r--core/res/AndroidManifest.xml4
-rw-r--r--core/res/res/layout/accessibility_button_chooser_item.xml2
-rw-r--r--core/res/res/values/strings.xml5
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java21
-rw-r--r--core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java2
-rw-r--r--core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java4
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityThreadTest.java3
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java21
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java52
-rw-r--r--core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java7
-rw-r--r--core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java140
-rw-r--r--core/xsd/permission.xsd4
-rw-r--r--core/xsd/schema/current.txt7
-rw-r--r--media/java/android/media/IMediaRoute2Provider.aidl2
-rw-r--r--media/java/android/media/IMediaRouter2Manager.aidl2
-rw-r--r--media/java/android/media/IMediaRouterService.aidl5
-rw-r--r--media/java/android/media/MediaRoute2Info.java83
-rw-r--r--media/java/android/media/MediaRoute2ProviderService.java27
-rw-r--r--media/java/android/media/MediaRouter2.java187
-rw-r--r--media/java/android/media/MediaRouter2Manager.java33
-rw-r--r--media/java/android/media/MediaScannerConnection.java2
-rw-r--r--media/java/android/media/RouteDiscoveryRequest.aidl19
-rw-r--r--media/java/android/media/RouteDiscoveryRequest.java200
-rw-r--r--media/java/android/media/RouteSessionInfo.java30
-rw-r--r--media/java/android/media/soundtrigger/SoundTriggerDetector.java2
-rw-r--r--media/java/android/media/soundtrigger/SoundTriggerManager.java2
-rw-r--r--media/java/android/media/tv/TvInputInfo.java2
-rwxr-xr-xmedia/java/android/media/tv/TvInputService.java2
-rw-r--r--media/java/android/media/tv/TvTrackInfo.java53
-rw-r--r--media/java/android/media/tv/tuner/FrontendCapabilities.java291
-rw-r--r--media/java/android/media/tv/tuner/frontend/AnalogFrontendCapabilities.java41
-rw-r--r--media/java/android/media/tv/tuner/frontend/Atsc3FrontendCapabilities.java65
-rw-r--r--media/java/android/media/tv/tuner/frontend/AtscFrontendCapabilities.java33
-rw-r--r--media/java/android/media/tv/tuner/frontend/DvbcFrontendCapabilities.java46
-rw-r--r--media/java/android/media/tv/tuner/frontend/DvbsFrontendCapabilities.java46
-rw-r--r--media/java/android/media/tv/tuner/frontend/DvbtFrontendCapabilities.java78
-rw-r--r--media/java/android/media/tv/tuner/frontend/FrontendCapabilities.java24
-rw-r--r--media/java/android/media/tv/tuner/frontend/FrontendInfo.java1
-rw-r--r--media/java/android/media/tv/tuner/frontend/IsdbcFrontendCapabilities.java59
-rw-r--r--media/java/android/media/tv/tuner/frontend/Isdbs3FrontendCapabilities.java40
-rw-r--r--media/java/android/media/tv/tuner/frontend/IsdbsFrontendCapabilities.java40
-rw-r--r--media/java/android/mtp/MtpPropertyList.java3
-rw-r--r--media/java/android/mtp/MtpStorage.java3
-rw-r--r--media/java/android/service/media/MediaBrowserService.java2
-rw-r--r--media/mca/effect/java/android/media/effect/SingleFilterEffect.java3
-rw-r--r--media/mca/filterfw/java/android/filterfw/GraphEnvironment.java4
-rw-r--r--media/mca/filterfw/java/android/filterfw/core/Filter.java10
-rw-r--r--media/mca/filterfw/java/android/filterfw/core/FilterContext.java6
-rw-r--r--media/mca/filterfw/java/android/filterfw/core/FilterGraph.java13
-rw-r--r--media/mca/filterfw/java/android/filterfw/core/Frame.java4
-rw-r--r--media/mca/filterfw/java/android/filterfw/core/FrameFormat.java4
-rw-r--r--media/mca/filterfw/java/android/filterfw/core/FrameManager.java5
-rw-r--r--media/mca/filterfw/java/android/filterfw/core/GLEnvironment.java5
-rw-r--r--media/mca/filterfw/java/android/filterfw/core/GLFrame.java9
-rw-r--r--media/mca/filterfw/java/android/filterfw/core/GraphRunner.java2
-rw-r--r--media/mca/filterfw/java/android/filterfw/core/MutableFrameFormat.java4
-rw-r--r--media/mca/filterfw/java/android/filterfw/core/Program.java3
-rw-r--r--media/mca/filterfw/java/android/filterfw/core/ShaderProgram.java7
-rw-r--r--media/mca/filterfw/java/android/filterfw/format/ImageFormat.java2
-rw-r--r--media/mca/filterfw/java/android/filterfw/geometry/Point.java3
-rw-r--r--media/mca/filterfw/java/android/filterfw/geometry/Quad.java4
-rw-r--r--media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java36
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java153
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java69
-rw-r--r--media/tests/MediaRouter/src/com/android/mediaroutertest/RouteDiscoveryRequestTest.java87
-rw-r--r--opengl/java/android/opengl/EGL14.java4
-rw-r--r--opengl/java/android/opengl/GLES20.java2
-rw-r--r--opengl/java/android/opengl/GLSurfaceView.java2
-rw-r--r--opengl/java/javax/microedition/khronos/egl/EGL10.java3
-rw-r--r--packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java7
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java24
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java6
-rw-r--r--packages/SettingsProvider/Android.bp2
-rw-r--r--packages/SettingsProvider/res/values/overlayable.xml25
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java2
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java2
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java2
-rw-r--r--packages/Tethering/Android.bp2
-rw-r--r--packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java101
-rw-r--r--packages/Tethering/jarjar-rules.txt1
-rw-r--r--packages/Tethering/src/android/net/ip/IpServer.java218
-rw-r--r--packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java2
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java52
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java2
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java125
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java38
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java19
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java14
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java23
-rw-r--r--packages/Tethering/tests/unit/jarjar-rules.txt1
-rw-r--r--packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java204
-rw-r--r--packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java12
-rw-r--r--packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java230
-rw-r--r--rs/java/android/renderscript/BaseObj.java4
-rw-r--r--rs/java/android/renderscript/Element.java2
-rw-r--r--rs/java/android/renderscript/FileA3D.java8
-rw-r--r--rs/java/android/renderscript/Font.java11
-rw-r--r--rs/java/android/renderscript/Matrix4f.java3
-rw-r--r--rs/java/android/renderscript/Mesh.java3
-rw-r--r--rs/java/android/renderscript/Program.java8
-rw-r--r--rs/java/android/renderscript/ProgramFragment.java2
-rw-r--r--rs/java/android/renderscript/ProgramFragmentFixedFunction.java2
-rw-r--r--rs/java/android/renderscript/ProgramRaster.java2
-rw-r--r--rs/java/android/renderscript/ProgramStore.java2
-rw-r--r--rs/java/android/renderscript/ProgramVertex.java2
-rw-r--r--rs/java/android/renderscript/ProgramVertexFixedFunction.java2
-rw-r--r--rs/java/android/renderscript/RSSurfaceView.java2
-rw-r--r--rs/java/android/renderscript/RenderScript.java2
-rw-r--r--rs/java/android/renderscript/RenderScriptCacheDir.java3
-rw-r--r--rs/java/android/renderscript/RenderScriptGL.java2
-rw-r--r--rs/java/android/renderscript/Script.java2
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java101
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java88
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java26
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java4
-rw-r--r--services/core/java/com/android/server/Watchdog.java11
-rw-r--r--services/core/java/com/android/server/adb/AdbDebuggingManager.java5
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java31
-rw-r--r--services/core/java/com/android/server/display/DisplayModeDirector.java27
-rw-r--r--services/core/java/com/android/server/display/LocalDisplayAdapter.java31
-rw-r--r--services/core/java/com/android/server/display/OverlayDisplayAdapter.java2
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java77
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2Provider.java2
-rw-r--r--services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java8
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java58
-rw-r--r--services/core/java/com/android/server/media/MediaRouterService.java9
-rw-r--r--services/core/java/com/android/server/media/MediaSession2Record.java179
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java50
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecordImpl.java143
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java280
-rw-r--r--services/core/java/com/android/server/media/MediaSessionStack.java161
-rw-r--r--services/core/java/com/android/server/media/SystemMediaRoute2Provider.java12
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsFactory.java6
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java10
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java51
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java12
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java104
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java68
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java3
-rw-r--r--services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java8
-rw-r--r--services/core/java/com/android/server/wm/InsetsSourceProvider.java46
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java3
-rw-r--r--services/core/java/com/android/server/wm/SurfaceAnimator.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java6
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp8
-rw-r--r--services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java24
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DimmerTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java2
-rw-r--r--telecomm/java/android/telecom/AudioState.java2
-rw-r--r--telecomm/java/android/telecom/Call.java3
-rw-r--r--telecomm/java/android/telecom/CallerInfo.java4
-rw-r--r--telecomm/java/android/telecom/Connection.java2
-rw-r--r--telecomm/java/android/telecom/Log.java2
-rw-r--r--telecomm/java/android/telecom/ParcelableCall.java7
-rw-r--r--telecomm/java/android/telecom/Phone.java2
-rw-r--r--telecomm/java/android/telecom/PhoneAccountHandle.java2
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java2
-rw-r--r--telecomm/java/android/telecom/VideoCallImpl.java2
-rw-r--r--telecomm/java/android/telecom/VideoProfile.java1
-rw-r--r--telephony/common/com/android/internal/telephony/GsmAlphabet.java2
-rw-r--r--telephony/common/com/android/internal/telephony/SmsConstants.java2
-rw-r--r--telephony/java/android/service/euicc/EuiccProfileInfo.java2
-rw-r--r--telephony/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java2
-rw-r--r--telephony/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java2
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityGsm.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityLte.java2
-rw-r--r--telephony/java/android/telephony/ServiceState.java23
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java19
-rw-r--r--tests/net/java/android/net/NetworkStatsTest.java334
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsObserversTest.java16
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsServiceTest.java110
242 files changed, 4834 insertions, 2693 deletions
diff --git a/Android.bp b/Android.bp
index 477f0272efa0..efe530798041 100644
--- a/Android.bp
+++ b/Android.bp
@@ -651,6 +651,7 @@ filegroup {
"core/java/com/android/internal/util/Preconditions.java",
"core/java/com/android/internal/util/State.java",
"core/java/com/android/internal/util/StateMachine.java",
+ "core/java/com/android/internal/util/TrafficStatsConstants.java",
"core/java/android/net/shared/Inet4AddressUtils.java",
],
}
diff --git a/apex/jobscheduler/framework/Android.bp b/apex/jobscheduler/framework/Android.bp
index 98bbe8243183..ec074262fb13 100644
--- a/apex/jobscheduler/framework/Android.bp
+++ b/apex/jobscheduler/framework/Android.bp
@@ -25,5 +25,6 @@ java_library {
},
libs: [
"framework-minus-apex",
+ "unsupportedappusage",
],
}
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index 8b3b3a28f2bc..0bb07caf0b00 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -29,7 +29,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.ComponentName;
import android.net.NetworkRequest;
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
index 42cf17b1264e..ef1351e6d597 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
@@ -18,8 +18,7 @@ package android.app.job;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
-import android.app.job.IJobCallback;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.net.Network;
import android.net.Uri;
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobWorkItem.java b/apex/jobscheduler/framework/java/android/app/job/JobWorkItem.java
index c6631fa76494..0c45cbf6dc11 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobWorkItem.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobWorkItem.java
@@ -19,7 +19,7 @@ package android.app.job;
import static android.app.job.JobInfo.NETWORK_BYTES_UNKNOWN;
import android.annotation.BytesLong;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Build;
import android.os.Parcel;
diff --git a/apex/media/framework/java/android/media/MediaController2.java b/apex/media/framework/java/android/media/MediaController2.java
index c3dd3fe4451c..d059c670ccb6 100644
--- a/apex/media/framework/java/android/media/MediaController2.java
+++ b/apex/media/framework/java/android/media/MediaController2.java
@@ -141,6 +141,9 @@ public class MediaController2 implements AutoCloseable {
// Note: unbindService() throws IllegalArgumentException when it's called twice.
return;
}
+ if (DEBUG) {
+ Log.d(TAG, "closing " + this);
+ }
mClosed = true;
if (mServiceConnection != null) {
// Note: This should be called even when the bindService() has returned false.
diff --git a/api/current.txt b/api/current.txt
index a441841ba815..b673df0b5c90 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9504,6 +9504,7 @@ package android.content {
method public void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
method @Nullable public final String getCallingFeatureId();
method @Nullable public final String getCallingPackage();
+ method @Nullable public final String getCallingPackageUnchecked();
method @Nullable public final android.content.Context getContext();
method @Nullable public final android.content.pm.PathPermission[] getPathPermissions();
method @Nullable public final String getReadPermission();
@@ -9513,6 +9514,7 @@ package android.content {
method @Nullable public abstract android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues);
method @Nullable public android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle);
method protected boolean isTemporary();
+ method public void onCallingPackageChanged();
method public void onConfigurationChanged(android.content.res.Configuration);
method public abstract boolean onCreate();
method public void onLowMemory();
@@ -9627,13 +9629,13 @@ package android.content {
ctor public ContentProviderResult(@NonNull android.net.Uri);
ctor public ContentProviderResult(int);
ctor public ContentProviderResult(@NonNull android.os.Bundle);
- ctor public ContentProviderResult(@NonNull Exception);
+ ctor public ContentProviderResult(@NonNull Throwable);
ctor public ContentProviderResult(android.os.Parcel);
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.content.ContentProviderResult> CREATOR;
field @Nullable public final Integer count;
- field @Nullable public final Exception exception;
+ field @Nullable public final Throwable exception;
field @Nullable public final android.os.Bundle extras;
field @Nullable public final android.net.Uri uri;
}
@@ -13324,6 +13326,7 @@ package android.database.sqlite {
method @Deprecated public String buildUnionSubQuery(String, String[], java.util.Set<java.lang.String>, int, String, String, String[], String, String);
method public int delete(@NonNull android.database.sqlite.SQLiteDatabase, @Nullable String, @Nullable String[]);
method @Nullable public android.database.sqlite.SQLiteDatabase.CursorFactory getCursorFactory();
+ method @Nullable public java.util.Collection<java.util.regex.Pattern> getProjectionGreylist();
method @Nullable public java.util.Map<java.lang.String,java.lang.String> getProjectionMap();
method @Nullable public String getTables();
method public long insert(@NonNull android.database.sqlite.SQLiteDatabase, @NonNull android.content.ContentValues);
@@ -13336,6 +13339,7 @@ package android.database.sqlite {
method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, String[], String, String[], String, String, String, String, android.os.CancellationSignal);
method public void setCursorFactory(@Nullable android.database.sqlite.SQLiteDatabase.CursorFactory);
method public void setDistinct(boolean);
+ method public void setProjectionGreylist(@Nullable java.util.Collection<java.util.regex.Pattern>);
method public void setProjectionMap(@Nullable java.util.Map<java.lang.String,java.lang.String>);
method public void setStrict(boolean);
method public void setStrictColumns(boolean);
@@ -28685,6 +28689,7 @@ package android.media.tv {
method public boolean isAudioDescription();
method public boolean isEncrypted();
method public boolean isHardOfHearing();
+ method public boolean isSpokenSubtitle();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.TvTrackInfo> CREATOR;
field public static final int TYPE_AUDIO = 0; // 0x0
@@ -28703,6 +28708,7 @@ package android.media.tv {
method public android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle);
method @NonNull public android.media.tv.TvTrackInfo.Builder setHardOfHearing(boolean);
method public android.media.tv.TvTrackInfo.Builder setLanguage(String);
+ method @NonNull public android.media.tv.TvTrackInfo.Builder setSpokenSubtitle(boolean);
method public android.media.tv.TvTrackInfo.Builder setVideoActiveFormatDescription(byte);
method public android.media.tv.TvTrackInfo.Builder setVideoFrameRate(float);
method public android.media.tv.TvTrackInfo.Builder setVideoHeight(int);
@@ -36387,15 +36393,22 @@ package android.os.storage {
method public boolean isObbMounted(String);
method public boolean mountObb(String, String, android.os.storage.OnObbStateChangeListener);
method @NonNull public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback, android.os.Handler) throws java.io.IOException;
+ method public void registerStorageVolumeCallback(@NonNull java.util.concurrent.Executor, @NonNull android.os.storage.StorageManager.StorageVolumeCallback);
method public void setCacheBehaviorGroup(java.io.File, boolean) throws java.io.IOException;
method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException;
method public boolean unmountObb(String, boolean, android.os.storage.OnObbStateChangeListener);
+ method public void unregisterStorageVolumeCallback(@NonNull android.os.storage.StorageManager.StorageVolumeCallback);
field public static final String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE";
field public static final String EXTRA_REQUESTED_BYTES = "android.os.storage.extra.REQUESTED_BYTES";
field public static final String EXTRA_UUID = "android.os.storage.extra.UUID";
field public static final java.util.UUID UUID_DEFAULT;
}
+ public static class StorageManager.StorageVolumeCallback {
+ ctor public StorageManager.StorageVolumeCallback();
+ method public void onStateChanged(@NonNull android.os.storage.StorageVolume);
+ }
+
public final class StorageVolume implements android.os.Parcelable {
method @Deprecated @Nullable public android.content.Intent createAccessIntent(String);
method @NonNull public android.content.Intent createOpenDocumentTreeIntent();
@@ -45703,6 +45716,7 @@ package android.telephony {
method public String getOperatorNumeric();
method public boolean getRoaming();
method public int getState();
+ method public boolean isSearching();
method public void setIsManualSelection(boolean);
method public void setOperatorName(String, String, String);
method public void setRoaming(boolean);
@@ -45961,6 +45975,7 @@ package android.telephony {
public class SubscriptionManager {
method public void addOnOpportunisticSubscriptionsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
method public void addOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
+ method public void addOnSubscriptionsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void addSubscriptionsIntoGroup(@NonNull java.util.List<java.lang.Integer>, @NonNull android.os.ParcelUuid);
method public boolean canManageSubscription(android.telephony.SubscriptionInfo);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.os.ParcelUuid createSubscriptionGroup(@NonNull java.util.List<java.lang.Integer>);
diff --git a/api/system-current.txt b/api/system-current.txt
index 4f262618c48e..384dc13ff567 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -567,6 +567,7 @@ package android.app {
}
public class DownloadManager {
+ method @RequiresPermission(android.Manifest.permission.WRITE_MEDIA_STORAGE) public void onMediaStoreDownloadsDeleted(@NonNull android.util.LongSparseArray<java.lang.String>);
field public static final String ACTION_DOWNLOAD_COMPLETED = "android.intent.action.DOWNLOAD_COMPLETED";
}
@@ -1654,11 +1655,17 @@ package android.content {
method @NonNull public final android.os.UserHandle getSendingUser();
}
+ public abstract class ContentProvider implements android.content.ComponentCallbacks2 {
+ method public int checkUriPermission(@NonNull android.net.Uri, int, int);
+ }
+
public class ContentProviderClient implements java.lang.AutoCloseable {
method @RequiresPermission(android.Manifest.permission.REMOVE_TASKS) public void setDetectNotResponding(long);
}
public abstract class ContentResolver {
+ method @NonNull public static android.net.Uri decodeFromFile(@NonNull java.io.File);
+ method @NonNull public static java.io.File encodeToFile(@NonNull android.net.Uri);
method @Nullable @RequiresPermission("android.permission.CACHE_CONTENT") public android.os.Bundle getCache(@NonNull android.net.Uri);
method @RequiresPermission("android.permission.CACHE_CONTENT") public void putCache(@NonNull android.net.Uri, @Nullable android.os.Bundle);
}
@@ -3581,9 +3588,17 @@ package android.hardware.usb {
}
public class UsbManager {
+ method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public long getCurrentFunctions();
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_USB) public java.util.List<android.hardware.usb.UsbPort> getPorts();
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void grantPermission(android.hardware.usb.UsbDevice, String);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setCurrentFunctions(long);
field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_CHANGED = "android.hardware.usb.action.USB_PORT_CHANGED";
+ field public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE";
+ field public static final long FUNCTION_NONE = 0L; // 0x0L
+ field public static final long FUNCTION_RNDIS = 32L; // 0x20L
+ field public static final String USB_CONFIGURED = "configured";
+ field public static final String USB_CONNECTED = "connected";
+ field public static final String USB_FUNCTION_RNDIS = "rndis";
}
public final class UsbPort {
@@ -4680,6 +4695,7 @@ package android.net {
method @Deprecated @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String getCaptivePortalServerUrl();
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener);
method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
+ method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public int registerNetworkProvider(@NonNull android.net.NetworkProvider);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public boolean shouldAvoidBadWifi();
@@ -4687,6 +4703,7 @@ package android.net {
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void unregisterNetworkProvider(@NonNull android.net.NetworkProvider);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
@@ -4857,6 +4874,17 @@ package android.net {
field public final android.net.WifiKey wifiKey;
}
+ public class NetworkProvider {
+ ctor public NetworkProvider(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void declareNetworkRequestUnfulfillable(@NonNull android.net.NetworkRequest);
+ method @Nullable public android.os.Messenger getMessenger();
+ method @NonNull public String getName();
+ method public int getProviderId();
+ method public void onNetworkRequested(@NonNull android.net.NetworkRequest, int, int);
+ method public void onRequestWithdrawn(@NonNull android.net.NetworkRequest);
+ field public static final int ID_NONE = -1; // 0xffffffff
+ }
+
public abstract class NetworkRecommendationProvider {
ctor public NetworkRecommendationProvider(android.content.Context, java.util.concurrent.Executor);
method public final android.os.IBinder getBinder();
@@ -4900,6 +4928,33 @@ package android.net {
field public static final String PERMISSION_MAINLINE_NETWORK_STACK = "android.permission.MAINLINE_NETWORK_STACK";
}
+ public final class NetworkStats implements android.os.Parcelable {
+ ctor public NetworkStats(long, int);
+ method @NonNull public android.net.NetworkStats add(@NonNull android.net.NetworkStats);
+ method @NonNull public android.net.NetworkStats addValues(@NonNull android.net.NetworkStats.Entry);
+ method public int describeContents();
+ method @NonNull public android.net.NetworkStats subtract(@NonNull android.net.NetworkStats);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStats> CREATOR;
+ field public static final int DEFAULT_NETWORK_NO = 0; // 0x0
+ field public static final int DEFAULT_NETWORK_YES = 1; // 0x1
+ field @Nullable public static final String IFACE_ALL;
+ field public static final String IFACE_VT = "vt_data0";
+ field public static final int METERED_NO = 0; // 0x0
+ field public static final int METERED_YES = 1; // 0x1
+ field public static final int ROAMING_NO = 0; // 0x0
+ field public static final int ROAMING_YES = 1; // 0x1
+ field public static final int SET_DEFAULT = 0; // 0x0
+ field public static final int SET_FOREGROUND = 1; // 0x1
+ field public static final int TAG_NONE = 0; // 0x0
+ field public static final int UID_ALL = -1; // 0xffffffff
+ field public static final int UID_TETHERING = -5; // 0xfffffffb
+ }
+
+ public static class NetworkStats.Entry {
+ ctor public NetworkStats.Entry(@Nullable String, int, int, int, int, int, int, long, long, long, long, long);
+ }
+
public final class RouteInfo implements android.os.Parcelable {
ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int);
method public int getType();
@@ -5491,6 +5546,25 @@ package android.net.metrics {
}
+package android.net.netstats.provider {
+
+ public abstract class AbstractNetworkStatsProvider {
+ ctor public AbstractNetworkStatsProvider();
+ method public abstract void requestStatsUpdate(int);
+ method public abstract void setAlert(long);
+ method public abstract void setLimit(@NonNull String, long);
+ field public static final int QUOTA_UNLIMITED = -1; // 0xffffffff
+ }
+
+ public class NetworkStatsProviderCallback {
+ method public void onAlertReached();
+ method public void onLimitReached();
+ method public void onStatsUpdated(int, @NonNull android.net.NetworkStats, @NonNull android.net.NetworkStats);
+ method public void unregister();
+ }
+
+}
+
package android.net.util {
public final class SocketUtils {
@@ -6966,6 +7040,10 @@ package android.os {
method public boolean hasSingleFileDescriptor();
}
+ public class ParcelFileDescriptor implements java.io.Closeable android.os.Parcelable {
+ method @NonNull public static android.os.ParcelFileDescriptor wrap(@NonNull android.os.ParcelFileDescriptor, @NonNull android.os.Handler, @NonNull android.os.ParcelFileDescriptor.OnCloseListener) throws java.io.IOException;
+ }
+
public final class PowerManager {
method @RequiresPermission(allOf={android.Manifest.permission.READ_DREAM_STATE, android.Manifest.permission.WRITE_DREAM_STATE}) public void dream(long);
method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public boolean forceSuspend();
@@ -7369,6 +7447,10 @@ package android.os.storage {
field @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) public static final int FLAG_ALLOCATE_AGGRESSIVE = 1; // 0x1
}
+ public final class StorageVolume implements android.os.Parcelable {
+ method @NonNull public String getId();
+ }
+
}
package android.permission {
@@ -7788,6 +7870,7 @@ package android.provider {
field public static final String ACTION_NOTIFICATION_POLICY_ACCESS_DETAIL_SETTINGS = "android.settings.NOTIFICATION_POLICY_ACCESS_DETAIL_SETTINGS";
field public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE = "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
field public static final String ACTION_SHOW_ADMIN_SUPPORT_DETAILS = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
+ field public static final String ACTION_TETHER_PROVISIONING_UI = "android.settings.TETHER_PROVISIONING_UI";
}
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
@@ -7807,6 +7890,7 @@ package android.provider {
field public static final String INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS = "install_carrier_app_notification_sleep_millis";
field public static final String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
field public static final String REQUIRE_PASSWORD_TO_DECRYPT = "require_password_to_decrypt";
+ field public static final String TETHER_OFFLOAD_DISABLED = "tether_offload_disabled";
field public static final String TETHER_SUPPORTED = "tether_supported";
field public static final String THEATER_MODE_ON = "theater_mode_on";
field public static final String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
diff --git a/api/test-current.txt b/api/test-current.txt
index e64cbdb6eb10..d017dd63bdd3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2552,6 +2552,7 @@ package android.provider {
field public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
field public static final String ACTION_MANAGE_APP_OVERLAY_PERMISSION = "android.settings.MANAGE_APP_OVERLAY_PERMISSION";
field public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE = "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
+ field public static final String ACTION_TETHER_PROVISIONING_UI = "android.settings.TETHER_PROVISIONING_UI";
field public static final int RESET_MODE_PACKAGE_DEFAULTS = 1; // 0x1
}
@@ -2570,6 +2571,7 @@ package android.provider {
field public static final String LOW_POWER_MODE_STICKY = "low_power_sticky";
field public static final String NOTIFICATION_BUBBLES = "notification_bubbles";
field public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
+ field public static final String TETHER_OFFLOAD_DISABLED = "tether_offload_disabled";
field public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index a4f6f57c097e..b82a67556fc0 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3349,8 +3349,8 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void handleStartActivity(ActivityClientRecord r,
- PendingTransactionActions pendingActions) {
+ public void handleStartActivity(IBinder token, PendingTransactionActions pendingActions) {
+ final ActivityClientRecord r = mActivities.get(token);
final Activity activity = r.activity;
if (r.activity == null) {
// TODO(lifecycler): What do we do in this case?
@@ -3364,6 +3364,8 @@ public final class ActivityThread extends ClientTransactionHandler {
return;
}
+ unscheduleGcIdler();
+
// Start
activity.performStart("handleStartActivity");
r.setState(ON_START);
@@ -3400,6 +3402,9 @@ public final class ActivityThread extends ClientTransactionHandler {
+ " did not call through to super.onPostCreate()");
}
}
+
+ updateVisibility(r, true /* show */);
+ mSomeActivitiesChanged = true;
}
/**
@@ -4660,8 +4665,8 @@ public final class ActivityThread extends ClientTransactionHandler {
@UnsupportedAppUsage
final void performStopActivity(IBinder token, boolean saveState, String reason) {
ActivityClientRecord r = mActivities.get(token);
- performStopActivityInner(r, null /* stopInfo */, false /* keepShown */, saveState,
- false /* finalStateRequest */, reason);
+ performStopActivityInner(r, null /* stopInfo */, saveState, false /* finalStateRequest */,
+ reason);
}
private static final class ProviderRefCount {
@@ -4687,25 +4692,19 @@ public final class ActivityThread extends ClientTransactionHandler {
}
/**
- * Core implementation of stopping an activity. Note this is a little
- * tricky because the server's meaning of stop is slightly different
- * than our client -- for the server, stop means to save state and give
- * it the result when it is done, but the window may still be visible.
- * For the client, we want to call onStop()/onStart() to indicate when
- * the activity's UI visibility changes.
+ * Core implementation of stopping an activity.
* @param r Target activity client record.
* @param info Action that will report activity stop to server.
- * @param keepShown Flag indicating whether the activity is still shown.
* @param saveState Flag indicating whether the activity state should be saved.
* @param finalStateRequest Flag indicating if this call is handling final lifecycle state
* request for a transaction.
* @param reason Reason for performing this operation.
*/
- private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean keepShown,
+ private void performStopActivityInner(ActivityClientRecord r, StopInfo info,
boolean saveState, boolean finalStateRequest, String reason) {
if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
if (r != null) {
- if (!keepShown && r.stopped) {
+ if (r.stopped) {
if (r.activity.mFinished) {
// If we are finishing, we won't call onResume() in certain
// cases. So here we likewise don't want to call onStop()
@@ -4740,9 +4739,7 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
- if (!keepShown) {
- callActivityOnStop(r, saveState, reason);
- }
+ callActivityOnStop(r, saveState, reason);
}
}
@@ -4810,20 +4807,19 @@ public final class ActivityThread extends ClientTransactionHandler {
}
@Override
- public void handleStopActivity(IBinder token, boolean show, int configChanges,
+ public void handleStopActivity(IBinder token, int configChanges,
PendingTransactionActions pendingActions, boolean finalStateRequest, String reason) {
final ActivityClientRecord r = mActivities.get(token);
r.activity.mConfigChangeFlags |= configChanges;
final StopInfo stopInfo = new StopInfo();
- performStopActivityInner(r, stopInfo, show, true /* saveState */, finalStateRequest,
+ performStopActivityInner(r, stopInfo, true /* saveState */, finalStateRequest,
reason);
if (localLOGV) Slog.v(
- TAG, "Finishing stop of " + r + ": show=" + show
- + " win=" + r.window);
+ TAG, "Finishing stop of " + r + ": win=" + r.window);
- updateVisibility(r, show);
+ updateVisibility(r, false);
// Make sure any pending writes are now committed.
if (!r.isPreHoneycomb()) {
@@ -4859,34 +4855,6 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
- @Override
- public void handleWindowVisibility(IBinder token, boolean show) {
- ActivityClientRecord r = mActivities.get(token);
-
- if (r == null) {
- Log.w(TAG, "handleWindowVisibility: no activity for token " + token);
- return;
- }
-
- if (!show && !r.stopped) {
- performStopActivityInner(r, null /* stopInfo */, show, false /* saveState */,
- false /* finalStateRequest */, "handleWindowVisibility");
- } else if (show && r.getLifecycleState() == ON_STOP) {
- // If we are getting ready to gc after going to the background, well
- // we are back active so skip it.
- unscheduleGcIdler();
-
- r.activity.performRestart(true /* start */, "handleWindowVisibility");
- r.setState(ON_START);
- }
- if (r.activity.mDecor != null) {
- if (false) Slog.v(
- TAG, "Handle window " + r + " visibility: " + show);
- updateVisibility(r, show);
- }
- mSomeActivitiesChanged = true;
- }
-
// TODO: This method should be changed to use {@link #performStopActivityInner} to perform to
// stop operation on the activity to reduce code duplication and the chance of fixing a bug in
// one place and missing the other.
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index f9a689a7e1de..d2235f10da99 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -119,7 +119,6 @@ public abstract class ClientTransactionHandler {
/**
* Stop the activity.
* @param token Target activity token.
- * @param show Flag indicating whether activity is still shown.
* @param configChanges Activity configuration changes.
* @param pendingActions Pending actions to be used on this or later stages of activity
* transaction.
@@ -127,7 +126,7 @@ public abstract class ClientTransactionHandler {
* request for a transaction.
* @param reason Reason for performing this operation.
*/
- public abstract void handleStopActivity(IBinder token, boolean show, int configChanges,
+ public abstract void handleStopActivity(IBinder token, int configChanges,
PendingTransactionActions pendingActions, boolean finalStateRequest, String reason);
/** Report that activity was stopped to server. */
@@ -161,15 +160,12 @@ public abstract class ClientTransactionHandler {
/** Request that an activity enter picture-in-picture. */
public abstract void handlePictureInPictureRequested(IBinder token);
- /** Update window visibility. */
- public abstract void handleWindowVisibility(IBinder token, boolean show);
-
/** Perform activity launch. */
public abstract Activity handleLaunchActivity(ActivityThread.ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent);
/** Perform activity start. */
- public abstract void handleStartActivity(ActivityThread.ActivityClientRecord r,
+ public abstract void handleStartActivity(IBinder token,
PendingTransactionActions pendingActions);
/** Get package info. */
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 49c389a0c4a7..1278ff6817fd 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -16,7 +16,9 @@
package android.app;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -40,11 +42,13 @@ import android.os.Environment;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.provider.BaseColumns;
import android.provider.Downloads;
import android.provider.MediaStore;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
+import android.util.LongSparseArray;
import android.util.Pair;
import java.io.File;
@@ -1069,6 +1073,37 @@ public class DownloadManager {
}
/**
+ * Notify {@link DownloadManager} that the given {@link MediaStore} items
+ * were just deleted so that {@link DownloadManager} internal data
+ * structures can be cleaned up.
+ *
+ * @param idToMime map from {@link BaseColumns#_ID} to
+ * {@link ContentResolver#getType(Uri)}.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_MEDIA_STORAGE)
+ public void onMediaStoreDownloadsDeleted(@NonNull LongSparseArray<String> idToMime) {
+ try (ContentProviderClient client = mResolver
+ .acquireUnstableContentProviderClient(mBaseUri)) {
+ final Bundle callExtras = new Bundle();
+ final long[] ids = new long[idToMime.size()];
+ final String[] mimeTypes = new String[idToMime.size()];
+ for (int i = idToMime.size() - 1; i >= 0; --i) {
+ ids[i] = idToMime.keyAt(i);
+ mimeTypes[i] = idToMime.valueAt(i);
+ }
+ callExtras.putLongArray(android.provider.Downloads.EXTRA_IDS, ids);
+ callExtras.putStringArray(android.provider.Downloads.EXTRA_MIME_TYPES,
+ mimeTypes);
+ client.call(android.provider.Downloads.CALL_MEDIASTORE_DOWNLOADS_DELETED,
+ null, callExtras);
+ } catch (RemoteException e) {
+ // Should not happen
+ }
+ }
+
+ /**
* Enqueue a new download. The download will start automatically once the download manager is
* ready to execute it and connectivity is available.
*
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 4033aea32b55..7cdf85e0a6b8 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -177,7 +177,7 @@ public class LocalActivityManager {
pendingActions = null;
}
- mActivityThread.handleStartActivity(clientRecord, pendingActions);
+ mActivityThread.handleStartActivity(r, pendingActions);
r.curState = STARTED;
if (desiredState == RESUMED) {
diff --git a/core/java/android/app/servertransaction/WindowVisibilityItem.java b/core/java/android/app/servertransaction/StartActivityItem.java
index 115d1ececc0e..4fbe02b9cf76 100644
--- a/core/java/android/app/servertransaction/WindowVisibilityItem.java
+++ b/core/java/android/app/servertransaction/StartActivityItem.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2019 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.
@@ -24,41 +24,44 @@ import android.os.Parcel;
import android.os.Trace;
/**
- * Window visibility change message.
+ * Request to move an activity to started and visible state.
* @hide
*/
-public class WindowVisibilityItem extends ClientTransactionItem {
+public class StartActivityItem extends ActivityLifecycleItem {
- private boolean mShowWindow;
+ private static final String TAG = "StartActivityItem";
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
- Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER,
- mShowWindow ? "activityShowWindow" : "activityHideWindow");
- client.handleWindowVisibility(token, mShowWindow);
+ Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "startActivityItem");
+ client.handleStartActivity(token, pendingActions);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
+ @Override
+ public int getTargetState() {
+ return ON_START;
+ }
+
// ObjectPoolItem implementation
- private WindowVisibilityItem() {}
+ private StartActivityItem() {}
/** Obtain an instance initialized with provided params. */
- public static WindowVisibilityItem obtain(boolean showWindow) {
- WindowVisibilityItem instance = ObjectPool.obtain(WindowVisibilityItem.class);
+ public static StartActivityItem obtain() {
+ StartActivityItem instance = ObjectPool.obtain(StartActivityItem.class);
if (instance == null) {
- instance = new WindowVisibilityItem();
+ instance = new StartActivityItem();
}
- instance.mShowWindow = showWindow;
return instance;
}
@Override
public void recycle() {
- mShowWindow = false;
+ super.recycle();
ObjectPool.recycle(this);
}
@@ -68,24 +71,24 @@ public class WindowVisibilityItem extends ClientTransactionItem {
/** Write to Parcel. */
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeBoolean(mShowWindow);
+ // Empty
}
/** Read from Parcel. */
- private WindowVisibilityItem(Parcel in) {
- mShowWindow = in.readBoolean();
+ private StartActivityItem(Parcel in) {
+ // Empty
}
- public static final @android.annotation.NonNull Creator<WindowVisibilityItem> CREATOR =
- new Creator<WindowVisibilityItem>() {
- public WindowVisibilityItem createFromParcel(Parcel in) {
- return new WindowVisibilityItem(in);
- }
+ public static final @android.annotation.NonNull Creator<StartActivityItem> CREATOR =
+ new Creator<StartActivityItem>() {
+ public StartActivityItem createFromParcel(Parcel in) {
+ return new StartActivityItem(in);
+ }
- public WindowVisibilityItem[] newArray(int size) {
- return new WindowVisibilityItem[size];
- }
- };
+ public StartActivityItem[] newArray(int size) {
+ return new StartActivityItem[size];
+ }
+ };
@Override
public boolean equals(Object o) {
@@ -95,17 +98,17 @@ public class WindowVisibilityItem extends ClientTransactionItem {
if (o == null || getClass() != o.getClass()) {
return false;
}
- final WindowVisibilityItem other = (WindowVisibilityItem) o;
- return mShowWindow == other.mShowWindow;
+ return true;
}
@Override
public int hashCode() {
- return 17 + 31 * (mShowWindow ? 1 : 0);
+ return 17;
}
@Override
public String toString() {
- return "WindowVisibilityItem{showWindow=" + mShowWindow + "}";
+ return "StartActivityItem{}";
}
}
+
diff --git a/core/java/android/app/servertransaction/StopActivityItem.java b/core/java/android/app/servertransaction/StopActivityItem.java
index 63efa6fe7c17..8668bd49c8f5 100644
--- a/core/java/android/app/servertransaction/StopActivityItem.java
+++ b/core/java/android/app/servertransaction/StopActivityItem.java
@@ -31,14 +31,13 @@ public class StopActivityItem extends ActivityLifecycleItem {
private static final String TAG = "StopActivityItem";
- private boolean mShowWindow;
private int mConfigChanges;
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
- client.handleStopActivity(token, mShowWindow, mConfigChanges, pendingActions,
+ client.handleStopActivity(token, mConfigChanges, pendingActions,
true /* finalStateRequest */, "STOP_ACTIVITY_ITEM");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -59,13 +58,15 @@ public class StopActivityItem extends ActivityLifecycleItem {
private StopActivityItem() {}
- /** Obtain an instance initialized with provided params. */
- public static StopActivityItem obtain(boolean showWindow, int configChanges) {
+ /**
+ * Obtain an instance initialized with provided params.
+ * @param configChanges Configuration pieces that changed.
+ */
+ public static StopActivityItem obtain(int configChanges) {
StopActivityItem instance = ObjectPool.obtain(StopActivityItem.class);
if (instance == null) {
instance = new StopActivityItem();
}
- instance.mShowWindow = showWindow;
instance.mConfigChanges = configChanges;
return instance;
@@ -74,7 +75,6 @@ public class StopActivityItem extends ActivityLifecycleItem {
@Override
public void recycle() {
super.recycle();
- mShowWindow = false;
mConfigChanges = 0;
ObjectPool.recycle(this);
}
@@ -85,13 +85,11 @@ public class StopActivityItem extends ActivityLifecycleItem {
/** Write to Parcel. */
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeBoolean(mShowWindow);
dest.writeInt(mConfigChanges);
}
/** Read from Parcel. */
private StopActivityItem(Parcel in) {
- mShowWindow = in.readBoolean();
mConfigChanges = in.readInt();
}
@@ -115,20 +113,18 @@ public class StopActivityItem extends ActivityLifecycleItem {
return false;
}
final StopActivityItem other = (StopActivityItem) o;
- return mShowWindow == other.mShowWindow && mConfigChanges == other.mConfigChanges;
+ return mConfigChanges == other.mConfigChanges;
}
@Override
public int hashCode() {
int result = 17;
- result = 31 * result + (mShowWindow ? 1 : 0);
result = 31 * result + mConfigChanges;
return result;
}
@Override
public String toString() {
- return "StopActivityItem{showWindow=" + mShowWindow + ",configChanges=" + mConfigChanges
- + "}";
+ return "StopActivityItem{configChanges=" + mConfigChanges + "}";
}
}
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index 20e0da3ead8a..17fcda587322 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -218,7 +218,7 @@ public class TransactionExecutor {
null /* customIntent */);
break;
case ON_START:
- mTransactionHandler.handleStartActivity(r, mPendingActions);
+ mTransactionHandler.handleStartActivity(r.token, mPendingActions);
break;
case ON_RESUME:
mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
@@ -230,8 +230,8 @@ public class TransactionExecutor {
"LIFECYCLER_PAUSE_ACTIVITY");
break;
case ON_STOP:
- mTransactionHandler.handleStopActivity(r.token, false /* show */,
- 0 /* configChanges */, mPendingActions, false /* finalStateRequest */,
+ mTransactionHandler.handleStopActivity(r.token, 0 /* configChanges */,
+ mPendingActions, false /* finalStateRequest */,
"LIFECYCLER_STOP_ACTIVITY");
break;
case ON_DESTROY:
diff --git a/core/java/android/app/servertransaction/TransactionExecutorHelper.java b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
index 0ea8c3c159fa..6df92a78cc9f 100644
--- a/core/java/android/app/servertransaction/TransactionExecutorHelper.java
+++ b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
@@ -183,8 +183,7 @@ public class TransactionExecutorHelper {
lifecycleItem = PauseActivityItem.obtain();
break;
case ON_STOP:
- lifecycleItem = StopActivityItem.obtain(r.isVisibleFromServer(),
- 0 /* configChanges */);
+ lifecycleItem = StopActivityItem.obtain(0 /* configChanges */);
break;
default:
lifecycleItem = ResumeActivityItem.obtain(false /* isForward */);
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 393d48891d64..85826fd4e669 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -27,6 +27,7 @@ import static android.os.Trace.TRACE_TAG_DATABASE;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.app.AppOpsManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.PackageManager;
@@ -942,7 +943,18 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
return null;
}
- /** {@hide} */
+ /**
+ * Return the package name of the caller that initiated the request being
+ * processed on the current thread. The returned package will have
+ * <em>not</em> been verified to belong to the calling UID. Returns
+ * {@code null} if not currently processing a request.
+ * <p>
+ * This will always return {@code null} when processing
+ * {@link #getType(Uri)} or {@link #getStreamTypes(Uri, String)} requests.
+ *
+ * @see Binder#getCallingUid()
+ * @see Context#grantUriPermission(String, Uri, int)
+ */
public final @Nullable String getCallingPackageUnchecked() {
final Pair<String, String> pkg = mCallingPackage.get();
if (pkg != null) {
@@ -952,7 +964,14 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
return null;
}
- /** {@hide} */
+ /**
+ * Called whenever the value of {@link #getCallingPackage()} changes, giving
+ * the provider an opportunity to invalidate any security related caching it
+ * may be performing.
+ * <p>
+ * This typically happens when a {@link ContentProvider} makes a nested call
+ * back into itself when already processing a call from a remote process.
+ */
public void onCallingPackageChanged() {
}
@@ -1390,8 +1409,11 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
* @param uri The URI to query. This will be the full URI sent by the client.
* @param projection The list of columns to put into the cursor.
* If {@code null} provide a default set of columns.
- * @param queryArgs A Bundle containing all additional information necessary for the query.
- * Values in the Bundle may include SQL style arguments.
+ * @param queryArgs A Bundle containing additional information necessary for
+ * the operation. Arguments may include SQL style arguments, such
+ * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
+ * the documentation for each individual provider will indicate
+ * which arguments they support.
* @param cancellationSignal A signal to cancel the operation in progress,
* or {@code null}.
* @return a Cursor or {@code null}.
@@ -1525,8 +1547,24 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
return false;
}
- /** {@hide} */
+ /**
+ * Perform a detailed internal check on a {@link Uri} to determine if a UID
+ * is able to access it with specific mode flags.
+ * <p>
+ * This method is typically used when the provider implements more dynamic
+ * access controls that cannot be expressed with {@code <path-permission>}
+ * style static rules.
+ *
+ * @param uri the {@link Uri} to perform an access check on.
+ * @param uid the UID to check the permission for.
+ * @param modeFlags the access flags to use for the access check, such as
+ * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}.
+ * @return {@link PackageManager#PERMISSION_GRANTED} if access is allowed,
+ * otherwise {@link PackageManager#PERMISSION_DENIED}.
+ * @hide
+ */
@Override
+ @SystemApi
public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) {
return PackageManager.PERMISSION_DENIED;
}
@@ -1574,9 +1612,14 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
*
* @param uri The content:// URI of the insertion request.
* @param values A set of column_name/value pairs to add to the database.
- * @param extras A Bundle containing all additional information necessary
- * for the insert.
+ * @param extras A Bundle containing additional information necessary for
+ * the operation. Arguments may include SQL style arguments, such
+ * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
+ * the documentation for each individual provider will indicate
+ * which arguments they support.
* @return The URI for the newly inserted item.
+ * @throws IllegalArgumentException if the provider doesn't support one of
+ * the requested Bundle arguments.
*/
@Override
public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values,
@@ -1653,10 +1696,13 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
*
* @param uri The full URI to query, including a row ID (if a specific
* record is requested).
- * @param extras A Bundle containing all additional information necessary
- * for the delete. Values in the Bundle may include SQL style
- * arguments.
- * @return The number of rows affected.
+ * @param extras A Bundle containing additional information necessary for
+ * the operation. Arguments may include SQL style arguments, such
+ * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
+ * the documentation for each individual provider will indicate
+ * which arguments they support.
+ * @throws IllegalArgumentException if the provider doesn't support one of
+ * the requested Bundle arguments.
* @throws SQLException
*/
@Override
@@ -1699,10 +1745,14 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
* @param uri The URI to query. This can potentially have a record ID if
* this is an update request for a specific record.
* @param values A set of column_name/value pairs to update in the database.
- * @param extras A Bundle containing all additional information necessary
- * for the update. Values in the Bundle may include SQL style
- * arguments.
+ * @param extras A Bundle containing additional information necessary for
+ * the operation. Arguments may include SQL style arguments, such
+ * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
+ * the documentation for each individual provider will indicate
+ * which arguments they support.
* @return the number of rows affected.
+ * @throws IllegalArgumentException if the provider doesn't support one of
+ * the requested Bundle arguments.
*/
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values,
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 93f42879d946..494d2aeaf42a 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -18,7 +18,7 @@ package android.content;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
diff --git a/core/java/android/content/ContentProviderResult.java b/core/java/android/content/ContentProviderResult.java
index 11dda83a6e6c..4fb1ddb958d5 100644
--- a/core/java/android/content/ContentProviderResult.java
+++ b/core/java/android/content/ContentProviderResult.java
@@ -36,7 +36,7 @@ public class ContentProviderResult implements Parcelable {
public final @Nullable Uri uri;
public final @Nullable Integer count;
public final @Nullable Bundle extras;
- public final @Nullable Exception exception;
+ public final @Nullable Throwable exception;
public ContentProviderResult(@NonNull Uri uri) {
this(Objects.requireNonNull(uri), null, null, null);
@@ -50,12 +50,12 @@ public class ContentProviderResult implements Parcelable {
this(null, null, Objects.requireNonNull(extras), null);
}
- public ContentProviderResult(@NonNull Exception exception) {
+ public ContentProviderResult(@NonNull Throwable exception) {
this(null, null, null, exception);
}
/** {@hide} */
- public ContentProviderResult(Uri uri, Integer count, Bundle extras, Exception exception) {
+ public ContentProviderResult(Uri uri, Integer count, Bundle extras, Throwable exception) {
this.uri = uri;
this.count = count;
this.extras = extras;
@@ -79,7 +79,7 @@ public class ContentProviderResult implements Parcelable {
extras = null;
}
if (source.readInt() != 0) {
- exception = (Exception) ParcelableException.readFromParcel(source);
+ exception = ParcelableException.readFromParcel(source);
} else {
exception = null;
}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 1d3c6505f677..6cd1cd3354c2 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -984,7 +984,11 @@ public abstract class ContentResolver implements ContentInterface {
* retrieve.
* @param projection A list of which columns to return. Passing null will
* return all columns, which is inefficient.
- * @param queryArgs A Bundle containing any arguments to the query.
+ * @param queryArgs A Bundle containing additional information necessary for
+ * the operation. Arguments may include SQL style arguments, such
+ * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
+ * the documentation for each individual provider will indicate
+ * which arguments they support.
* @param cancellationSignal A signal to cancel the operation in progress, or null if none.
* If the operation is canceled, then {@link OperationCanceledException} will be thrown
* when the query is executed.
@@ -1925,9 +1929,15 @@ public abstract class ContentResolver implements ContentInterface {
* @param url The URL of the table to insert into.
* @param values The initial values for the newly inserted row. The key is the column name for
* the field. Passing an empty ContentValues will create an empty row.
- * @param extras A Bundle containing all additional information necessary for the insert.
+ * @param extras A Bundle containing additional information necessary for
+ * the operation. Arguments may include SQL style arguments, such
+ * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
+ * the documentation for each individual provider will indicate
+ * which arguments they support.
* @return the URL of the newly created row. May return <code>null</code> if the underlying
* content provider returns <code>null</code>, or if it crashes.
+ * @throws IllegalArgumentException if the provider doesn't support one of
+ * the requested Bundle arguments.
*/
@Override
public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
@@ -2061,9 +2071,14 @@ public abstract class ContentResolver implements ContentInterface {
* If the content provider supports transactions, the deletion will be atomic.
*
* @param url The URL of the row to delete.
- * @param extras A Bundle containing all additional information necessary for the delete.
- * Values in the Bundle may include SQL style arguments.
+ * @param extras A Bundle containing additional information necessary for
+ * the operation. Arguments may include SQL style arguments, such
+ * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
+ * the documentation for each individual provider will indicate
+ * which arguments they support.
* @return The number of rows deleted.
+ * @throws IllegalArgumentException if the provider doesn't support one of
+ * the requested Bundle arguments.
*/
@Override
public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable Bundle extras) {
@@ -2121,10 +2136,15 @@ public abstract class ContentResolver implements ContentInterface {
* @param uri The URI to modify.
* @param values The new field values. The key is the column name for the field.
A null value will remove an existing field value.
- * @param extras A Bundle containing all additional information necessary for the update.
- * Values in the Bundle may include SQL style arguments.
+ * @param extras A Bundle containing additional information necessary for
+ * the operation. Arguments may include SQL style arguments, such
+ * as {@link ContentResolver#QUERY_ARG_SQL_LIMIT}, but note that
+ * the documentation for each individual provider will indicate
+ * which arguments they support.
* @return the number of rows updated.
* @throws NullPointerException if uri or values are null
+ * @throws IllegalArgumentException if the provider doesn't support one of
+ * the requested Bundle arguments.
*/
@Override
public final int update(@RequiresPermission.Write @NonNull Uri uri,
@@ -3851,15 +3871,47 @@ public abstract class ContentResolver implements ContentInterface {
}
}
+ /**
+ * Decode a path generated by {@link #encodeToFile(Uri)} back into
+ * the original {@link Uri}.
+ * <p>
+ * This is used to offer a way to intercept filesystem calls in
+ * {@link ContentProvider} unaware code and redirect them to a
+ * {@link ContentProvider} when they attempt to use {@code _DATA} columns
+ * that are otherwise deprecated.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static @NonNull Uri decodeFromFile(@NonNull File file) {
+ return translateDeprecatedDataPath(file.getAbsolutePath());
+ }
+
+ /**
+ * Encode a {@link Uri} into an opaque filesystem path which can then be
+ * resurrected by {@link #decodeFromFile(File)}.
+ * <p>
+ * This is used to offer a way to intercept filesystem calls in
+ * {@link ContentProvider} unaware code and redirect them to a
+ * {@link ContentProvider} when they attempt to use {@code _DATA} columns
+ * that are otherwise deprecated.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static @NonNull File encodeToFile(@NonNull Uri uri) {
+ return new File(translateDeprecatedDataPath(uri));
+ }
+
/** {@hide} */
- public static Uri translateDeprecatedDataPath(String path) {
+ public static @NonNull Uri translateDeprecatedDataPath(@NonNull String path) {
final String ssp = "//" + path.substring(DEPRECATE_DATA_PREFIX.length());
return Uri.parse(new Uri.Builder().scheme(SCHEME_CONTENT)
.encodedOpaquePart(ssp).build().toString());
}
/** {@hide} */
- public static String translateDeprecatedDataPath(Uri uri) {
+ public static @NonNull String translateDeprecatedDataPath(@NonNull Uri uri) {
return DEPRECATE_DATA_PREFIX + uri.getEncodedSchemeSpecificPart().substring(2);
}
}
diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
index ac2e373f000d..6639b3d5c0b5 100644
--- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
@@ -18,7 +18,7 @@ package android.content.pm.parsing;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
diff --git a/core/java/android/content/pm/parsing/ComponentParseUtils.java b/core/java/android/content/pm/parsing/ComponentParseUtils.java
index 595685729a0c..f04a30ce4239 100644
--- a/core/java/android/content/pm/parsing/ComponentParseUtils.java
+++ b/core/java/android/content/pm/parsing/ComponentParseUtils.java
@@ -27,8 +27,8 @@ import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityTaskManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index bba14c39de72..36ec67ee1471 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -35,8 +35,8 @@ import com.android.internal.util.ArrayUtils;
import libcore.util.EmptyArray;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Iterator;
-import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
@@ -56,7 +56,7 @@ public class SQLiteQueryBuilder {
"(?i)(AVG|COUNT|MAX|MIN|SUM|TOTAL|GROUP_CONCAT)\\((.+)\\)");
private Map<String, String> mProjectionMap = null;
- private List<Pattern> mProjectionGreylist = null;
+ private Collection<Pattern> mProjectionGreylist = null;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private String mTables = "";
@@ -196,20 +196,16 @@ public class SQLiteQueryBuilder {
* Sets a projection greylist of columns that will be allowed through, even
* when {@link #setStrict(boolean)} is enabled. This provides a way for
* abusive custom columns like {@code COUNT(*)} to continue working.
- *
- * @hide
*/
- public void setProjectionGreylist(@Nullable List<Pattern> projectionGreylist) {
+ public void setProjectionGreylist(@Nullable Collection<Pattern> projectionGreylist) {
mProjectionGreylist = projectionGreylist;
}
/**
* Gets the projection greylist for the query, as last configured by
- * {@link #setProjectionGreylist(List)}.
- *
- * @hide
+ * {@link #setProjectionGreylist}.
*/
- public @Nullable List<Pattern> getProjectionGreylist() {
+ public @Nullable Collection<Pattern> getProjectionGreylist() {
return mProjectionGreylist;
}
@@ -244,25 +240,27 @@ public class SQLiteQueryBuilder {
}
/**
- * When set, the selection is verified against malicious arguments.
- * When using this class to create a statement using
+ * When set, the selection is verified against malicious arguments. When
+ * using this class to create a statement using
* {@link #buildQueryString(boolean, String, String[], String, String, String, String, String)},
- * non-numeric limits will raise an exception. If a projection map is specified, fields
- * not in that map will be ignored.
- * If this class is used to execute the statement directly using
+ * non-numeric limits will raise an exception. If a projection map is
+ * specified, fields not in that map will be ignored. If this class is used
+ * to execute the statement directly using
* {@link #query(SQLiteDatabase, String[], String, String[], String, String, String)}
* or
* {@link #query(SQLiteDatabase, String[], String, String[], String, String, String, String)},
- * additionally also parenthesis escaping selection are caught.
- *
- * To summarize: To get maximum protection against malicious third party apps (for example
- * content provider consumers), make sure to do the following:
+ * additionally also parenthesis escaping selection are caught. To
+ * summarize: To get maximum protection against malicious third party apps
+ * (for example content provider consumers), make sure to do the following:
* <ul>
* <li>Set this value to true</li>
* <li>Use a projection map</li>
- * <li>Use one of the query overloads instead of getting the statement as a sql string</li>
+ * <li>Use one of the query overloads instead of getting the statement as a
+ * sql string</li>
* </ul>
- * By default, this value is false.
+ * <p>
+ * This feature is disabled by default on each newly constructed
+ * {@link SQLiteQueryBuilder} and needs to be manually enabled.
*/
public void setStrict(boolean strict) {
if (strict) {
@@ -287,6 +285,9 @@ public class SQLiteQueryBuilder {
* This enforcement applies to {@link #insert}, {@link #query}, and
* {@link #update} operations. Any enforcement failures will throw an
* {@link IllegalArgumentException}.
+ * <p>
+ * This feature is disabled by default on each newly constructed
+ * {@link SQLiteQueryBuilder} and needs to be manually enabled.
*/
public void setStrictColumns(boolean strictColumns) {
if (strictColumns) {
@@ -323,6 +324,9 @@ public class SQLiteQueryBuilder {
* {@link #delete} operations. This enforcement does not apply to trusted
* inputs, such as those provided by {@link #appendWhere}. Any enforcement
* failures will throw an {@link IllegalArgumentException}.
+ * <p>
+ * This feature is disabled by default on each newly constructed
+ * {@link SQLiteQueryBuilder} and needs to be manually enabled.
*/
public void setStrictGrammar(boolean strictGrammar) {
if (strictGrammar) {
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 638d81b2f635..6e1987c47d20 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -90,4 +90,11 @@ interface IInputManager {
/** Create an input monitor for gestures. */
InputMonitor monitorGestureInput(String name, int displayId);
+
+ // Add a runtime association between the input port and the display port. This overrides any
+ // static associations.
+ void addPortAssociation(in String inputPort, int displayPort);
+ // Remove the runtime association between the input port and the display port. Any existing
+ // static association for the cleared input port will be restored.
+ void removePortAssociation(in String inputPort);
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 8d32db013fb3..83f01a5dca35 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -17,6 +17,7 @@
package android.hardware.input;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
@@ -963,6 +964,41 @@ public final class InputManager {
}
}
+ /**
+ * Add a runtime association between the input port and the display port. This overrides any
+ * static associations.
+ * @param inputPort The port of the input device.
+ * @param displayPort The physical port of the associated display.
+ * <p>
+ * Requires {@link android.Manifest.permissions.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT}.
+ * </p>
+ * @hide
+ */
+ public void addPortAssociation(@NonNull String inputPort, int displayPort) {
+ try {
+ mIm.addPortAssociation(inputPort, displayPort);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Remove the runtime association between the input port and the display port. Any existing
+ * static association for the cleared input port will be restored.
+ * @param inputPort The port of the input device to be cleared.
+ * <p>
+ * Requires {@link android.Manifest.permissions.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT}.
+ * </p>
+ * @hide
+ */
+ public void removePortAssociation(@NonNull String inputPort) {
+ try {
+ mIm.removePortAssociation(inputPort);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
private void populateInputDevicesLocked() {
if (mInputDevicesChangedListener == null) {
final InputDevicesChangedListener listener = new InputDevicesChangedListener();
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 73b9d1739061..67fdda37ed3b 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -91,7 +91,7 @@ public class UsbManager {
*
* {@hide}
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final String ACTION_USB_STATE =
"android.hardware.usb.action.USB_STATE";
@@ -164,7 +164,7 @@ public class UsbManager {
*
* {@hide}
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final String USB_CONNECTED = "connected";
/**
@@ -181,6 +181,7 @@ public class UsbManager {
*
* {@hide}
*/
+ @SystemApi
public static final String USB_CONFIGURED = "configured";
/**
@@ -217,6 +218,7 @@ public class UsbManager {
*
* {@hide}
*/
+ @SystemApi
public static final String USB_FUNCTION_RNDIS = "rndis";
/**
@@ -319,6 +321,7 @@ public class UsbManager {
* Code for the charging usb function. Passed into {@link #setCurrentFunctions(long)}
* {@hide}
*/
+ @SystemApi
public static final long FUNCTION_NONE = 0;
/**
@@ -337,6 +340,7 @@ public class UsbManager {
* Code for the rndis usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
* {@hide}
*/
+ @SystemApi
public static final long FUNCTION_RNDIS = GadgetFunction.RNDIS;
/**
@@ -698,6 +702,8 @@ public class UsbManager {
*
* {@hide}
*/
+ @SystemApi
+ @RequiresPermission(Manifest.permission.MANAGE_USB)
public void setCurrentFunctions(long functions) {
try {
mService.setCurrentFunctions(functions);
@@ -737,6 +743,8 @@ public class UsbManager {
*
* {@hide}
*/
+ @SystemApi
+ @RequiresPermission(Manifest.permission.MANAGE_USB)
public long getCurrentFunctions() {
try {
return mService.getCurrentFunctions();
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 6da16a82c822..03d4200bd90f 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -363,7 +363,7 @@ public class ConnectivityManager {
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@UnsupportedAppUsage
public static final String ACTION_TETHER_STATE_CHANGED =
- "android.net.conn.TETHER_STATE_CHANGED";
+ TetheringManager.ACTION_TETHER_STATE_CHANGED;
/**
* @hide
@@ -371,14 +371,14 @@ public class ConnectivityManager {
* tethering and currently available for tethering.
*/
@UnsupportedAppUsage
- public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
+ public static final String EXTRA_AVAILABLE_TETHER = TetheringManager.EXTRA_AVAILABLE_TETHER;
/**
* @hide
* gives a String[] listing all the interfaces currently in local-only
* mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding)
*/
- public static final String EXTRA_ACTIVE_LOCAL_ONLY = "localOnlyArray";
+ public static final String EXTRA_ACTIVE_LOCAL_ONLY = TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY;
/**
* @hide
@@ -386,7 +386,7 @@ public class ConnectivityManager {
* (ie, has DHCPv4 support and packets potentially forwarded/NATed)
*/
@UnsupportedAppUsage
- public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
+ public static final String EXTRA_ACTIVE_TETHER = TetheringManager.EXTRA_ACTIVE_TETHER;
/**
* @hide
@@ -395,7 +395,7 @@ public class ConnectivityManager {
* for any interfaces listed here.
*/
@UnsupportedAppUsage
- public static final String EXTRA_ERRORED_TETHER = "erroredArray";
+ public static final String EXTRA_ERRORED_TETHER = TetheringManager.EXTRA_ERRORED_TETHER;
/**
* Broadcast Action: The captive portal tracker has finished its test.
@@ -445,7 +445,7 @@ public class ConnectivityManager {
* @see #startTethering(int, boolean, OnStartTetheringCallback)
* @hide
*/
- public static final int TETHERING_INVALID = -1;
+ public static final int TETHERING_INVALID = TetheringManager.TETHERING_INVALID;
/**
* Wifi tethering type.
@@ -453,7 +453,7 @@ public class ConnectivityManager {
* @hide
*/
@SystemApi
- public static final int TETHERING_WIFI = 0;
+ public static final int TETHERING_WIFI = TetheringManager.TETHERING_WIFI;
/**
* USB tethering type.
@@ -461,7 +461,7 @@ public class ConnectivityManager {
* @hide
*/
@SystemApi
- public static final int TETHERING_USB = 1;
+ public static final int TETHERING_USB = TetheringManager.TETHERING_USB;
/**
* Bluetooth tethering type.
@@ -469,7 +469,7 @@ public class ConnectivityManager {
* @hide
*/
@SystemApi
- public static final int TETHERING_BLUETOOTH = 2;
+ public static final int TETHERING_BLUETOOTH = TetheringManager.TETHERING_BLUETOOTH;
/**
* Wifi P2p tethering type.
@@ -477,41 +477,41 @@ public class ConnectivityManager {
* need to start from #startTethering(int, boolean, OnStartTetheringCallback).
* @hide
*/
- public static final int TETHERING_WIFI_P2P = 3;
+ public static final int TETHERING_WIFI_P2P = TetheringManager.TETHERING_WIFI_P2P;
/**
* Extra used for communicating with the TetherService. Includes the type of tethering to
* enable if any.
* @hide
*/
- public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
+ public static final String EXTRA_ADD_TETHER_TYPE = TetheringManager.EXTRA_ADD_TETHER_TYPE;
/**
* Extra used for communicating with the TetherService. Includes the type of tethering for
* which to cancel provisioning.
* @hide
*/
- public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
+ public static final String EXTRA_REM_TETHER_TYPE = TetheringManager.EXTRA_REM_TETHER_TYPE;
/**
* Extra used for communicating with the TetherService. True to schedule a recheck of tether
* provisioning.
* @hide
*/
- public static final String EXTRA_SET_ALARM = "extraSetAlarm";
+ public static final String EXTRA_SET_ALARM = TetheringManager.EXTRA_SET_ALARM;
/**
* Tells the TetherService to run a provision check now.
* @hide
*/
- public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
+ public static final String EXTRA_RUN_PROVISION = TetheringManager.EXTRA_RUN_PROVISION;
/**
* Extra used for communicating with the TetherService. Contains the {@link ResultReceiver}
* which will receive provisioning results. Can be left empty.
* @hide
*/
- public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
+ public static final String EXTRA_PROVISION_CALLBACK = TetheringManager.EXTRA_PROVISION_CALLBACK;
/**
* The absence of a connection type.
@@ -3107,6 +3107,63 @@ public class ConnectivityManager {
}
}
+ /**
+ * Registers the specified {@link NetworkProvider}.
+ * Each listener must only be registered once. The listener can be unregistered with
+ * {@link #unregisterNetworkProvider}.
+ *
+ * @param provider the provider to register
+ * @return the ID of the provider. This ID must be used by the provider when registering
+ * {@link android.net.NetworkAgent}s.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public int registerNetworkProvider(@NonNull NetworkProvider provider) {
+ if (provider.getProviderId() != NetworkProvider.ID_NONE) {
+ // TODO: Provide a better method for checking this by moving NetworkFactory.SerialNumber
+ // out of NetworkFactory.
+ throw new IllegalStateException("NetworkProviders can only be registered once");
+ }
+
+ try {
+ int providerId = mService.registerNetworkProvider(provider.getMessenger(),
+ provider.getName());
+ provider.setProviderId(providerId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ return provider.getProviderId();
+ }
+
+ /**
+ * Unregisters the specified NetworkProvider.
+ *
+ * @param provider the provider to unregister
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public void unregisterNetworkProvider(@NonNull NetworkProvider provider) {
+ try {
+ mService.unregisterNetworkProvider(provider.getMessenger());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ provider.setProviderId(NetworkProvider.ID_NONE);
+ }
+
+
+ /** @hide exposed via the NetworkProvider class. */
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) {
+ try {
+ mService.declareNetworkRequestUnfulfillable(request);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
// TODO : remove this method. It is a stopgap measure to help sheperding a number
// of dependent changes that would conflict throughout the automerger graph. Having this
// temporarily helps with the process of going through with all these dependent changes across
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 09c02efbcfc4..e6a0379ff629 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -142,12 +142,16 @@ interface IConnectivityManager
void setAirplaneMode(boolean enable);
- int registerNetworkFactory(in Messenger messenger, in String name);
-
boolean requestBandwidthUpdate(in Network network);
+ int registerNetworkFactory(in Messenger messenger, in String name);
void unregisterNetworkFactory(in Messenger messenger);
+ int registerNetworkProvider(in Messenger messenger, in String name);
+ void unregisterNetworkProvider(in Messenger messenger);
+
+ void declareNetworkRequestUnfulfillable(in NetworkRequest request);
+
int registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
in NetworkCapabilities nc, int score, in NetworkMisc misc, in int factorySerialNumber);
diff --git a/core/java/android/net/NetworkProvider.java b/core/java/android/net/NetworkProvider.java
new file mode 100644
index 000000000000..2c0e4aa700b1
--- /dev/null
+++ b/core/java/android/net/NetworkProvider.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 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.net;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.util.Log;
+
+/**
+ * Base class for network providers such as telephony or Wi-Fi. NetworkProviders connect the device
+ * to networks and makes them available to to the core network stack by creating
+ * {@link NetworkAgent}s. The networks can then provide connectivity to apps and can be interacted
+ * with via networking APIs such as {@link ConnectivityManager}.
+ *
+ * Subclasses should implement {@link #onNetworkRequested} and {@link #onRequestWithdrawn} to
+ * receive {@link NetworkRequest}s sent by the system and by apps. A network that is not the
+ * best (highest-scoring) network for any request is generally not used by the system, and torn
+ * down.
+ *
+ * @hide
+ */
+@SystemApi
+public class NetworkProvider {
+ /**
+ * {@code providerId} value that indicates the absence of a provider. It is the providerId of
+ * any NetworkProvider that is not currently registered, and of any NetworkRequest that is not
+ * currently being satisfied by a network.
+ */
+ public static final int ID_NONE = -1;
+
+ /**
+ * A hardcoded ID for NetworkAgents representing VPNs. These agents are not created by any
+ * provider, so they use this constant for clarity instead of NONE.
+ * @hide only used by ConnectivityService.
+ */
+ public static final int ID_VPN = -2;
+
+ /**
+ * The first providerId value that will be allocated.
+ * @hide only used by ConnectivityService.
+ */
+ public static final int FIRST_PROVIDER_ID = 1;
+
+ /** @hide only used by ConnectivityService */
+ public static final int CMD_REQUEST_NETWORK = 1;
+ /** @hide only used by ConnectivityService */
+ public static final int CMD_CANCEL_REQUEST = 2;
+
+ private final Messenger mMessenger;
+ private final String mName;
+ private final ConnectivityManager mCm;
+
+ private int mProviderId = ID_NONE;
+
+ /**
+ * Constructs a new NetworkProvider.
+ *
+ * @param looper the Looper on which to run {@link #onNetworkRequested} and
+ * {@link #onRequestWithdrawn}.
+ * @param name the name of the listener, used only for debugging.
+ *
+ * @hide
+ */
+ @SystemApi
+ public NetworkProvider(@NonNull Context context, @NonNull Looper looper, @NonNull String name) {
+ mCm = ConnectivityManager.from(context);
+
+ Handler handler = new Handler(looper) {
+ @Override
+ public void handleMessage(Message m) {
+ switch (m.what) {
+ case CMD_REQUEST_NETWORK:
+ onNetworkRequested((NetworkRequest) m.obj, m.arg1, m.arg2);
+ break;
+ case CMD_CANCEL_REQUEST:
+ onRequestWithdrawn((NetworkRequest) m.obj);
+ break;
+ default:
+ Log.e(mName, "Unhandled message: " + m.what);
+ }
+ }
+ };
+ mMessenger = new Messenger(handler);
+ mName = name;
+ }
+
+ // TODO: consider adding a register() method so ConnectivityManager does not need to call this.
+ public @Nullable Messenger getMessenger() {
+ return mMessenger;
+ }
+
+ public @NonNull String getName() {
+ return mName;
+ }
+
+ /**
+ * Returns the ID of this provider. This is known only once the provider is registered via
+ * {@link ConnectivityManager#registerNetworkProvider()}, otherwise the ID is {@link #ID_NONE}.
+ * This ID must be used when registering any {@link NetworkAgent}s.
+ */
+ public int getProviderId() {
+ return mProviderId;
+ }
+
+ /** @hide */
+ public void setProviderId(int providerId) {
+ mProviderId = providerId;
+ }
+
+ /**
+ * Called when a NetworkRequest is received. The request may be a new request or an existing
+ * request with a different score.
+ *
+ * @param request the NetworkRequest being received
+ * @param score the score of the network currently satisfying the request, or 0 if none.
+ * @param providerId the ID of the provider that created the network currently satisfying this
+ * request, or {@link #ID_NONE} if none.
+ *
+ * @hide
+ */
+ @SystemApi
+ public void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId) {}
+
+ /**
+ * Called when a NetworkRequest is withdrawn.
+ * @hide
+ */
+ @SystemApi
+ public void onRequestWithdrawn(@NonNull NetworkRequest request) {}
+
+ /**
+ * Asserts that no provider will ever be able to satisfy the specified request. The provider
+ * must only call this method if it knows that it is the only provider on the system capable of
+ * satisfying this request, and that the request cannot be satisfied. The application filing the
+ * request will receive an {@link NetworkCallback#onUnavailable()} callback.
+ *
+ * @param request the request that cannot be fulfilled
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) {
+ mCm.declareNetworkRequestUnfulfillable(request);
+ }
+}
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 45bf4d2e1358..96d7a80886a5 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -19,6 +19,9 @@ package android.net;
import static android.os.Process.CLAT_UID;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -48,59 +51,104 @@ import java.util.function.Predicate;
* @hide
*/
// @NotThreadSafe
-public class NetworkStats implements Parcelable {
+@SystemApi
+public final class NetworkStats implements Parcelable {
private static final String TAG = "NetworkStats";
+
/** {@link #iface} value when interface details unavailable. */
- public static final String IFACE_ALL = null;
+ @SuppressLint("CompileTimeConstant")
+ @Nullable public static final String IFACE_ALL = null;
+ /**
+ * Virtual network interface for video telephony. This is for VT data usage counting
+ * purpose.
+ */
+ public static final String IFACE_VT = "vt_data0";
+
/** {@link #uid} value when UID details unavailable. */
public static final int UID_ALL = -1;
- /** {@link #tag} value matching any tag. */
+ /** Special UID value for data usage by tethering. */
+ public static final int UID_TETHERING = -5;
+
+ /**
+ * {@link #tag} value matching any tag.
+ * @hide
+ */
// TODO: Rename TAG_ALL to TAG_ANY.
public static final int TAG_ALL = -1;
- /** {@link #set} value for all sets combined, not including debug sets. */
+ /**
+ * {@link #set} value for all sets combined, not including debug sets.
+ * @hide
+ */
public static final int SET_ALL = -1;
/** {@link #set} value where background data is accounted. */
public static final int SET_DEFAULT = 0;
/** {@link #set} value where foreground data is accounted. */
public static final int SET_FOREGROUND = 1;
- /** All {@link #set} value greater than SET_DEBUG_START are debug {@link #set} values. */
+ /**
+ * All {@link #set} value greater than SET_DEBUG_START are debug {@link #set} values.
+ * @hide
+ */
public static final int SET_DEBUG_START = 1000;
- /** Debug {@link #set} value when the VPN stats are moved in. */
+ /**
+ * Debug {@link #set} value when the VPN stats are moved in.
+ * @hide
+ */
public static final int SET_DBG_VPN_IN = 1001;
- /** Debug {@link #set} value when the VPN stats are moved out of a vpn UID. */
+ /**
+ * Debug {@link #set} value when the VPN stats are moved out of a vpn UID.
+ * @hide
+ */
public static final int SET_DBG_VPN_OUT = 1002;
- /** Include all interfaces when filtering */
- public static final String[] INTERFACES_ALL = null;
+ /**
+ * Include all interfaces when filtering
+ * @hide
+ */
+ public @Nullable static final String[] INTERFACES_ALL = null;
/** {@link #tag} value for total data across all tags. */
// TODO: Rename TAG_NONE to TAG_ALL.
public static final int TAG_NONE = 0;
- /** {@link #metered} value to account for all metered states. */
+ /**
+ * {@link #metered} value to account for all metered states.
+ * @hide
+ */
public static final int METERED_ALL = -1;
/** {@link #metered} value where native, unmetered data is accounted. */
public static final int METERED_NO = 0;
/** {@link #metered} value where metered data is accounted. */
public static final int METERED_YES = 1;
- /** {@link #roaming} value to account for all roaming states. */
+ /**
+ * {@link #roaming} value to account for all roaming states.
+ * @hide
+ */
public static final int ROAMING_ALL = -1;
/** {@link #roaming} value where native, non-roaming data is accounted. */
public static final int ROAMING_NO = 0;
/** {@link #roaming} value where roaming data is accounted. */
public static final int ROAMING_YES = 1;
- /** {@link #onDefaultNetwork} value to account for all default network states. */
+ /**
+ * {@link #onDefaultNetwork} value to account for all default network states.
+ * @hide
+ */
public static final int DEFAULT_NETWORK_ALL = -1;
/** {@link #onDefaultNetwork} value to account for usage while not the default network. */
public static final int DEFAULT_NETWORK_NO = 0;
/** {@link #onDefaultNetwork} value to account for usage while the default network. */
public static final int DEFAULT_NETWORK_YES = 1;
- /** Denotes a request for stats at the interface level. */
+ /**
+ * Denotes a request for stats at the interface level.
+ * @hide
+ */
public static final int STATS_PER_IFACE = 0;
- /** Denotes a request for stats at the interface and UID level. */
+ /**
+ * Denotes a request for stats at the interface and UID level.
+ * @hide
+ */
public static final int STATS_PER_UID = 1;
private static final String CLATD_INTERFACE_PREFIX = "v4-";
@@ -144,60 +192,78 @@ public class NetworkStats implements Parcelable {
@UnsupportedAppUsage
private long[] operations;
+ /** @hide */
+ @SystemApi
public static class Entry {
+ /** @hide */
@UnsupportedAppUsage
public String iface;
+ /** @hide */
@UnsupportedAppUsage
public int uid;
+ /** @hide */
@UnsupportedAppUsage
public int set;
+ /** @hide */
@UnsupportedAppUsage
public int tag;
/**
* Note that this is only populated w/ the default value when read from /proc or written
* to disk. We merge in the correct value when reporting this value to clients of
* getSummary().
+ * @hide
*/
public int metered;
/**
* Note that this is only populated w/ the default value when read from /proc or written
* to disk. We merge in the correct value when reporting this value to clients of
* getSummary().
+ * @hide
*/
public int roaming;
/**
* Note that this is only populated w/ the default value when read from /proc or written
* to disk. We merge in the correct value when reporting this value to clients of
* getSummary().
+ * @hide
*/
public int defaultNetwork;
+ /** @hide */
@UnsupportedAppUsage
public long rxBytes;
+ /** @hide */
@UnsupportedAppUsage
public long rxPackets;
+ /** @hide */
@UnsupportedAppUsage
public long txBytes;
+ /** @hide */
@UnsupportedAppUsage
public long txPackets;
+ /** @hide */
+ @UnsupportedAppUsage
public long operations;
+ /** @hide */
@UnsupportedAppUsage
public Entry() {
this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
}
+ /** @hide */
public Entry(long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets,
operations);
}
+ /** @hide */
public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets,
long txBytes, long txPackets, long operations) {
this(iface, uid, set, tag, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO,
rxBytes, rxPackets, txBytes, txPackets, operations);
}
- public Entry(String iface, int uid, int set, int tag, int metered, int roaming,
+ public Entry(@Nullable String iface, int uid, int set, int tag, int metered, int roaming,
int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets,
long operations) {
this.iface = iface;
@@ -214,15 +280,18 @@ public class NetworkStats implements Parcelable {
this.operations = operations;
}
+ /** @hide */
public boolean isNegative() {
return rxBytes < 0 || rxPackets < 0 || txBytes < 0 || txPackets < 0 || operations < 0;
}
+ /** @hide */
public boolean isEmpty() {
return rxBytes == 0 && rxPackets == 0 && txBytes == 0 && txPackets == 0
&& operations == 0;
}
+ /** @hide */
public void add(Entry another) {
this.rxBytes += another.rxBytes;
this.rxPackets += another.rxPackets;
@@ -249,6 +318,7 @@ public class NetworkStats implements Parcelable {
return builder.toString();
}
+ /** @hide */
@Override
public boolean equals(Object o) {
if (o instanceof Entry) {
@@ -262,13 +332,13 @@ public class NetworkStats implements Parcelable {
return false;
}
+ /** @hide */
@Override
public int hashCode() {
return Objects.hash(uid, set, tag, metered, roaming, defaultNetwork, iface);
}
}
- @UnsupportedAppUsage
public NetworkStats(long elapsedRealtime, int initialSize) {
this.elapsedRealtime = elapsedRealtime;
this.size = 0;
@@ -292,6 +362,7 @@ public class NetworkStats implements Parcelable {
}
}
+ /** @hide */
@UnsupportedAppUsage
public NetworkStats(Parcel parcel) {
elapsedRealtime = parcel.readLong();
@@ -312,7 +383,7 @@ public class NetworkStats implements Parcelable {
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeLong(elapsedRealtime);
dest.writeInt(size);
dest.writeInt(capacity);
@@ -330,19 +401,23 @@ public class NetworkStats implements Parcelable {
dest.writeLongArray(operations);
}
+ /**
+ * @hide
+ */
@Override
public NetworkStats clone() {
final NetworkStats clone = new NetworkStats(elapsedRealtime, size);
NetworkStats.Entry entry = null;
for (int i = 0; i < size; i++) {
entry = getValues(i, entry);
- clone.addValues(entry);
+ clone.addEntry(entry);
}
return clone;
}
/**
* Clear all data stored in this object.
+ * @hide
*/
public void clear() {
this.capacity = 0;
@@ -360,25 +435,28 @@ public class NetworkStats implements Parcelable {
this.operations = EmptyArray.LONG;
}
+ /** @hide */
@VisibleForTesting
public NetworkStats addIfaceValues(
String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
- return addValues(
+ return addEntry(
iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L);
}
+ /** @hide */
@VisibleForTesting
- public NetworkStats addValues(String iface, int uid, int set, int tag, long rxBytes,
+ public NetworkStats addEntry(String iface, int uid, int set, int tag, long rxBytes,
long rxPackets, long txBytes, long txPackets, long operations) {
- return addValues(new Entry(
+ return addEntry(new Entry(
iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
}
+ /** @hide */
@VisibleForTesting
- public NetworkStats addValues(String iface, int uid, int set, int tag, int metered, int roaming,
+ public NetworkStats addEntry(String iface, int uid, int set, int tag, int metered, int roaming,
int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets,
long operations) {
- return addValues(new Entry(
+ return addEntry(new Entry(
iface, uid, set, tag, metered, roaming, defaultNetwork, rxBytes, rxPackets,
txBytes, txPackets, operations));
}
@@ -386,8 +464,9 @@ public class NetworkStats implements Parcelable {
/**
* Add new stats entry, copying from given {@link Entry}. The {@link Entry}
* object can be recycled across multiple calls.
+ * @hide
*/
- public NetworkStats addValues(Entry entry) {
+ public NetworkStats addEntry(Entry entry) {
if (size >= capacity) {
final int newLength = Math.max(size, 10) * 3 / 2;
iface = Arrays.copyOf(iface, newLength);
@@ -428,6 +507,7 @@ public class NetworkStats implements Parcelable {
/**
* Return specific stats entry.
+ * @hide
*/
@UnsupportedAppUsage
public Entry getValues(int i, Entry recycle) {
@@ -467,10 +547,12 @@ public class NetworkStats implements Parcelable {
operations[dest] = operations[src];
}
+ /** @hide */
public long getElapsedRealtime() {
return elapsedRealtime;
}
+ /** @hide */
public void setElapsedRealtime(long time) {
elapsedRealtime = time;
}
@@ -478,21 +560,25 @@ public class NetworkStats implements Parcelable {
/**
* Return age of this {@link NetworkStats} object with respect to
* {@link SystemClock#elapsedRealtime()}.
+ * @hide
*/
public long getElapsedRealtimeAge() {
return SystemClock.elapsedRealtime() - elapsedRealtime;
}
+ /** @hide */
@UnsupportedAppUsage
public int size() {
return size;
}
+ /** @hide */
@VisibleForTesting
public int internalSize() {
return capacity;
}
+ /** @hide */
@Deprecated
public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
long txBytes, long txPackets, long operations) {
@@ -501,6 +587,7 @@ public class NetworkStats implements Parcelable {
txPackets, operations);
}
+ /** @hide */
public NetworkStats combineValues(String iface, int uid, int set, int tag,
long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
return combineValues(new Entry(
@@ -509,16 +596,20 @@ public class NetworkStats implements Parcelable {
/**
* Combine given values with an existing row, or create a new row if
- * {@link #findIndex(String, int, int, int, int)} is unable to find match. Can
- * also be used to subtract values from existing rows.
+ * {@link #findIndex(String, int, int, int, int, int, int)} is unable to find match. Can
+ * also be used to subtract values from existing rows. This method mutates the referencing
+ * {@link NetworkStats} object.
+ *
+ * @param entry the {@link Entry} to combine.
+ * @return a reference to this mutated {@link NetworkStats} object.
+ * @hide
*/
- @UnsupportedAppUsage
- public NetworkStats combineValues(Entry entry) {
+ public @NonNull NetworkStats combineValues(@NonNull Entry entry) {
final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.metered,
entry.roaming, entry.defaultNetwork);
if (i == -1) {
// only create new entry when positive contribution
- addValues(entry);
+ addEntry(entry);
} else {
rxBytes[i] += entry.rxBytes;
rxPackets[i] += entry.rxPackets;
@@ -530,10 +621,33 @@ public class NetworkStats implements Parcelable {
}
/**
+ * Add given values with an existing row, or create a new row if
+ * {@link #findIndex(String, int, int, int, int, int, int)} is unable to find match. Can
+ * also be used to subtract values from existing rows.
+ *
+ * @param entry the {@link Entry} to add.
+ * @return a new constructed {@link NetworkStats} object that contains the result.
+ */
+ public @NonNull NetworkStats addValues(@NonNull Entry entry) {
+ return this.clone().combineValues(entry);
+ }
+
+ /**
+ * Add the given {@link NetworkStats} objects.
+ *
+ * @return the sum of two objects.
+ */
+ public @NonNull NetworkStats add(@NonNull NetworkStats another) {
+ final NetworkStats ret = this.clone();
+ ret.combineAllValues(another);
+ return ret;
+ }
+
+ /**
* Combine all values from another {@link NetworkStats} into this object.
+ * @hide
*/
- @UnsupportedAppUsage
- public void combineAllValues(NetworkStats another) {
+ public void combineAllValues(@NonNull NetworkStats another) {
NetworkStats.Entry entry = null;
for (int i = 0; i < another.size; i++) {
entry = another.getValues(i, entry);
@@ -543,6 +657,7 @@ public class NetworkStats implements Parcelable {
/**
* Find first stats index that matches the requested parameters.
+ * @hide
*/
public int findIndex(String iface, int uid, int set, int tag, int metered, int roaming,
int defaultNetwork) {
@@ -560,6 +675,7 @@ public class NetworkStats implements Parcelable {
/**
* Find first stats index that matches the requested parameters, starting
* search around the hinted index as an optimization.
+ * @hide
*/
@VisibleForTesting
public int findIndexHinted(String iface, int uid, int set, int tag, int metered, int roaming,
@@ -589,6 +705,7 @@ public class NetworkStats implements Parcelable {
* Splice in {@link #operations} from the given {@link NetworkStats} based
* on matching {@link #uid} and {@link #tag} rows. Ignores {@link #iface},
* since operation counts are at data layer.
+ * @hide
*/
public void spliceOperationsFrom(NetworkStats stats) {
for (int i = 0; i < size; i++) {
@@ -604,6 +721,7 @@ public class NetworkStats implements Parcelable {
/**
* Return list of unique interfaces known by this data structure.
+ * @hide
*/
public String[] getUniqueIfaces() {
final HashSet<String> ifaces = new HashSet<String>();
@@ -617,6 +735,7 @@ public class NetworkStats implements Parcelable {
/**
* Return list of unique UIDs known by this data structure.
+ * @hide
*/
@UnsupportedAppUsage
public int[] getUniqueUids() {
@@ -636,6 +755,7 @@ public class NetworkStats implements Parcelable {
/**
* Return total bytes represented by this snapshot object, usually used when
* checking if a {@link #subtract(NetworkStats)} delta passes a threshold.
+ * @hide
*/
@UnsupportedAppUsage
public long getTotalBytes() {
@@ -645,6 +765,7 @@ public class NetworkStats implements Parcelable {
/**
* Return total of all fields represented by this snapshot object.
+ * @hide
*/
@UnsupportedAppUsage
public Entry getTotal(Entry recycle) {
@@ -654,6 +775,7 @@ public class NetworkStats implements Parcelable {
/**
* Return total of all fields represented by this snapshot object matching
* the requested {@link #uid}.
+ * @hide
*/
@UnsupportedAppUsage
public Entry getTotal(Entry recycle, int limitUid) {
@@ -663,11 +785,13 @@ public class NetworkStats implements Parcelable {
/**
* Return total of all fields represented by this snapshot object matching
* the requested {@link #iface}.
+ * @hide
*/
public Entry getTotal(Entry recycle, HashSet<String> limitIface) {
return getTotal(recycle, limitIface, UID_ALL, false);
}
+ /** @hide */
@UnsupportedAppUsage
public Entry getTotalIncludingTags(Entry recycle) {
return getTotal(recycle, null, UID_ALL, true);
@@ -717,6 +841,7 @@ public class NetworkStats implements Parcelable {
/**
* Fast path for battery stats.
+ * @hide
*/
public long getTotalPackets() {
long total = 0;
@@ -729,9 +854,12 @@ public class NetworkStats implements Parcelable {
/**
* Subtract the given {@link NetworkStats}, effectively leaving the delta
* between two snapshots in time. Assumes that statistics rows collect over
- * time, and that none of them have disappeared.
+ * time, and that none of them have disappeared. This method does not mutate
+ * the referencing object.
+ *
+ * @return the delta between two objects.
*/
- public NetworkStats subtract(NetworkStats right) {
+ public @NonNull NetworkStats subtract(@NonNull NetworkStats right) {
return subtract(this, right, null, null);
}
@@ -742,6 +870,7 @@ public class NetworkStats implements Parcelable {
* <p>
* If counters have rolled backwards, they are clamped to {@code 0} and
* reported to the given {@link NonMonotonicObserver}.
+ * @hide
*/
public static <C> NetworkStats subtract(NetworkStats left, NetworkStats right,
NonMonotonicObserver<C> observer, C cookie) {
@@ -759,6 +888,7 @@ public class NetworkStats implements Parcelable {
* If <var>recycle</var> is supplied, this NetworkStats object will be
* reused (and returned) as the result if it is large enough to contain
* the data.
+ * @hide
*/
public static <C> NetworkStats subtract(NetworkStats left, NetworkStats right,
NonMonotonicObserver<C> observer, C cookie, NetworkStats recycle) {
@@ -817,7 +947,7 @@ public class NetworkStats implements Parcelable {
entry.operations = Math.max(entry.operations, 0);
}
- result.addValues(entry);
+ result.addEntry(entry);
}
return result;
@@ -847,6 +977,7 @@ public class NetworkStats implements Parcelable {
* @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated.
* @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both.
* @param useBpfStats True if eBPF is in use.
+ * @hide
*/
public static void apply464xlatAdjustments(NetworkStats baseTraffic,
NetworkStats stackedTraffic, Map<String, String> stackedIfaces, boolean useBpfStats) {
@@ -899,6 +1030,7 @@ public class NetworkStats implements Parcelable {
* {@link #apply464xlatAdjustments(NetworkStats, NetworkStats, Map)} with {@code this} as
* base and stacked traffic.
* @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both.
+ * @hide
*/
public void apply464xlatAdjustments(Map<String, String> stackedIfaces, boolean useBpfStats) {
apply464xlatAdjustments(this, this, stackedIfaces, useBpfStats);
@@ -907,6 +1039,7 @@ public class NetworkStats implements Parcelable {
/**
* Return total statistics grouped by {@link #iface}; doesn't mutate the
* original structure.
+ * @hide
*/
public NetworkStats groupedByIface() {
final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
@@ -938,6 +1071,7 @@ public class NetworkStats implements Parcelable {
/**
* Return total statistics grouped by {@link #uid}; doesn't mutate the
* original structure.
+ * @hide
*/
public NetworkStats groupedByUid() {
final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
@@ -968,6 +1102,7 @@ public class NetworkStats implements Parcelable {
/**
* Remove all rows that match one of specified UIDs.
+ * @hide
*/
public void removeUids(int[] uids) {
int nextOutputEntry = 0;
@@ -989,6 +1124,7 @@ public class NetworkStats implements Parcelable {
* @param limitUid UID to filter for, or {@link #UID_ALL}.
* @param limitIfaces Interfaces to filter for, or {@link #INTERFACES_ALL}.
* @param limitTag Tag to filter for, or {@link #TAG_ALL}.
+ * @hide
*/
public void filter(int limitUid, String[] limitIfaces, int limitTag) {
if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) {
@@ -1004,6 +1140,7 @@ public class NetworkStats implements Parcelable {
* Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}.
*
* <p>This mutates the original structure in place.
+ * @hide
*/
public void filterDebugEntries() {
filter(e -> e.set < SET_DEBUG_START);
@@ -1024,6 +1161,7 @@ public class NetworkStats implements Parcelable {
size = nextOutputEntry;
}
+ /** @hide */
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix);
pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);
@@ -1047,6 +1185,7 @@ public class NetworkStats implements Parcelable {
/**
* Return text description of {@link #set} value.
+ * @hide
*/
public static String setToString(int set) {
switch (set) {
@@ -1067,6 +1206,7 @@ public class NetworkStats implements Parcelable {
/**
* Return text description of {@link #set} value.
+ * @hide
*/
public static String setToCheckinString(int set) {
switch (set) {
@@ -1087,6 +1227,7 @@ public class NetworkStats implements Parcelable {
/**
* @return true if the querySet matches the dataSet.
+ * @hide
*/
public static boolean setMatches(int querySet, int dataSet) {
if (querySet == dataSet) {
@@ -1098,6 +1239,7 @@ public class NetworkStats implements Parcelable {
/**
* Return text description of {@link #tag} value.
+ * @hide
*/
public static String tagToString(int tag) {
return "0x" + Integer.toHexString(tag);
@@ -1105,6 +1247,7 @@ public class NetworkStats implements Parcelable {
/**
* Return text description of {@link #metered} value.
+ * @hide
*/
public static String meteredToString(int metered) {
switch (metered) {
@@ -1121,6 +1264,7 @@ public class NetworkStats implements Parcelable {
/**
* Return text description of {@link #roaming} value.
+ * @hide
*/
public static String roamingToString(int roaming) {
switch (roaming) {
@@ -1137,6 +1281,7 @@ public class NetworkStats implements Parcelable {
/**
* Return text description of {@link #defaultNetwork} value.
+ * @hide
*/
public static String defaultNetworkToString(int defaultNetwork) {
switch (defaultNetwork) {
@@ -1151,6 +1296,7 @@ public class NetworkStats implements Parcelable {
}
}
+ /** @hide */
@Override
public String toString() {
final CharArrayWriter writer = new CharArrayWriter();
@@ -1163,8 +1309,7 @@ public class NetworkStats implements Parcelable {
return 0;
}
- @UnsupportedAppUsage
- public static final @android.annotation.NonNull Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
+ public static final @NonNull Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
@Override
public NetworkStats createFromParcel(Parcel in) {
return new NetworkStats(in);
@@ -1176,6 +1321,7 @@ public class NetworkStats implements Parcelable {
}
};
+ /** @hide */
public interface NonMonotonicObserver<C> {
public void foundNonMonotonic(
NetworkStats left, int leftIndex, NetworkStats right, int rightIndex, C cookie);
@@ -1195,6 +1341,7 @@ public class NetworkStats implements Parcelable {
* @param tunUid uid of the VPN application
* @param tunIface iface of the vpn tunnel
* @param underlyingIfaces underlying network ifaces used by the VPN application
+ * @hide
*/
public void migrateTun(int tunUid, @NonNull String tunIface,
@NonNull String[] underlyingIfaces) {
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 162d6e27bd42..8108cf08d5c3 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -89,7 +89,7 @@ public class TrafficStats {
*
* @hide
*/
- public static final int UID_TETHERING = -5;
+ public static final int UID_TETHERING = NetworkStats.UID_TETHERING;
/**
* Tag values in this range are reserved for the network stack. The network stack is
diff --git a/core/java/android/net/netstats/provider/AbstractNetworkStatsProvider.java b/core/java/android/net/netstats/provider/AbstractNetworkStatsProvider.java
new file mode 100644
index 000000000000..740aa92ad484
--- /dev/null
+++ b/core/java/android/net/netstats/provider/AbstractNetworkStatsProvider.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 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.net.netstats.provider;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.net.NetworkStats;
+
+/**
+ * A base class that allows external modules to implement a custom network statistics provider.
+ * @hide
+ */
+@SystemApi
+public abstract class AbstractNetworkStatsProvider {
+ /**
+ * A value used by {@link #setLimit} and {@link #setAlert} indicates there is no limit.
+ */
+ public static final int QUOTA_UNLIMITED = -1;
+
+ /**
+ * Called by {@code NetworkStatsService} when global polling is needed. Custom
+ * implementation of providers MUST respond to it by calling
+ * {@link NetworkStatsProviderCallback#onStatsUpdated} within one minute. Responding
+ * later than this may cause the stats to be dropped.
+ *
+ * @param token a positive number identifying the new state of the system under which
+ * {@link NetworkStats} have to be gathered from now on. When this is called,
+ * custom implementations of providers MUST report the latest stats with the
+ * previous token, under which stats were being gathered so far.
+ */
+ public abstract void requestStatsUpdate(int token);
+
+ /**
+ * Called by {@code NetworkStatsService} when setting the interface quota for the specified
+ * upstream interface. When this is called, the custom implementation should block all egress
+ * packets on the {@code iface} associated with the provider when {@code quotaBytes} bytes have
+ * been reached, and MUST respond to it by calling
+ * {@link NetworkStatsProviderCallback#onLimitReached()}.
+ *
+ * @param iface the interface requiring the operation.
+ * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
+ * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit.
+ */
+ public abstract void setLimit(@NonNull String iface, long quotaBytes);
+
+ /**
+ * Called by {@code NetworkStatsService} when setting the alert bytes. Custom implementations
+ * MUST call {@link NetworkStatsProviderCallback#onAlertReached()} when {@code quotaBytes} bytes
+ * have been reached. Unlike {@link #setLimit(String, long)}, the custom implementation should
+ * not block all egress packets.
+ *
+ * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
+ * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no alert.
+ */
+ public abstract void setAlert(long quotaBytes);
+}
diff --git a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl
new file mode 100644
index 000000000000..55b3d4edb157
--- /dev/null
+++ b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 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.net.netstats.provider;
+
+/**
+ * Interface for NetworkStatsService to query network statistics and set data limits.
+ *
+ * @hide
+ */
+oneway interface INetworkStatsProvider {
+ void requestStatsUpdate(int token);
+ void setLimit(String iface, long quotaBytes);
+ void setAlert(long quotaBytes);
+}
diff --git a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
new file mode 100644
index 000000000000..3ea9318f10d4
--- /dev/null
+++ b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 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.net.netstats.provider;
+
+import android.net.NetworkStats;
+
+/**
+ * Interface for implementor of {@link INetworkStatsProviderCallback} to push events
+ * such as network statistics update or notify limit reached.
+ * @hide
+ */
+oneway interface INetworkStatsProviderCallback {
+ void onStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats);
+ void onAlertReached();
+ void onLimitReached();
+ void unregister();
+}
diff --git a/core/java/android/net/netstats/provider/NetworkStatsProviderCallback.java b/core/java/android/net/netstats/provider/NetworkStatsProviderCallback.java
new file mode 100644
index 000000000000..e17a8eee7ff0
--- /dev/null
+++ b/core/java/android/net/netstats/provider/NetworkStatsProviderCallback.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 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.net.netstats.provider;
+
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.net.NetworkStats;
+import android.os.RemoteException;
+
+/**
+ * A callback class that allows callers to report events to the system.
+ * @hide
+ */
+@SystemApi
+@SuppressLint("CallbackMethodName")
+public class NetworkStatsProviderCallback {
+ @NonNull private final INetworkStatsProviderCallback mBinder;
+
+ /** @hide */
+ public NetworkStatsProviderCallback(@NonNull INetworkStatsProviderCallback binder) {
+ mBinder = binder;
+ }
+
+ /**
+ * Notify the system of new network statistics.
+ *
+ * Send the network statistics recorded since the last call to {@link #onStatsUpdated}. Must be
+ * called within one minute of {@link AbstractNetworkStatsProvider#requestStatsUpdate(int)}
+ * being called. The provider can also call this whenever it wants to reports new stats for any
+ * reason. Note that the system will not necessarily immediately propagate the statistics to
+ * reflect the update.
+ *
+ * @param token the token under which these stats were gathered. Providers can call this method
+ * with the current token as often as they want, until the token changes.
+ * {@see AbstractNetworkStatsProvider#requestStatsUpdate()}
+ * @param ifaceStats the {@link NetworkStats} per interface to be reported.
+ * The provider should not include any traffic that is already counted by
+ * kernel interface counters.
+ * @param uidStats the same stats as above, but counts {@link NetworkStats}
+ * per uid.
+ */
+ public void onStatsUpdated(int token, @NonNull NetworkStats ifaceStats,
+ @NonNull NetworkStats uidStats) {
+ try {
+ mBinder.onStatsUpdated(token, ifaceStats, uidStats);
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Notify system that the quota set by {@code setAlert} has been reached.
+ */
+ public void onAlertReached() {
+ try {
+ mBinder.onAlertReached();
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Notify system that the quota set by {@code setLimit} has been reached.
+ */
+ public void onLimitReached() {
+ try {
+ mBinder.onLimitReached();
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Unregister the provider and the referencing callback.
+ */
+ public void unregister() {
+ try {
+ mBinder.unregister();
+ } catch (RemoteException e) {
+ // Ignore error.
+ }
+ }
+}
diff --git a/core/java/android/net/netstats/provider/NetworkStatsProviderWrapper.java b/core/java/android/net/netstats/provider/NetworkStatsProviderWrapper.java
new file mode 100644
index 000000000000..4bf7c9bc086e
--- /dev/null
+++ b/core/java/android/net/netstats/provider/NetworkStatsProviderWrapper.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 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.net.netstats.provider;
+
+import android.annotation.NonNull;
+
+/**
+ * A wrapper class of {@link INetworkStatsProvider} that hides the binder interface from exposing
+ * to outer world.
+ *
+ * @hide
+ */
+public class NetworkStatsProviderWrapper extends INetworkStatsProvider.Stub {
+ @NonNull final AbstractNetworkStatsProvider mProvider;
+
+ public NetworkStatsProviderWrapper(AbstractNetworkStatsProvider provider) {
+ mProvider = provider;
+ }
+
+ @Override
+ public void requestStatsUpdate(int token) {
+ mProvider.requestStatsUpdate(token);
+ }
+
+ @Override
+ public void setLimit(@NonNull String iface, long quotaBytes) {
+ mProvider.setLimit(iface, quotaBytes);
+ }
+
+ @Override
+ public void setAlert(long quotaBytes) {
+ mProvider.setAlert(quotaBytes);
+ }
+}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index c9ebed3bd0a2..1a4dac78855f 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1886,29 +1886,7 @@ public final class Parcel {
public final void writeException(@NonNull Exception e) {
AppOpsManager.prefixParcelWithAppOpsIfNeeded(this);
- int code = 0;
- if (e instanceof Parcelable
- && (e.getClass().getClassLoader() == Parcelable.class.getClassLoader())) {
- // We only send Parcelable exceptions that are in the
- // BootClassLoader to ensure that the receiver can unpack them
- code = EX_PARCELABLE;
- } else if (e instanceof SecurityException) {
- code = EX_SECURITY;
- } else if (e instanceof BadParcelableException) {
- code = EX_BAD_PARCELABLE;
- } else if (e instanceof IllegalArgumentException) {
- code = EX_ILLEGAL_ARGUMENT;
- } else if (e instanceof NullPointerException) {
- code = EX_NULL_POINTER;
- } else if (e instanceof IllegalStateException) {
- code = EX_ILLEGAL_STATE;
- } else if (e instanceof NetworkOnMainThreadException) {
- code = EX_NETWORK_MAIN_THREAD;
- } else if (e instanceof UnsupportedOperationException) {
- code = EX_UNSUPPORTED_OPERATION;
- } else if (e instanceof ServiceSpecificException) {
- code = EX_SERVICE_SPECIFIC;
- }
+ int code = getExceptionCode(e);
writeInt(code);
StrictMode.clearGatheredViolations();
if (code == 0) {
@@ -1922,20 +1900,7 @@ public final class Parcel {
if (sParcelExceptionStackTrace && (timeNow - sLastWriteExceptionStackTrace
> WRITE_EXCEPTION_STACK_TRACE_THRESHOLD_MS)) {
sLastWriteExceptionStackTrace = timeNow;
- final int sizePosition = dataPosition();
- writeInt(0); // Header size will be filled in later
- StackTraceElement[] stackTrace = e.getStackTrace();
- final int truncatedSize = Math.min(stackTrace.length, 5);
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < truncatedSize; i++) {
- sb.append("\tat ").append(stackTrace[i]).append('\n');
- }
- writeString(sb.toString());
- final int payloadPosition = dataPosition();
- setDataPosition(sizePosition);
- // Write stack trace header size. Used in native side to skip the header
- writeInt(payloadPosition - sizePosition);
- setDataPosition(payloadPosition);
+ writeStackTrace(e);
} else {
writeInt(0);
}
@@ -1956,6 +1921,52 @@ public final class Parcel {
}
}
+ /** @hide */
+ public static int getExceptionCode(@NonNull Throwable e) {
+ int code = 0;
+ if (e instanceof Parcelable
+ && (e.getClass().getClassLoader() == Parcelable.class.getClassLoader())) {
+ // We only send Parcelable exceptions that are in the
+ // BootClassLoader to ensure that the receiver can unpack them
+ code = EX_PARCELABLE;
+ } else if (e instanceof SecurityException) {
+ code = EX_SECURITY;
+ } else if (e instanceof BadParcelableException) {
+ code = EX_BAD_PARCELABLE;
+ } else if (e instanceof IllegalArgumentException) {
+ code = EX_ILLEGAL_ARGUMENT;
+ } else if (e instanceof NullPointerException) {
+ code = EX_NULL_POINTER;
+ } else if (e instanceof IllegalStateException) {
+ code = EX_ILLEGAL_STATE;
+ } else if (e instanceof NetworkOnMainThreadException) {
+ code = EX_NETWORK_MAIN_THREAD;
+ } else if (e instanceof UnsupportedOperationException) {
+ code = EX_UNSUPPORTED_OPERATION;
+ } else if (e instanceof ServiceSpecificException) {
+ code = EX_SERVICE_SPECIFIC;
+ }
+ return code;
+ }
+
+ /** @hide */
+ public void writeStackTrace(@NonNull Throwable e) {
+ final int sizePosition = dataPosition();
+ writeInt(0); // Header size will be filled in later
+ StackTraceElement[] stackTrace = e.getStackTrace();
+ final int truncatedSize = Math.min(stackTrace.length, 5);
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < truncatedSize; i++) {
+ sb.append("\tat ").append(stackTrace[i]).append('\n');
+ }
+ writeString(sb.toString());
+ final int payloadPosition = dataPosition();
+ setDataPosition(sizePosition);
+ // Write stack trace header size. Used in native side to skip the header
+ writeInt(payloadPosition - sizePosition);
+ setDataPosition(payloadPosition);
+ }
+
/**
* Special function for writing information at the front of the Parcel
* indicating that no exception occurred.
@@ -2069,14 +2080,7 @@ public final class Parcel {
if (remoteStackTrace != null) {
RemoteException cause = new RemoteException(
"Remote stack trace:\n" + remoteStackTrace, null, false, false);
- try {
- Throwable rootCause = ExceptionUtils.getRootCause(e);
- if (rootCause != null) {
- rootCause.initCause(cause);
- }
- } catch (RuntimeException ex) {
- Log.e(TAG, "Cannot set cause " + cause + " for " + e, ex);
- }
+ ExceptionUtils.appendCause(e, cause);
}
SneakyThrow.sneakyThrow(e);
}
@@ -2088,6 +2092,14 @@ public final class Parcel {
* @param msg The exception message.
*/
private Exception createException(int code, String msg) {
+ Exception exception = createExceptionOrNull(code, msg);
+ return exception != null
+ ? exception
+ : new RuntimeException("Unknown exception code: " + code + " msg " + msg);
+ }
+
+ /** @hide */
+ public Exception createExceptionOrNull(int code, String msg) {
switch (code) {
case EX_PARCELABLE:
if (readInt() > 0) {
@@ -2111,9 +2123,9 @@ public final class Parcel {
return new UnsupportedOperationException(msg);
case EX_SERVICE_SPECIFIC:
return new ServiceSpecificException(readInt(), msg);
+ default:
+ return null;
}
- return new RuntimeException("Unknown exception code: " + code
- + " msg " + msg);
}
/**
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 983053bbe7fd..89ddf8cbd96a 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -31,6 +31,9 @@ import static android.system.OsConstants.S_ISLNK;
import static android.system.OsConstants.S_ISREG;
import static android.system.OsConstants.S_IWOTH;
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
@@ -253,6 +256,9 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
* be opened with the requested mode.
* @see #parseMode(String)
*/
+ // We can't accept a generic Executor here, since we need to use
+ // MessageQueue.addOnFileDescriptorEventListener()
+ @SuppressLint("ExecutorRegistration")
public static ParcelFileDescriptor open(File file, int mode, Handler handler,
final OnCloseListener listener) throws IOException {
if (handler == null) {
@@ -268,9 +274,22 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
return fromFd(fd, handler, listener);
}
- /** {@hide} */
- public static ParcelFileDescriptor fromPfd(ParcelFileDescriptor pfd, Handler handler,
- final OnCloseListener listener) throws IOException {
+ /**
+ * Create a new ParcelFileDescriptor wrapping an already-opened file.
+ *
+ * @param pfd The already-opened file.
+ * @param handler to call listener from.
+ * @param listener to be invoked when the returned descriptor has been
+ * closed.
+ * @return a new ParcelFileDescriptor pointing to the given file.
+ * @hide
+ */
+ @SystemApi
+ // We can't accept a generic Executor here, since we need to use
+ // MessageQueue.addOnFileDescriptorEventListener()
+ @SuppressLint("ExecutorRegistration")
+ public static @NonNull ParcelFileDescriptor wrap(@NonNull ParcelFileDescriptor pfd,
+ @NonNull Handler handler, @NonNull OnCloseListener listener) throws IOException {
final FileDescriptor original = new FileDescriptor();
original.setInt$(pfd.detachFd());
return fromFd(original, handler, listener);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 94623bc71346..3ef86ed9f994 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -89,6 +89,12 @@ public class Process {
public static final int DRM_UID = 1019;
/**
+ * Defines the GID for the group that allows write access to the internal media storage.
+ * @hide
+ */
+ public static final int SDCARD_RW_GID = 1015;
+
+ /**
* Defines the UID/GID for the group that controls VPN services.
* @hide
*/
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 62b8953b158a..3846f894c4c3 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -594,6 +594,8 @@ public class ZygoteProcess {
argsForZygote.add("--mount-external-legacy");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_PASS_THROUGH) {
argsForZygote.add("--mount-external-pass-through");
+ } else if (mountExternal == Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE) {
+ argsForZygote.add("--mount-external-android-writable");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 8959fcf7ac18..f0a11748fbd6 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -31,6 +31,7 @@ import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.annotation.BytesLong;
+import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -72,6 +73,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.provider.MediaStore;
import android.provider.Settings;
import android.sysprop.VoldProperties;
@@ -93,7 +95,6 @@ import com.android.internal.os.AppFuseMount;
import com.android.internal.os.FuseAppLoop;
import com.android.internal.os.FuseUnavailableMountException;
import com.android.internal.os.RoSystemProperties;
-import com.android.internal.os.SomeArgs;
import com.android.internal.util.Preconditions;
import dalvik.system.BlockGuard;
@@ -114,6 +115,7 @@ import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -305,109 +307,85 @@ public class StorageManager {
private final Looper mLooper;
private final AtomicInteger mNextNonce = new AtomicInteger(0);
+ @GuardedBy("mDelegates")
private final ArrayList<StorageEventListenerDelegate> mDelegates = new ArrayList<>();
- private static class StorageEventListenerDelegate extends IStorageEventListener.Stub implements
- Handler.Callback {
- private static final int MSG_STORAGE_STATE_CHANGED = 1;
- private static final int MSG_VOLUME_STATE_CHANGED = 2;
- private static final int MSG_VOLUME_RECORD_CHANGED = 3;
- private static final int MSG_VOLUME_FORGOTTEN = 4;
- private static final int MSG_DISK_SCANNED = 5;
- private static final int MSG_DISK_DESTROYED = 6;
+ private class StorageEventListenerDelegate extends IStorageEventListener.Stub {
+ final Executor mExecutor;
+ final StorageEventListener mListener;
+ final StorageVolumeCallback mCallback;
- final StorageEventListener mCallback;
- final Handler mHandler;
-
- public StorageEventListenerDelegate(StorageEventListener callback, Looper looper) {
+ public StorageEventListenerDelegate(@NonNull Executor executor,
+ @NonNull StorageEventListener listener, @NonNull StorageVolumeCallback callback) {
+ mExecutor = executor;
+ mListener = listener;
mCallback = callback;
- mHandler = new Handler(looper, this);
- }
-
- @Override
- public boolean handleMessage(Message msg) {
- final SomeArgs args = (SomeArgs) msg.obj;
- switch (msg.what) {
- case MSG_STORAGE_STATE_CHANGED:
- mCallback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
- (String) args.arg3);
- args.recycle();
- return true;
- case MSG_VOLUME_STATE_CHANGED:
- mCallback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
- args.recycle();
- return true;
- case MSG_VOLUME_RECORD_CHANGED:
- mCallback.onVolumeRecordChanged((VolumeRecord) args.arg1);
- args.recycle();
- return true;
- case MSG_VOLUME_FORGOTTEN:
- mCallback.onVolumeForgotten((String) args.arg1);
- args.recycle();
- return true;
- case MSG_DISK_SCANNED:
- mCallback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
- args.recycle();
- return true;
- case MSG_DISK_DESTROYED:
- mCallback.onDiskDestroyed((DiskInfo) args.arg1);
- args.recycle();
- return true;
- }
- args.recycle();
- return false;
}
@Override
public void onUsbMassStorageConnectionChanged(boolean connected) throws RemoteException {
- // Ignored
+ mExecutor.execute(() -> {
+ mListener.onUsbMassStorageConnectionChanged(connected);
+ });
}
@Override
public void onStorageStateChanged(String path, String oldState, String newState) {
- final SomeArgs args = SomeArgs.obtain();
- args.arg1 = path;
- args.arg2 = oldState;
- args.arg3 = newState;
- mHandler.obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
+ mExecutor.execute(() -> {
+ mListener.onStorageStateChanged(path, oldState, newState);
+
+ if (path != null) {
+ for (StorageVolume sv : getStorageVolumes()) {
+ if (Objects.equals(path, sv.getPath())) {
+ mCallback.onStateChanged(sv);
+ }
+ }
+ }
+ });
}
@Override
public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
- final SomeArgs args = SomeArgs.obtain();
- args.arg1 = vol;
- args.argi2 = oldState;
- args.argi3 = newState;
- mHandler.obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
+ mExecutor.execute(() -> {
+ mListener.onVolumeStateChanged(vol, oldState, newState);
+
+ final File path = vol.getPathForUser(UserHandle.myUserId());
+ if (path != null) {
+ for (StorageVolume sv : getStorageVolumes()) {
+ if (Objects.equals(path.getAbsolutePath(), sv.getPath())) {
+ mCallback.onStateChanged(sv);
+ }
+ }
+ }
+ });
}
@Override
public void onVolumeRecordChanged(VolumeRecord rec) {
- final SomeArgs args = SomeArgs.obtain();
- args.arg1 = rec;
- mHandler.obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget();
+ mExecutor.execute(() -> {
+ mListener.onVolumeRecordChanged(rec);
+ });
}
@Override
public void onVolumeForgotten(String fsUuid) {
- final SomeArgs args = SomeArgs.obtain();
- args.arg1 = fsUuid;
- mHandler.obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget();
+ mExecutor.execute(() -> {
+ mListener.onVolumeForgotten(fsUuid);
+ });
}
@Override
public void onDiskScanned(DiskInfo disk, int volumeCount) {
- final SomeArgs args = SomeArgs.obtain();
- args.arg1 = disk;
- args.argi2 = volumeCount;
- mHandler.obtainMessage(MSG_DISK_SCANNED, args).sendToTarget();
+ mExecutor.execute(() -> {
+ mListener.onDiskScanned(disk, volumeCount);
+ });
}
@Override
public void onDiskDestroyed(DiskInfo disk) throws RemoteException {
- final SomeArgs args = SomeArgs.obtain();
- args.arg1 = disk;
- mHandler.obtainMessage(MSG_DISK_DESTROYED, args).sendToTarget();
+ mExecutor.execute(() -> {
+ mListener.onDiskDestroyed(disk);
+ });
}
}
@@ -525,8 +503,8 @@ public class StorageManager {
@UnsupportedAppUsage
public void registerListener(StorageEventListener listener) {
synchronized (mDelegates) {
- final StorageEventListenerDelegate delegate = new StorageEventListenerDelegate(listener,
- mLooper);
+ final StorageEventListenerDelegate delegate = new StorageEventListenerDelegate(
+ mContext.getMainExecutor(), listener, new StorageVolumeCallback());
try {
mStorageManager.registerListener(delegate);
} catch (RemoteException e) {
@@ -548,7 +526,76 @@ public class StorageManager {
synchronized (mDelegates) {
for (Iterator<StorageEventListenerDelegate> i = mDelegates.iterator(); i.hasNext();) {
final StorageEventListenerDelegate delegate = i.next();
- if (delegate.mCallback == listener) {
+ if (delegate.mListener == listener) {
+ try {
+ mStorageManager.unregisterListener(delegate);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ i.remove();
+ }
+ }
+ }
+ }
+
+ /**
+ * Callback that delivers {@link StorageVolume} related events.
+ * <p>
+ * For example, this can be used to detect when a volume changes to the
+ * {@link Environment#MEDIA_MOUNTED} or {@link Environment#MEDIA_UNMOUNTED}
+ * states.
+ *
+ * @see StorageManager#registerStorageVolumeCallback
+ * @see StorageManager#unregisterStorageVolumeCallback
+ */
+ public static class StorageVolumeCallback {
+ /**
+ * Called when {@link StorageVolume#getState()} changes, such as
+ * changing to the {@link Environment#MEDIA_MOUNTED} or
+ * {@link Environment#MEDIA_UNMOUNTED} states.
+ * <p>
+ * The given argument is a snapshot in time and can be used to process
+ * events in the order they occurred, or you can call
+ * {@link StorageManager#getStorageVolumes()} to observe the latest
+ * value.
+ */
+ public void onStateChanged(@NonNull StorageVolume volume) { }
+ }
+
+ /**
+ * Registers the given callback to listen for {@link StorageVolume} changes.
+ * <p>
+ * For example, this can be used to detect when a volume changes to the
+ * {@link Environment#MEDIA_MOUNTED} or {@link Environment#MEDIA_UNMOUNTED}
+ * states.
+ *
+ * @see StorageManager#unregisterStorageVolumeCallback
+ */
+ public void registerStorageVolumeCallback(@CallbackExecutor @NonNull Executor executor,
+ @NonNull StorageVolumeCallback callback) {
+ synchronized (mDelegates) {
+ final StorageEventListenerDelegate delegate = new StorageEventListenerDelegate(
+ executor, new StorageEventListener(), callback);
+ try {
+ mStorageManager.registerListener(delegate);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ mDelegates.add(delegate);
+ }
+ }
+
+ /**
+ * Unregisters the given callback from listening for {@link StorageVolume}
+ * changes.
+ *
+ * @see StorageManager#registerStorageVolumeCallback
+ */
+ public void unregisterStorageVolumeCallback(@NonNull StorageVolumeCallback callback) {
+ synchronized (mDelegates) {
+ for (Iterator<StorageEventListenerDelegate> i = mDelegates.iterator(); i.hasNext();) {
+ final StorageEventListenerDelegate delegate = i.next();
+ if (delegate.mCallback == callback) {
try {
mStorageManager.unregisterListener(delegate);
} catch (RemoteException e) {
@@ -829,7 +876,14 @@ public class StorageManager {
*/
public @NonNull UUID getUuidForPath(@NonNull File path) throws IOException {
Preconditions.checkNotNull(path);
- final String pathString = path.getCanonicalPath();
+ String pathString = path.getCanonicalPath();
+ if (path.getPath().startsWith("/sdcard")) {
+ // On FUSE enabled devices, realpath(2) /sdcard is /mnt/user/<userid>/emulated/<userid>
+ // as opposed to /storage/emulated/<userid>.
+ // And vol.path below expects to match with a path starting with /storage
+ pathString = pathString.replaceFirst("^/mnt/user/[0-9]+/", "/storage/");
+ }
+
if (FileUtils.contains(Environment.getDataDirectory().getAbsolutePath(), pathString)) {
return UUID_DEFAULT;
}
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index 2ab226f81bb4..e251f8072b1f 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -18,6 +18,7 @@ package android.os.storage;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -162,9 +163,13 @@ public final class StorageVolume implements Parcelable {
mState = in.readString();
}
- /** {@hide} */
- @UnsupportedAppUsage
- public String getId() {
+ /**
+ * Return an opaque ID that can be used to identify this volume.
+ *
+ * @hide
+ */
+ @SystemApi
+ public @NonNull String getId() {
return mId;
}
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 0a3c333ae7b1..ef8a2860cf4f 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -553,7 +553,9 @@ public final class DocumentsContract {
/**
* Flag indicating that a document is a directory that wants to block itself
* from being selected when the user launches an {@link Intent#ACTION_OPEN_DOCUMENT_TREE}
- * intent. Only valid when {@link #COLUMN_MIME_TYPE} is {@link #MIME_TYPE_DIR}.
+ * intent. Individual files can still be selected when launched via other intents
+ * like {@link Intent#ACTION_OPEN_DOCUMENT} and {@link Intent#ACTION_GET_CONTENT}.
+ * Only valid when {@link #COLUMN_MIME_TYPE} is {@link #MIME_TYPE_DIR}.
* <p>
* Note that this flag <em>only</em> applies to the single directory to which it is
* applied. It does <em>not</em> block the user from selecting either a parent or
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 07cbcfbb298b..9ee4cc30949d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -218,7 +218,9 @@ public final class Settings {
* @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_TETHER_PROVISIONING =
+ @SystemApi
+ @TestApi
+ public static final String ACTION_TETHER_PROVISIONING_UI =
"android.settings.TETHER_PROVISIONING_UI";
/**
@@ -9697,6 +9699,8 @@ public final class Settings {
* is interpreted as |false|.
* @hide
*/
+ @SystemApi
+ @TestApi
public static final String TETHER_OFFLOAD_DISABLED = "tether_offload_disabled";
/**
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index d51e4ca6398f..939ae878816a 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -609,10 +609,12 @@ public final class FillResponse implements Parcelable {
"must add at least 1 dataset when using header or footer");
}
- for (final Dataset dataset : mDatasets) {
- if (dataset.getFieldInlinePresentation(0) != null) {
- mSupportsInlineSuggestions = true;
- break;
+ if (mDatasets != null) {
+ for (final Dataset dataset : mDatasets) {
+ if (dataset.getFieldInlinePresentation(0) != null) {
+ mSupportsInlineSuggestions = true;
+ break;
+ }
}
}
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 771695c2b873..a3245b9916ec 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -257,10 +257,6 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
for (int i = items.size() - 1; i >= 0; i--) {
final InsetsSourceControl control = items.valueAt(i);
final InsetsSource source = mInitialInsetsState.getSource(control.getType());
- if (control == null) {
- // TODO: remove this check when we ensure the elements will not be null.
- continue;
- }
final SurfaceControl leash = control.getLeash();
mTmpMatrix.setTranslate(control.getSurfacePosition().x, control.getSurfacePosition().y);
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 4d4ace27cac9..2a7a4e3a922c 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -375,8 +375,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
cancelExistingControllers(types);
- final ArraySet<Integer> internalTypes = mState.toInternalType(types);
- final SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>();
+ final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types);
final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
Pair<Integer, Boolean> typesReadyPair = collectSourceControls(
@@ -441,7 +440,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
typesReady |= InsetsState.toPublicType(consumer.getType());
}
- controls.put(consumer.getType(), consumer.getControl());
+ final InsetsSourceControl control = consumer.getControl();
+ if (control != null) {
+ controls.put(consumer.getType(), control);
+ }
}
return new Pair<>(typesReady, isReady);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index f6d6522f80d6..ff8455ab0915 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -677,6 +677,22 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * Set the initial visibility for the SurfaceControl.
+ *
+ * @param hidden Whether the Surface is initially HIDDEN.
+ * @hide
+ */
+ @NonNull
+ public Builder setHidden(boolean hidden) {
+ if (hidden) {
+ mFlags |= HIDDEN;
+ } else {
+ mFlags &= ~HIDDEN;
+ }
+ return this;
+ }
+
+ /**
* Set a parent surface for our new SurfaceControl.
*
* Child surfaces are constrained to the onscreen region of their parent.
@@ -789,8 +805,7 @@ public final class SurfaceControl implements Parcelable {
* @param name The surface name, must not be null.
* @param w The surface initial width.
* @param h The surface initial height.
- * @param flags The surface creation flags. Should always include {@link #HIDDEN}
- * in the creation flags.
+ * @param flags The surface creation flags.
* @param metadata Initial metadata.
* @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
*/
@@ -801,15 +816,6 @@ public final class SurfaceControl implements Parcelable {
throw new IllegalArgumentException("name must not be null");
}
- if ((flags & SurfaceControl.HIDDEN) == 0) {
- Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set "
- + "to ensure that they are not made visible prematurely before "
- + "all of the surface's properties have been configured. "
- + "Set the other properties and make the surface visible within "
- + "a transaction. New surface name: " + name,
- new Throwable());
- }
-
mName = name;
mWidth = w;
mHeight = h;
diff --git a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
index f9ba34ed1c3a..0a0d05ce8fc8 100644
--- a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
+++ b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
@@ -61,7 +61,6 @@ public class AccessibilityButtonChooserActivity extends Activity {
private int mShortcutType;
private List<AccessibilityButtonTarget> mTargets = new ArrayList<>();
- private List<AccessibilityButtonTarget> mReadyToBeDisabledTargets = new ArrayList<>();
private AlertDialog mAlertDialog;
private TargetAdapter mTargetAdapter;
@@ -117,7 +116,6 @@ public class AccessibilityButtonChooserActivity extends Activity {
ACCESSIBILITY_BUTTON);
mTargets.addAll(getServiceTargets(this, mShortcutType));
- // TODO(b/146815548): Will add title to separate which one type
mTargetAdapter = new TargetAdapter(mTargets);
mAlertDialog = new AlertDialog.Builder(this)
.setAdapter(mTargetAdapter, /* listener= */ null)
@@ -269,8 +267,10 @@ public class AccessibilityButtonChooserActivity extends Activity {
switch (target.getFragmentType()) {
case AccessibilityServiceFragmentType.LEGACY:
+ updateLegacyActionItemVisibility(context, holder);
+ break;
case AccessibilityServiceFragmentType.INVISIBLE:
- updateLegacyOrInvisibleActionItemVisibility(context, holder);
+ updateInvisibleActionItemVisibility(context, holder);
break;
case AccessibilityServiceFragmentType.INTUITIVE:
updateIntuitiveActionItemVisibility(context, holder, target);
@@ -283,9 +283,21 @@ public class AccessibilityButtonChooserActivity extends Activity {
}
}
- private void updateLegacyOrInvisibleActionItemVisibility(@NonNull Context context,
+ private void updateLegacyActionItemVisibility(@NonNull Context context,
+ @NonNull ViewHolder holder) {
+ final boolean isEditMenuMode = (mShortcutMenuMode == ShortcutMenuMode.EDIT);
+
+ holder.mLabelView.setEnabled(!isEditMenuMode);
+ holder.mViewItem.setEnabled(!isEditMenuMode);
+ holder.mViewItem.setImageDrawable(context.getDrawable(R.drawable.ic_delete_item));
+ holder.mViewItem.setVisibility(View.VISIBLE);
+ holder.mSwitchItem.setVisibility(View.GONE);
+ holder.mItemContainer.setVisibility(isEditMenuMode ? View.VISIBLE : View.GONE);
+ }
+
+ private void updateInvisibleActionItemVisibility(@NonNull Context context,
@NonNull ViewHolder holder) {
- final boolean isEditMenuMode = mShortcutMenuMode == ShortcutMenuMode.EDIT;
+ final boolean isEditMenuMode = (mShortcutMenuMode == ShortcutMenuMode.EDIT);
holder.mViewItem.setImageDrawable(context.getDrawable(R.drawable.ic_delete_item));
holder.mViewItem.setVisibility(View.VISIBLE);
@@ -295,7 +307,7 @@ public class AccessibilityButtonChooserActivity extends Activity {
private void updateIntuitiveActionItemVisibility(@NonNull Context context,
@NonNull ViewHolder holder, AccessibilityButtonTarget target) {
- final boolean isEditMenuMode = mShortcutMenuMode == ShortcutMenuMode.EDIT;
+ final boolean isEditMenuMode = (mShortcutMenuMode == ShortcutMenuMode.EDIT);
holder.mViewItem.setImageDrawable(context.getDrawable(R.drawable.ic_delete_item));
holder.mViewItem.setVisibility(isEditMenuMode ? View.VISIBLE : View.GONE);
@@ -306,7 +318,7 @@ public class AccessibilityButtonChooserActivity extends Activity {
private void updateBounceActionItemVisibility(@NonNull Context context,
@NonNull ViewHolder holder) {
- final boolean isEditMenuMode = mShortcutMenuMode == ShortcutMenuMode.EDIT;
+ final boolean isEditMenuMode = (mShortcutMenuMode == ShortcutMenuMode.EDIT);
holder.mViewItem.setImageDrawable(
isEditMenuMode ? context.getDrawable(R.drawable.ic_delete_item)
@@ -383,20 +395,23 @@ public class AccessibilityButtonChooserActivity extends Activity {
}
private void onTargetDeleted(AdapterView<?> parent, View view, int position, long id) {
- // TODO(b/147027236): Will discuss with UX designer what UX behavior about deleting item
- // is good for user.
- mReadyToBeDisabledTargets.add(mTargets.get(position));
- mTargets.remove(position);
- mTargetAdapter.notifyDataSetChanged();
+ // TODO(b/146967898): disable service when deleting the target and the target only have
+ // last one shortcut item, only remove it from shortcut list otherwise.
+ if ((mShortcutType == ACCESSIBILITY_BUTTON) && (mTargets.get(position).mFragmentType
+ != AccessibilityServiceFragmentType.LEGACY)) {
+ mTargets.remove(position);
+ mTargetAdapter.notifyDataSetChanged();
+ }
+
+ if (mTargets.isEmpty()) {
+ mAlertDialog.dismiss();
+ }
}
private void onCancelButtonClicked() {
- resetAndUpdateTargets();
-
mTargetAdapter.setShortcutMenuMode(ShortcutMenuMode.LAUNCH);
mTargetAdapter.notifyDataSetChanged();
- mAlertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.GONE);
mAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setText(
getString(R.string.edit_accessibility_shortcut_menu_button));
@@ -407,49 +422,19 @@ public class AccessibilityButtonChooserActivity extends Activity {
mTargetAdapter.setShortcutMenuMode(ShortcutMenuMode.EDIT);
mTargetAdapter.notifyDataSetChanged();
- mAlertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setText(
- getString(R.string.cancel_accessibility_shortcut_menu_button));
- mAlertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.VISIBLE);
- mAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setText(
- getString(R.string.save_accessibility_shortcut_menu_button));
-
- updateDialogListeners();
- }
-
- private void onSaveButtonClicked() {
- disableTargets();
- resetAndUpdateTargets();
-
- mTargetAdapter.setShortcutMenuMode(ShortcutMenuMode.LAUNCH);
- mTargetAdapter.notifyDataSetChanged();
-
- mAlertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.GONE);
mAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setText(
- getString(R.string.edit_accessibility_shortcut_menu_button));
+ getString(R.string.cancel_accessibility_shortcut_menu_button));
updateDialogListeners();
}
private void updateDialogListeners() {
final boolean isEditMenuMode =
- mTargetAdapter.getShortcutMenuMode() == ShortcutMenuMode.EDIT;
+ (mTargetAdapter.getShortcutMenuMode() == ShortcutMenuMode.EDIT);
- mAlertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(
- view -> onCancelButtonClicked());
mAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(
- isEditMenuMode ? view -> onSaveButtonClicked() : view -> onEditButtonClicked());
+ isEditMenuMode ? view -> onCancelButtonClicked() : view -> onEditButtonClicked());
mAlertDialog.getListView().setOnItemClickListener(
isEditMenuMode ? this::onTargetDeleted : this::onTargetSelected);
}
-
- private void disableTargets() {
- for (AccessibilityButtonTarget service : mReadyToBeDisabledTargets) {
- // TODO(b/146967898): disable services.
- }
- }
-
- private void resetAndUpdateTargets() {
- mTargets.clear();
- mTargets.addAll(getServiceTargets(this, mShortcutType));
- }
}
diff --git a/core/java/com/android/internal/infra/AndroidFuture.java b/core/java/com/android/internal/infra/AndroidFuture.java
index b250578c8454..9f15d8991fa7 100644
--- a/core/java/com/android/internal/infra/AndroidFuture.java
+++ b/core/java/com/android/internal/infra/AndroidFuture.java
@@ -75,6 +75,7 @@ public class AndroidFuture<T> extends CompletableFuture<T> implements Parcelable
private static final boolean DEBUG = false;
private static final String LOG_TAG = AndroidFuture.class.getSimpleName();
+ private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];
private final @NonNull Object mLock = new Object();
@GuardedBy("mLock")
@@ -95,15 +96,7 @@ public class AndroidFuture<T> extends CompletableFuture<T> implements Parcelable
// Done
if (in.readBoolean()) {
// Failed
- try {
- in.readException();
- } catch (Throwable e) {
- completeExceptionally(e);
- }
- if (!isCompletedExceptionally()) {
- throw new IllegalStateException(
- "Error unparceling AndroidFuture: exception expected");
- }
+ completeExceptionally(unparcelException(in));
} else {
// Success
complete((T) in.readValue(null));
@@ -512,14 +505,9 @@ public class AndroidFuture<T> extends CompletableFuture<T> implements Parcelable
T result;
try {
result = get();
- } catch (Exception t) {
- // Exceptions coming out of get() are wrapped in ExecutionException, which is not
- // handled by Parcel.
- if (t instanceof ExecutionException && t.getCause() instanceof Exception) {
- t = (Exception) t.getCause();
- }
+ } catch (Throwable t) {
dest.writeBoolean(true);
- dest.writeException(t);
+ parcelException(dest, unwrapExecutionException(t));
return;
}
dest.writeBoolean(false);
@@ -528,22 +516,76 @@ public class AndroidFuture<T> extends CompletableFuture<T> implements Parcelable
dest.writeStrongBinder(new IAndroidFuture.Stub() {
@Override
public void complete(AndroidFuture resultContainer) {
+ boolean changed;
try {
- AndroidFuture.this.complete((T) resultContainer.get());
+ changed = AndroidFuture.this.complete((T) resultContainer.get());
} catch (Throwable t) {
- // If resultContainer was completed exceptionally, get() wraps the
- // underlying exception in an ExecutionException. Unwrap it now to avoid
- // double-layering ExecutionExceptions.
- if (t instanceof ExecutionException && t.getCause() != null) {
- t = t.getCause();
- }
- completeExceptionally(t);
+ changed = completeExceptionally(unwrapExecutionException(t));
+ }
+ if (!changed) {
+ Log.w(LOG_TAG, "Remote result " + resultContainer
+ + " ignored, as local future is already completed: "
+ + AndroidFuture.this);
}
}
}.asBinder());
}
}
+ /**
+ * Exceptions coming out of {@link #get} are wrapped in {@link ExecutionException}
+ */
+ Throwable unwrapExecutionException(Throwable t) {
+ return t instanceof ExecutionException
+ ? t.getCause()
+ : t;
+ }
+
+ /**
+ * Alternative to {@link Parcel#writeException} that stores the stack trace, in a
+ * way consistent with the binder IPC exception propagation behavior.
+ */
+ private static void parcelException(Parcel p, @Nullable Throwable t) {
+ p.writeBoolean(t == null);
+ if (t == null) {
+ return;
+ }
+
+ p.writeInt(Parcel.getExceptionCode(t));
+ p.writeString(t.getClass().getName());
+ p.writeString(t.getMessage());
+ p.writeStackTrace(t);
+ parcelException(p, t.getCause());
+ }
+
+ /**
+ * @see #parcelException
+ */
+ private static @Nullable Throwable unparcelException(Parcel p) {
+ if (p.readBoolean()) {
+ return null;
+ }
+
+ int exCode = p.readInt();
+ String cls = p.readString();
+ String msg = p.readString();
+ String stackTrace = p.readInt() > 0 ? p.readString() : "\t<stack trace unavailable>";
+ msg += "\n" + stackTrace;
+
+ Exception ex = p.createExceptionOrNull(exCode, msg);
+ if (ex == null) {
+ ex = new RuntimeException(cls + ": " + msg);
+ }
+ ex.setStackTrace(EMPTY_STACK_TRACE);
+
+ Throwable cause = unparcelException(p);
+ if (cause != null) {
+ ex.initCause(ex);
+ }
+
+ return ex;
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 2248b8853f8c..f0a346ab25fd 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -145,6 +145,11 @@ public final class Zygote {
/** The lower file system should be bind mounted directly on external storage */
public static final int MOUNT_EXTERNAL_PASS_THROUGH = IVold.REMOUNT_MODE_PASS_THROUGH;
+ /** Use the regular scoped storage filesystem, but Android/ should be writable.
+ * Used to support the applications hosting DownloadManager and the MTP server.
+ */
+ public static final int MOUNT_EXTERNAL_ANDROID_WRITABLE = IVold.REMOUNT_MODE_ANDROID_WRITABLE;
+
/** Number of bytes sent to the Zygote over USAP pipes or the pool event FD */
static final int USAP_MANAGEMENT_MESSAGE_BYTES = 8;
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index d3499541a3a3..37f570bba238 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -376,6 +376,8 @@ class ZygoteArguments {
mMountExternal = Zygote.MOUNT_EXTERNAL_LEGACY;
} else if (arg.equals("--mount-external-pass-through")) {
mMountExternal = Zygote.MOUNT_EXTERNAL_PASS_THROUGH;
+ } else if (arg.equals("--mount-external-android-writable")) {
+ mMountExternal = Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
} else if (arg.equals("--query-abi-list")) {
mAbiListQuery = true;
} else if (arg.equals("--get-pid")) {
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 8a59c998dacb..74b481c938c3 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -218,6 +218,7 @@ public class SystemConfig {
final ArrayMap<String, ArraySet<String>> mAllowedAssociations = new ArrayMap<>();
private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>();
+ private final ArraySet<String> mAppDataIsolationWhitelistedApps = new ArraySet<>();
// Map of packagesNames to userTypes. Stored temporarily until cleared by UserManagerService().
private ArrayMap<String, Set<String>> mPackageToUserTypeWhitelist = new ArrayMap<>();
@@ -389,6 +390,10 @@ public class SystemConfig {
return mRollbackWhitelistedPackages;
}
+ public ArraySet<String> getAppDataIsolationWhitelistedApps() {
+ return mAppDataIsolationWhitelistedApps;
+ }
+
/**
* Gets map of packagesNames to userTypes, dictating on which user types each package should be
* initially installed, and then removes this map from SystemConfig.
@@ -1045,6 +1050,16 @@ public class SystemConfig {
}
XmlUtils.skipCurrentTag(parser);
} break;
+ case "app-data-isolation-whitelisted-app": {
+ String pkgname = parser.getAttributeValue(null, "package");
+ if (pkgname == null) {
+ Slog.w(TAG, "<" + name + "> without package in " + permFile
+ + " at " + parser.getPositionDescription());
+ } else {
+ mAppDataIsolationWhitelistedApps.add(pkgname);
+ }
+ XmlUtils.skipCurrentTag(parser);
+ } break;
case "bugreport-whitelisted": {
String pkgname = parser.getAttributeValue(null, "package");
if (pkgname == null) {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index d17d0a4ebbe2..5039213954d7 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -319,7 +319,8 @@ enum MountExternalKind {
MOUNT_EXTERNAL_INSTALLER = 5,
MOUNT_EXTERNAL_FULL = 6,
MOUNT_EXTERNAL_PASS_THROUGH = 7,
- MOUNT_EXTERNAL_COUNT = 8
+ MOUNT_EXTERNAL_ANDROID_WRITABLE = 8,
+ MOUNT_EXTERNAL_COUNT = 9
};
// The order of entries here must be kept in sync with MountExternalKind enum values.
@@ -331,6 +332,8 @@ static const std::array<const std::string, MOUNT_EXTERNAL_COUNT> ExternalStorage
"/mnt/runtime/write", // MOUNT_EXTERNAL_LEGACY
"/mnt/runtime/write", // MOUNT_EXTERNAL_INSTALLER
"/mnt/runtime/full", // MOUNT_EXTERNAL_FULL
+ "/mnt/runtime/full", // MOUNT_EXTERNAL_PASS_THROUGH (only used w/ FUSE)
+ "/mnt/runtime/full", // MOUNT_EXTERNAL_ANDROID_WRITABLE (only used w/ FUSE)
};
// Must match values in com.android.internal.os.Zygote.
@@ -755,12 +758,7 @@ static void MountEmulatedStorage(uid_t uid, jint mount_mode,
multiuser_get_uid(user_id, AID_EVERYBODY), fail_fn);
if (isFuse) {
- if (mount_mode == MOUNT_EXTERNAL_PASS_THROUGH || mount_mode ==
- MOUNT_EXTERNAL_INSTALLER || mount_mode == MOUNT_EXTERNAL_FULL) {
- // For now, MediaProvider, installers and "full" get the pass_through mount
- // view, which is currently identical to the sdcardfs write view.
- //
- // TODO(b/146189163): scope down MOUNT_EXTERNAL_INSTALLER
+ if (mount_mode == MOUNT_EXTERNAL_PASS_THROUGH) {
BindMount(pass_through_source, "/storage", fail_fn);
} else {
BindMount(user_source, "/storage", fail_fn);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ea70dcf28e69..a808ed8fcc81 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4756,6 +4756,10 @@
<!-- Allows input events to be monitored. Very dangerous! @hide -->
<permission android:name="android.permission.MONITOR_INPUT"
android:protectionLevel="signature" />
+ <!-- Allows the caller to change the associations between input devices and displays.
+ Very dangerous! @hide -->
+ <permission android:name="android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT"
+ android:protectionLevel="signature" />
<!-- Allows query of any normal app on the device, regardless of manifest declarations. -->
<permission android:name="android.permission.QUERY_ALL_PACKAGES"
diff --git a/core/res/res/layout/accessibility_button_chooser_item.xml b/core/res/res/layout/accessibility_button_chooser_item.xml
index 1edd2cdfcfe3..d19e313055ae 100644
--- a/core/res/res/layout/accessibility_button_chooser_item.xml
+++ b/core/res/res/layout/accessibility_button_chooser_item.xml
@@ -36,7 +36,7 @@
android:id="@+id/accessibility_button_target_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_marginStart="8dp"
+ android:layout_marginStart="14dp"
android:layout_weight="1"
android:textColor="?attr/textColorPrimary"/>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 66267d136e10..a0e40646ead9 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4358,10 +4358,7 @@
<string name="accessibility_shortcut_menu_button">Empty</string>
<!-- Text in button that edit the accessibility shortcut menu. [CHAR LIMIT=100] -->
- <string name="edit_accessibility_shortcut_menu_button">Edit</string>
-
- <!-- Text in button that save the accessibility shortcut menu changed status. [CHAR LIMIT=100] -->
- <string name="save_accessibility_shortcut_menu_button">Save</string>
+ <string name="edit_accessibility_shortcut_menu_button">Edit shortcuts</string>
<!-- Text in button that cancel the accessibility shortcut menu changed status. [CHAR LIMIT=100] -->
<string name="cancel_accessibility_shortcut_menu_button">Cancel</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index cdbf14bf969a..973d5f6392f4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3212,7 +3212,6 @@
<java-symbol type="id" name="accessibility_button_target_switch_item" />
<java-symbol type="string" name="accessibility_magnification_chooser_text" />
<java-symbol type="string" name="edit_accessibility_shortcut_menu_button" />
- <java-symbol type="string" name="save_accessibility_shortcut_menu_button" />
<java-symbol type="string" name="cancel_accessibility_shortcut_menu_button" />
<java-symbol type="drawable" name="ic_accessibility_magnification" />
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java
index f0a83678f70b..a296ca27e268 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java
@@ -16,6 +16,7 @@
package com.android.connectivitymanagertest;
+import android.net.IpConfiguration;
import android.net.IpConfiguration.IpAssignment;
import android.net.IpConfiguration.ProxySettings;
import android.net.LinkAddress;
@@ -136,7 +137,7 @@ public class WifiConfigurationHelper {
config.enterpriseConfig.setPhase2Method(phase2);
config.enterpriseConfig.setIdentity(identity);
config.enterpriseConfig.setAnonymousIdentity(anonymousIdentity);
- config.enterpriseConfig.setCaCertificateAlias(caCert);
+ config.enterpriseConfig.setCaCertificateAliases(new String[] {caCert});
config.enterpriseConfig.setClientCertificateAlias(clientCert);
return config;
}
@@ -147,8 +148,12 @@ public class WifiConfigurationHelper {
private static WifiConfiguration createGenericConfig(String ssid) {
WifiConfiguration config = new WifiConfiguration();
config.SSID = quotedString(ssid);
- config.setIpAssignment(IpAssignment.DHCP);
- config.setProxySettings(ProxySettings.NONE);
+
+ IpConfiguration ipConfiguration = config.getIpConfiguration();
+ ipConfiguration.setIpAssignment(IpAssignment.DHCP);
+ ipConfiguration.setProxySettings(ProxySettings.NONE);
+ config.setIpConfiguration(ipConfiguration);
+
return config;
}
@@ -237,6 +242,7 @@ public class WifiConfigurationHelper {
throw new IllegalArgumentException();
}
+ IpConfiguration ipConfiguration = config.getIpConfiguration();
if (jsonConfig.has("ip")) {
StaticIpConfiguration staticIpConfig = new StaticIpConfiguration();
@@ -247,13 +253,14 @@ public class WifiConfigurationHelper {
staticIpConfig.dnsServers.add(getInetAddress(jsonConfig.getString("dns1")));
staticIpConfig.dnsServers.add(getInetAddress(jsonConfig.getString("dns2")));
- config.setIpAssignment(IpAssignment.STATIC);
- config.setStaticIpConfiguration(staticIpConfig);
+ ipConfiguration.setIpAssignment(IpAssignment.STATIC);
+ ipConfiguration.setStaticIpConfiguration(staticIpConfig);
} else {
- config.setIpAssignment(IpAssignment.DHCP);
+ ipConfiguration.setIpAssignment(IpAssignment.DHCP);
}
+ ipConfiguration.setProxySettings(ProxySettings.NONE);
+ config.setIpConfiguration(ipConfiguration);
- config.setProxySettings(ProxySettings.NONE);
return config;
}
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
index 2989df83866c..5d42915fc82b 100644
--- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
@@ -268,7 +268,7 @@ public class BandwidthTest extends InstrumentationTestCase {
File snd_stat = new File (root_filepath + "tcp_snd");
int tx = BandwidthTestUtil.parseIntValueFromFile(snd_stat);
NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
- stats.addValues(NetworkStats.IFACE_ALL, uid, NetworkStats.SET_DEFAULT,
+ stats.addEntry(NetworkStats.IFACE_ALL, uid, NetworkStats.SET_DEFAULT,
NetworkStats.TAG_NONE, rx, 0, tx, 0, 0);
return stats;
}
diff --git a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
index 707d7b30e09b..239f971664e9 100644
--- a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
+++ b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
@@ -54,7 +54,7 @@ public class NetworkStatsBenchmark {
recycle.txBytes = 150000;
recycle.txPackets = 1500;
recycle.operations = 0;
- mNetworkStats.addValues(recycle);
+ mNetworkStats.addEntry(recycle);
if (recycle.set == 1) {
uid++;
}
@@ -70,7 +70,7 @@ public class NetworkStatsBenchmark {
recycle.txBytes = 180000 * mSize;
recycle.txPackets = 1200 * mSize;
recycle.operations = 0;
- mNetworkStats.addValues(recycle);
+ mNetworkStats.addEntry(recycle);
}
}
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index beaaa373b1a0..d8b527c8a11a 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -438,8 +438,7 @@ public class ActivityThreadTest {
}
private static ClientTransaction newStopTransaction(Activity activity) {
- final StopActivityItem stopStateRequest =
- StopActivityItem.obtain(false /* showWindow */, 0 /* configChanges */);
+ final StopActivityItem stopStateRequest = StopActivityItem.obtain(0 /* configChanges */);
final ClientTransaction transaction = newTransaction(activity);
transaction.setLifecycleStateRequest(stopStateRequest);
diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
index 37d21f0928be..4b29d59de332 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
@@ -274,30 +274,15 @@ public class ObjectPoolTests {
@Test
public void testRecycleStopItem() {
- StopActivityItem emptyItem = StopActivityItem.obtain(false, 0);
- StopActivityItem item = StopActivityItem.obtain(true, 4);
+ StopActivityItem emptyItem = StopActivityItem.obtain(0);
+ StopActivityItem item = StopActivityItem.obtain(4);
assertNotSame(item, emptyItem);
assertFalse(item.equals(emptyItem));
item.recycle();
assertEquals(item, emptyItem);
- StopActivityItem item2 = StopActivityItem.obtain(true, 3);
- assertSame(item, item2);
- assertFalse(item2.equals(emptyItem));
- }
-
- @Test
- public void testRecycleWindowVisibleItem() {
- WindowVisibilityItem emptyItem = WindowVisibilityItem.obtain(false);
- WindowVisibilityItem item = WindowVisibilityItem.obtain(true);
- assertNotSame(item, emptyItem);
- assertFalse(item.equals(emptyItem));
-
- item.recycle();
- assertEquals(item, emptyItem);
-
- WindowVisibilityItem item2 = WindowVisibilityItem.obtain(true);
+ StopActivityItem item2 = StopActivityItem.obtain(3);
assertSame(item, item2);
assertFalse(item2.equals(emptyItem));
}
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index 39bf7421b15e..ecea9011e704 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -61,6 +61,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -180,31 +181,6 @@ public class TransactionParcelTests {
}
@Test
- public void testWindowVisibilityChange() {
- // Write to parcel
- WindowVisibilityItem item = WindowVisibilityItem.obtain(true /* showWindow */);
- writeAndPrepareForReading(item);
-
- // Read from parcel and assert
- WindowVisibilityItem result = WindowVisibilityItem.CREATOR.createFromParcel(mParcel);
-
- assertEquals(item.hashCode(), result.hashCode());
- assertTrue(item.equals(result));
-
- // Check different value
- item = WindowVisibilityItem.obtain(false);
-
- mParcel = Parcel.obtain();
- writeAndPrepareForReading(item);
-
- // Read from parcel and assert
- result = WindowVisibilityItem.CREATOR.createFromParcel(mParcel);
-
- assertEquals(item.hashCode(), result.hashCode());
- assertTrue(item.equals(result));
- }
-
- @Test
public void testDestroy() {
DestroyActivityItem item = DestroyActivityItem.obtain(true /* finished */,
135 /* configChanges */);
@@ -299,8 +275,7 @@ public class TransactionParcelTests {
@Test
public void testStop() {
// Write to parcel
- StopActivityItem item = StopActivityItem.obtain(true /* showWindow */,
- 14 /* configChanges */);
+ StopActivityItem item = StopActivityItem.obtain(14 /* configChanges */);
writeAndPrepareForReading(item);
// Read from parcel and assert
@@ -311,14 +286,26 @@ public class TransactionParcelTests {
}
@Test
+ public void testStart() {
+ // Write to parcel
+ StartActivityItem item = StartActivityItem.obtain();
+ writeAndPrepareForReading(item);
+
+ // Read from parcel and assert
+ StartActivityItem result = StartActivityItem.CREATOR.createFromParcel(mParcel);
+
+ assertEquals(item.hashCode(), result.hashCode());
+ assertEquals(item, result);
+ }
+
+ @Test
public void testClientTransaction() {
// Write to parcel
- WindowVisibilityItem callback1 = WindowVisibilityItem.obtain(true);
+ NewIntentItem callback1 = NewIntentItem.obtain(new ArrayList<>(), true);
ActivityConfigurationChangeItem callback2 = ActivityConfigurationChangeItem.obtain(
config());
- StopActivityItem lifecycleRequest = StopActivityItem.obtain(true /* showWindow */,
- 78 /* configChanges */);
+ StopActivityItem lifecycleRequest = StopActivityItem.obtain(78 /* configChanges */);
IApplicationThread appThread = new StubAppThread();
Binder activityToken = new Binder();
@@ -340,7 +327,7 @@ public class TransactionParcelTests {
@Test
public void testClientTransactionCallbacksOnly() {
// Write to parcel
- WindowVisibilityItem callback1 = WindowVisibilityItem.obtain(true);
+ NewIntentItem callback1 = NewIntentItem.obtain(new ArrayList<>(), true);
ActivityConfigurationChangeItem callback2 = ActivityConfigurationChangeItem.obtain(
config());
@@ -363,8 +350,7 @@ public class TransactionParcelTests {
@Test
public void testClientTransactionLifecycleOnly() {
// Write to parcel
- StopActivityItem lifecycleRequest = StopActivityItem.obtain(true /* showWindow */,
- 78 /* configChanges */);
+ StopActivityItem lifecycleRequest = StopActivityItem.obtain(78 /* configChanges */);
IApplicationThread appThread = new StubAppThread();
Binder activityToken = new Binder();
diff --git a/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java b/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java
index ffc925ff82cd..f108eb8aeb0b 100644
--- a/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java
+++ b/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java
@@ -121,7 +121,12 @@ public class AndroidFutureTest {
AndroidFuture future2 = AndroidFuture.CREATOR.createFromParcel(parcel);
ExecutionException executionException =
expectThrows(ExecutionException.class, future2::get);
- assertThat(executionException.getCause()).isInstanceOf(UnsupportedOperationException.class);
+
+ Throwable cause = executionException.getCause();
+ String msg = cause.getMessage();
+ assertThat(cause).isInstanceOf(UnsupportedOperationException.class);
+ assertThat(msg).contains(getClass().getName());
+ assertThat(msg).contains("testWriteToParcel_Exception");
}
@Test
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index 66d84aaf35cd..9018320e479c 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -79,138 +79,6 @@ public class ActivityThreadClientTest {
@Test
@UiThreadTest
- public void testWindowVisibilityChange_OnCreate() throws Exception {
- try (ClientMockSession clientSession = new ClientMockSession()) {
- ActivityClientRecord r = clientSession.stubActivityRecord();
-
- clientSession.launchActivity(r);
- assertEquals(ON_CREATE, r.getLifecycleState());
-
- clientSession.changeVisibility(r, true);
- assertEquals(ON_CREATE, r.getLifecycleState());
-
- clientSession.changeVisibility(r, false);
- assertEquals(ON_CREATE, r.getLifecycleState());
- }
- }
-
- @Test
- @UiThreadTest
- public void testWindowVisibilityChange_OnCreate_Finished() throws Exception {
- try (ClientMockSession clientSession = new ClientMockSession()) {
- ActivityClientRecord r = clientSession.stubActivityRecord();
-
- Activity activity = clientSession.launchActivity(r);
- activity.finish();
- assertEquals(ON_CREATE, r.getLifecycleState());
-
- clientSession.changeVisibility(r, true);
- assertEquals(ON_CREATE, r.getLifecycleState());
-
- clientSession.changeVisibility(r, false);
- assertEquals(ON_CREATE, r.getLifecycleState());
- }
- }
-
- @Test
- @UiThreadTest
- public void testWindowVisibilityChange_OnStart() throws Exception {
- try (ClientMockSession clientSession = new ClientMockSession()) {
- ActivityClientRecord r = clientSession.stubActivityRecord();
-
- clientSession.launchActivity(r);
- clientSession.startActivity(r);
- assertEquals(ON_START, r.getLifecycleState());
-
- clientSession.changeVisibility(r, false);
- assertEquals(ON_STOP, r.getLifecycleState());
-
- clientSession.changeVisibility(r, true);
- assertEquals(ON_START, r.getLifecycleState());
- }
- }
-
- @Test
- @UiThreadTest
- public void testWindowVisibilityChange_OnStart_Finished() throws Exception {
- try (ClientMockSession clientSession = new ClientMockSession()) {
- ActivityClientRecord r = clientSession.stubActivityRecord();
-
- Activity activity = clientSession.launchActivity(r);
- clientSession.startActivity(r);
- activity.finish();
- assertEquals(ON_START, r.getLifecycleState());
-
- clientSession.changeVisibility(r, false);
- assertEquals(ON_STOP, r.getLifecycleState());
-
- clientSession.changeVisibility(r, true);
- assertEquals(ON_START, r.getLifecycleState());
- }
- }
-
- @Test
- @UiThreadTest
- public void testWindowVisibilityChange_OnResume() throws Exception {
- try (ClientMockSession clientSession = new ClientMockSession()) {
- ActivityClientRecord r = clientSession.stubActivityRecord();
-
- clientSession.launchActivity(r);
- clientSession.startActivity(r);
- clientSession.resumeActivity(r);
- assertEquals(ON_RESUME, r.getLifecycleState());
-
- clientSession.changeVisibility(r, false);
- assertEquals(ON_STOP, r.getLifecycleState());
-
- clientSession.changeVisibility(r, true);
- assertEquals(ON_START, r.getLifecycleState());
- }
- }
-
- @Test
- @UiThreadTest
- public void testWindowVisibilityChange_OnPause() throws Exception {
- try (ClientMockSession clientSession = new ClientMockSession()) {
- ActivityClientRecord r = clientSession.stubActivityRecord();
-
- clientSession.launchActivity(r);
- clientSession.startActivity(r);
- clientSession.resumeActivity(r);
- clientSession.pauseActivity(r);
- assertEquals(ON_PAUSE, r.getLifecycleState());
-
- clientSession.changeVisibility(r, false);
- assertEquals(ON_STOP, r.getLifecycleState());
-
- clientSession.changeVisibility(r, true);
- assertEquals(ON_START, r.getLifecycleState());
- }
- }
-
- @Test
- @UiThreadTest
- public void testWindowVisibilityChange_OnStop() throws Exception {
- try (ClientMockSession clientSession = new ClientMockSession()) {
- ActivityClientRecord r = clientSession.stubActivityRecord();
-
- clientSession.launchActivity(r);
- clientSession.startActivity(r);
- clientSession.resumeActivity(r);
- clientSession.pauseActivity(r);
- clientSession.stopActivity(r);
- assertEquals(ON_STOP, r.getLifecycleState());
-
- clientSession.changeVisibility(r, true);
- assertEquals(ON_START, r.getLifecycleState());
-
- clientSession.changeVisibility(r, false);
- assertEquals(ON_STOP, r.getLifecycleState());
- }
- }
-
- @Test
- @UiThreadTest
public void testLifecycleAfterFinished_OnCreate() throws Exception {
try (ClientMockSession clientSession = new ClientMockSession()) {
ActivityClientRecord r = clientSession.stubActivityRecord();
@@ -308,7 +176,7 @@ public class ActivityThreadClientTest {
}
private void startActivity(ActivityClientRecord r) {
- mThread.handleStartActivity(r, null /* pendingActions */);
+ mThread.handleStartActivity(r.token, null /* pendingActions */);
}
private void resumeActivity(ActivityClientRecord r) {
@@ -323,7 +191,7 @@ public class ActivityThreadClientTest {
}
private void stopActivity(ActivityClientRecord r) {
- mThread.handleStopActivity(r.token, false /* show */, 0 /* configChanges */,
+ mThread.handleStopActivity(r.token, 0 /* configChanges */,
new PendingTransactionActions(), false /* finalStateRequest */, "test");
}
@@ -332,10 +200,6 @@ public class ActivityThreadClientTest {
false /* getNonConfigInstance */, "test");
}
- private void changeVisibility(ActivityClientRecord r, boolean show) {
- mThread.handleWindowVisibility(r.token, show);
- }
-
private ActivityClientRecord stubActivityRecord() {
ComponentName component = new ComponentName(
InstrumentationRegistry.getInstrumentation().getContext(), TestActivity.class);
diff --git a/core/xsd/permission.xsd b/core/xsd/permission.xsd
index cc01a31224bc..543504764ee3 100644
--- a/core/xsd/permission.xsd
+++ b/core/xsd/permission.xsd
@@ -46,6 +46,7 @@
<xs:element name="hidden-api-whitelisted-app" type="hidden-api-whitelisted-app"/>
<xs:element name="allow-association" type="allow-association"/>
<xs:element name="bugreport-whitelisted" type="bugreport-whitelisted"/>
+ <xs:element name="app-data-isolation-whitelisted-app" type="app-data-isolation-whitelisted-app"/>
</xs:choice>
</xs:complexType>
</xs:element>
@@ -161,6 +162,9 @@
<xs:attribute name="target" type="xs:string"/>
<xs:attribute name="allowed" type="xs:string"/>
</xs:complexType>
+ <xs:complexType name="app-data-isolation-whitelisted-app">
+ <xs:attribute name="package" type="xs:string"/>
+ </xs:complexType>
<xs:complexType name="bugreport-whitelisted">
<xs:attribute name="package" type="xs:string"/>
</xs:complexType>
diff --git a/core/xsd/schema/current.txt b/core/xsd/schema/current.txt
index 771c1dffb909..c36c422a852d 100644
--- a/core/xsd/schema/current.txt
+++ b/core/xsd/schema/current.txt
@@ -45,6 +45,12 @@ package com.android.xml.permission.configfile {
method public void set_package(String);
}
+ public class AppDataIsolationWhitelistedApp {
+ ctor public AppDataIsolationWhitelistedApp();
+ method public String get_package();
+ method public void set_package(String);
+ }
+
public class AppLink {
ctor public AppLink();
method public String get_package();
@@ -160,6 +166,7 @@ package com.android.xml.permission.configfile {
method public java.util.List<com.android.xml.permission.configfile.AllowInPowerSaveExceptIdle> getAllowInPowerSaveExceptIdle_optional();
method public java.util.List<com.android.xml.permission.configfile.AllowInPowerSave> getAllowInPowerSave_optional();
method public java.util.List<com.android.xml.permission.configfile.AllowUnthrottledLocation> getAllowUnthrottledLocation_optional();
+ method public java.util.List<com.android.xml.permission.configfile.AppDataIsolationWhitelistedApp> getAppDataIsolationWhitelistedApp_optional();
method public java.util.List<com.android.xml.permission.configfile.AppLink> getAppLink_optional();
method public java.util.List<com.android.xml.permission.configfile.AssignPermission> getAssignPermission_optional();
method public java.util.List<com.android.xml.permission.configfile.BackupTransportWhitelistedService> getBackupTransportWhitelistedService_optional();
diff --git a/media/java/android/media/IMediaRoute2Provider.aidl b/media/java/android/media/IMediaRoute2Provider.aidl
index 02a381669893..51fa4eeaf4d8 100644
--- a/media/java/android/media/IMediaRoute2Provider.aidl
+++ b/media/java/android/media/IMediaRoute2Provider.aidl
@@ -25,7 +25,7 @@ import android.media.IMediaRoute2ProviderClient;
oneway interface IMediaRoute2Provider {
void setClient(IMediaRoute2ProviderClient client);
void requestCreateSession(String packageName, String routeId,
- String controlCategory, long requestId);
+ String routeType, long requestId);
void releaseSession(int sessionId);
void selectRoute(int sessionId, String routeId);
diff --git a/media/java/android/media/IMediaRouter2Manager.aidl b/media/java/android/media/IMediaRouter2Manager.aidl
index b7cb7059ce3d..e8af21e59cc1 100644
--- a/media/java/android/media/IMediaRouter2Manager.aidl
+++ b/media/java/android/media/IMediaRouter2Manager.aidl
@@ -24,7 +24,7 @@ import android.media.MediaRoute2Info;
*/
oneway interface IMediaRouter2Manager {
void notifyRouteSelected(String packageName, in MediaRoute2Info route);
- void notifyControlCategoriesChanged(String packageName, in List<String> categories);
+ void notifyRouteTypesChanged(String packageName, in List<String> routeTypes);
void notifyRoutesAdded(in List<MediaRoute2Info> routes);
void notifyRoutesRemoved(in List<MediaRoute2Info> routes);
void notifyRoutesChanged(in List<MediaRoute2Info> routes);
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index e5b62ff10aa6..b573f64da51d 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -22,6 +22,7 @@ import android.media.IMediaRouter2Manager;
import android.media.IMediaRouterClient;
import android.media.MediaRoute2Info;
import android.media.MediaRouterClientState;
+import android.media.RouteDiscoveryRequest;
import android.media.RouteSessionInfo;
/**
@@ -51,8 +52,8 @@ interface IMediaRouterService {
void requestUpdateVolume2(IMediaRouter2Client client, in MediaRoute2Info route, int direction);
void requestCreateSession(IMediaRouter2Client client, in MediaRoute2Info route,
- String controlCategory, int requestId);
- void setControlCategories(IMediaRouter2Client client, in List<String> categories);
+ String routeType, int requestId);
+ void setDiscoveryRequest2(IMediaRouter2Client client, in RouteDiscoveryRequest request);
void selectRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
void deselectRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
void transferToRoute(IMediaRouter2Client client, String sessionId, in MediaRoute2Info route);
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 4e6b4af56597..13640a438e7b 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -83,12 +83,14 @@ public final class MediaRoute2Info implements Parcelable {
* controlled from this object. An example of fixed playback volume is a remote player,
* playing over HDMI where the user prefers to control the volume on the HDMI sink, rather
* than attenuate at the source.
+ *
* @see #getVolumeHandling()
*/
public static final int PLAYBACK_VOLUME_FIXED = 0;
/**
* Playback information indicating the playback volume is variable and can be controlled
* from this object.
+ *
* @see #getVolumeHandling()
*/
public static final int PLAYBACK_VOLUME_VARIABLE = 1;
@@ -148,7 +150,7 @@ public final class MediaRoute2Info implements Parcelable {
@Nullable
final String mClientPackageName;
@NonNull
- final List<String> mSupportedCategories;
+ final List<String> mRouteTypes;
final int mVolume;
final int mVolumeMax;
final int mVolumeHandling;
@@ -164,7 +166,7 @@ public final class MediaRoute2Info implements Parcelable {
mConnectionState = builder.mConnectionState;
mIconUri = builder.mIconUri;
mClientPackageName = builder.mClientPackageName;
- mSupportedCategories = builder.mSupportedCategories;
+ mRouteTypes = builder.mRouteTypes;
mVolume = builder.mVolume;
mVolumeMax = builder.mVolumeMax;
mVolumeHandling = builder.mVolumeHandling;
@@ -180,7 +182,7 @@ public final class MediaRoute2Info implements Parcelable {
mConnectionState = in.readInt();
mIconUri = in.readParcelable(null);
mClientPackageName = in.readString();
- mSupportedCategories = in.createStringArrayList();
+ mRouteTypes = in.createStringArrayList();
mVolume = in.readInt();
mVolumeMax = in.readInt();
mVolumeHandling = in.readInt();
@@ -226,7 +228,7 @@ public final class MediaRoute2Info implements Parcelable {
&& (mConnectionState == other.mConnectionState)
&& Objects.equals(mIconUri, other.mIconUri)
&& Objects.equals(mClientPackageName, other.mClientPackageName)
- && Objects.equals(mSupportedCategories, other.mSupportedCategories)
+ && Objects.equals(mRouteTypes, other.mRouteTypes)
&& (mVolume == other.mVolume)
&& (mVolumeMax == other.mVolumeMax)
&& (mVolumeHandling == other.mVolumeHandling)
@@ -238,7 +240,7 @@ public final class MediaRoute2Info implements Parcelable {
@Override
public int hashCode() {
return Objects.hash(mId, mName, mDescription, mConnectionState, mIconUri,
- mSupportedCategories, mVolume, mVolumeMax, mVolumeHandling, mDeviceType);
+ mRouteTypes, mVolume, mVolumeMax, mVolumeHandling, mDeviceType);
}
/**
@@ -327,8 +329,8 @@ public final class MediaRoute2Info implements Parcelable {
* Gets the supported categories of the route.
*/
@NonNull
- public List<String> getSupportedCategories() {
- return mSupportedCategories;
+ public List<String> getRouteTypes() {
+ return mRouteTypes;
}
//TODO: once device types are confirmed, reflect those into the comment.
@@ -372,32 +374,15 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
- * Returns if the route supports the specified control category
- *
- * @param controlCategory control category to consider
- * @return true if the route supports at the category
- */
- public boolean supportsControlCategory(@NonNull String controlCategory) {
- Objects.requireNonNull(controlCategory, "control category must not be null");
- for (String supportedCategory : getSupportedCategories()) {
- if (TextUtils.equals(controlCategory, supportedCategory)) {
- return true;
- }
- }
- return false;
- }
-
- //TODO: Move this if we re-define control category / selector things.
- /**
- * Returns if the route supports at least one of the specified control categories
+ * Returns if the route contains at least one of the specified route types.
*
- * @param controlCategories the list of control categories to consider
- * @return true if the route supports at least one category
+ * @param routeTypes the list of route types to consider
+ * @return true if the route contains at least one type in the list
*/
- public boolean supportsControlCategories(@NonNull Collection<String> controlCategories) {
- Objects.requireNonNull(controlCategories, "control categories must not be null");
- for (String controlCategory : controlCategories) {
- if (supportsControlCategory(controlCategory)) {
+ public boolean containsRouteTypes(@NonNull Collection<String> routeTypes) {
+ Objects.requireNonNull(routeTypes, "routeTypes must not be null");
+ for (String routeType : routeTypes) {
+ if (getRouteTypes().contains(routeType)) {
return true;
}
}
@@ -418,7 +403,7 @@ public final class MediaRoute2Info implements Parcelable {
dest.writeInt(mConnectionState);
dest.writeParcelable(mIconUri, flags);
dest.writeString(mClientPackageName);
- dest.writeStringList(mSupportedCategories);
+ dest.writeStringList(mRouteTypes);
dest.writeInt(mVolume);
dest.writeInt(mVolumeMax);
dest.writeInt(mVolumeHandling);
@@ -456,7 +441,7 @@ public final class MediaRoute2Info implements Parcelable {
int mConnectionState;
Uri mIconUri;
String mClientPackageName;
- List<String> mSupportedCategories;
+ List<String> mRouteTypes;
int mVolume;
int mVolumeMax;
int mVolumeHandling = PLAYBACK_VOLUME_FIXED;
@@ -467,7 +452,7 @@ public final class MediaRoute2Info implements Parcelable {
public Builder(@NonNull String id, @NonNull CharSequence name) {
setId(id);
setName(name);
- mSupportedCategories = new ArrayList<>();
+ mRouteTypes = new ArrayList<>();
}
public Builder(@NonNull MediaRoute2Info routeInfo) {
@@ -484,7 +469,7 @@ public final class MediaRoute2Info implements Parcelable {
mConnectionState = routeInfo.mConnectionState;
mIconUri = routeInfo.mIconUri;
setClientPackageName(routeInfo.mClientPackageName);
- setSupportedCategories(routeInfo.mSupportedCategories);
+ setRouteTypes(routeInfo.mRouteTypes);
setVolume(routeInfo.mVolume);
setVolumeMax(routeInfo.mVolumeMax);
setVolumeHandling(routeInfo.mVolumeHandling);
@@ -589,35 +574,35 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
- * Sets the supported categories of the route.
+ * Sets the types of the route.
*/
@NonNull
- public Builder setSupportedCategories(@NonNull Collection<String> categories) {
- mSupportedCategories = new ArrayList<>();
- return addSupportedCategories(categories);
+ public Builder setRouteTypes(@NonNull Collection<String> routeTypes) {
+ mRouteTypes = new ArrayList<>();
+ return addRouteTypes(routeTypes);
}
/**
- * Adds supported categories for the route.
+ * Adds types for the route.
*/
@NonNull
- public Builder addSupportedCategories(@NonNull Collection<String> categories) {
- Objects.requireNonNull(categories, "categories must not be null");
- for (String category: categories) {
- addSupportedCategory(category);
+ public Builder addRouteTypes(@NonNull Collection<String> routeTypes) {
+ Objects.requireNonNull(routeTypes, "routeTypes must not be null");
+ for (String routeType: routeTypes) {
+ addRouteType(routeType);
}
return this;
}
/**
- * Add a supported category for the route.
+ * Add a type for the route.
*/
@NonNull
- public Builder addSupportedCategory(@NonNull String category) {
- if (TextUtils.isEmpty(category)) {
- throw new IllegalArgumentException("category must not be null or empty");
+ public Builder addRouteType(@NonNull String routeType) {
+ if (TextUtils.isEmpty(routeType)) {
+ throw new IllegalArgumentException("routeType must not be null or empty");
}
- mSupportedCategories.add(category);
+ mRouteTypes.add(routeType);
return this;
}
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index 99bd1dcde3bb..91cc44807a73 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -246,11 +246,11 @@ public abstract class MediaRoute2ProviderService extends Service {
*
* @param packageName the package name of the application that selected the route
* @param routeId the id of the route initially being connected
- * @param controlCategory the control category of the new session
+ * @param routeType the route type of the new session
* @param requestId the id of this session creation request
*/
public abstract void onCreateSession(@NonNull String packageName, @NonNull String routeId,
- @NonNull String controlCategory, long requestId);
+ @NonNull String routeType, long requestId);
/**
* Called when a session is about to be destroyed.
@@ -301,6 +301,25 @@ public abstract class MediaRoute2ProviderService extends Service {
public abstract void onTransferToRoute(int sessionId, @NonNull String routeId);
/**
+ * Called when the {@link RouteDiscoveryRequest discovery request} has changed.
+ * <p>
+ * Whenever an application registers a {@link MediaRouter2.RouteCallback callback},
+ * it also provides a discovery request to specify types of routes that it is interested in.
+ * The media router combines all of these discovery request into a single discovery request
+ * and notifies each provider.
+ * </p><p>
+ * The provider should examine {@link RouteDiscoveryRequest#getRouteTypes() route types}
+ * in the discovery request to determine what kind of routes it should try to discover
+ * and whether it should perform active or passive scans. In many cases, the provider may be
+ * able to save power by not performing any scans when the request doesn't have any matching
+ * route types.
+ * </p>
+ *
+ * @param request the new discovery request
+ */
+ public void onDiscoveryRequestChanged(@NonNull RouteDiscoveryRequest request) {}
+
+ /**
* Updates provider info and publishes routes and session info.
*/
public final void updateProviderInfo(@NonNull MediaRoute2ProviderInfo providerInfo) {
@@ -357,12 +376,12 @@ public abstract class MediaRoute2ProviderService extends Service {
@Override
public void requestCreateSession(String packageName, String routeId,
- String controlCategory, long requestId) {
+ String routeType, long requestId) {
if (!checkCallerisSystem()) {
return;
}
mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onCreateSession,
- MediaRoute2ProviderService.this, packageName, routeId, controlCategory,
+ MediaRoute2ProviderService.this, packageName, routeId, routeType,
requestId));
}
@Override
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index bddfa6930b11..dea8b045e72a 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -39,7 +39,6 @@ import com.android.internal.annotations.GuardedBy;
import java.lang.annotation.Retention;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -48,6 +47,7 @@ import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
/**
* A new Media Router
@@ -118,7 +118,7 @@ public class MediaRouter2 {
final Map<String, MediaRoute2Info> mRoutes = new HashMap<>();
@GuardedBy("sLock")
- private List<String> mControlCategories = Collections.emptyList();
+ private RouteDiscoveryRequest mDiscoveryRequest = RouteDiscoveryRequest.EMPTY;
// TODO: Make MediaRouter2 is always connected to the MediaRouterService.
@GuardedBy("sLock")
@@ -152,7 +152,6 @@ public class MediaRouter2 {
mMediaRouterService = IMediaRouterService.Stub.asInterface(
ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE));
mPackageName = mContext.getPackageName();
- //TODO: read control categories from the manifest
mHandler = new Handler(Looper.getMainLooper());
List<MediaRoute2Info> currentSystemRoutes = null;
@@ -188,24 +187,18 @@ public class MediaRouter2 {
/**
* Registers a callback to discover routes and to receive events when they change.
- */
- public void registerRouteCallback(@NonNull @CallbackExecutor Executor executor,
- @NonNull RouteCallback routeCallback) {
- registerRouteCallback(executor, routeCallback, 0);
- }
-
- /**
- * Registers a callback to discover routes and to receive events when they change.
* <p>
* If you register the same callback twice or more, it will be ignored.
* </p>
*/
public void registerRouteCallback(@NonNull @CallbackExecutor Executor executor,
- @NonNull RouteCallback routeCallback, int flags) {
+ @NonNull RouteCallback routeCallback,
+ @NonNull RouteDiscoveryRequest request) {
Objects.requireNonNull(executor, "executor must not be null");
Objects.requireNonNull(routeCallback, "callback must not be null");
+ Objects.requireNonNull(request, "request must not be null");
- RouteCallbackRecord record = new RouteCallbackRecord(executor, routeCallback, flags);
+ RouteCallbackRecord record = new RouteCallbackRecord(executor, routeCallback, request);
if (!mRouteCallbackRecords.addIfAbsent(record)) {
Log.w(TAG, "Ignoring the same callback");
return;
@@ -216,7 +209,8 @@ public class MediaRouter2 {
Client2 client = new Client2();
try {
mMediaRouterService.registerClient2(client, mPackageName);
- mMediaRouterService.setControlCategories(client, mControlCategories);
+ updateDiscoveryRequestLocked();
+ mMediaRouterService.setDiscoveryRequest2(client, mDiscoveryRequest);
mClient = client;
} catch (RemoteException ex) {
Log.e(TAG, "Unable to register media router.", ex);
@@ -238,7 +232,7 @@ public class MediaRouter2 {
Objects.requireNonNull(routeCallback, "callback must not be null");
if (!mRouteCallbackRecords.remove(
- new RouteCallbackRecord(null, routeCallback, 0))) {
+ new RouteCallbackRecord(null, routeCallback, null))) {
Log.w(TAG, "Ignoring unknown callback");
return;
}
@@ -256,30 +250,10 @@ public class MediaRouter2 {
}
}
- //TODO(b/139033746): Rename "Control Category" when it's finalized.
- /**
- * Sets the control categories of the application.
- * Routes that support at least one of the given control categories are handled
- * by the media router.
- */
- public void setControlCategories(@NonNull Collection<String> controlCategories) {
- Objects.requireNonNull(controlCategories, "control categories must not be null");
-
- List<String> newControlCategories = new ArrayList<>(controlCategories);
-
- synchronized (sRouterLock) {
- mShouldUpdateRoutes = true;
-
- // invoke callbacks due to control categories change
- handleControlCategoriesChangedLocked(newControlCategories);
- if (mClient != null) {
- try {
- mMediaRouterService.setControlCategories(mClient, mControlCategories);
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to set control categories.", ex);
- }
- }
- }
+ private void updateDiscoveryRequestLocked() {
+ mDiscoveryRequest = new RouteDiscoveryRequest.Builder(
+ mRouteCallbackRecords.stream().map(record -> record.mRequest).collect(
+ Collectors.toList())).build();
}
/**
@@ -287,8 +261,8 @@ public class MediaRouter2 {
* known to the media router.
* Please note that the list can be changed before callbacks are invoked.
*
- * @return the list of routes that support at least one of the control categories set by
- * the application
+ * @return the list of routes that contains at least one of the route types in discovery
+ * requests registered by the application
*/
@NonNull
public List<MediaRoute2Info> getRoutes() {
@@ -298,7 +272,7 @@ public class MediaRouter2 {
List<MediaRoute2Info> filteredRoutes = new ArrayList<>();
for (MediaRoute2Info route : mRoutes.values()) {
- if (route.supportsControlCategories(mControlCategories)) {
+ if (route.containsRouteTypes(mDiscoveryRequest.getRouteTypes())) {
filteredRoutes.add(route);
}
}
@@ -350,26 +324,26 @@ public class MediaRouter2 {
* Requests the media route provider service to create a session with the given route.
*
* @param route the route you want to create a session with.
- * @param controlCategory the control category of the session. Should not be empty
+ * @param routeType the route type of the session. Should not be empty
*
* @see SessionCallback#onSessionCreated
* @see SessionCallback#onSessionCreationFailed
*/
@NonNull
public void requestCreateSession(@NonNull MediaRoute2Info route,
- @NonNull String controlCategory) {
+ @NonNull String routeType) {
Objects.requireNonNull(route, "route must not be null");
- if (TextUtils.isEmpty(controlCategory)) {
- throw new IllegalArgumentException("controlCategory must not be empty");
+ if (TextUtils.isEmpty(routeType)) {
+ throw new IllegalArgumentException("routeType must not be empty");
}
// TODO: Check the given route exists
- // TODO: Check the route supports the given controlCategory
+ // TODO: Check the route supports the given routeType
final int requestId;
requestId = mSessionCreationRequestCnt.getAndIncrement();
SessionCreationRequest request = new SessionCreationRequest(
- requestId, route, controlCategory);
+ requestId, route, routeType);
mSessionCreationRequests.add(request);
Client2 client;
@@ -379,7 +353,7 @@ public class MediaRouter2 {
if (client != null) {
try {
mMediaRouterService.requestCreateSession(
- client, route, controlCategory, requestId);
+ client, route, routeType, requestId);
} catch (RemoteException ex) {
Log.e(TAG, "Unable to request to create session.", ex);
mHandler.sendMessage(obtainMessage(MediaRouter2::createControllerOnHandler,
@@ -461,36 +435,6 @@ public class MediaRouter2 {
}
}
- private void handleControlCategoriesChangedLocked(List<String> newControlCategories) {
- List<MediaRoute2Info> addedRoutes = new ArrayList<>();
- List<MediaRoute2Info> removedRoutes = new ArrayList<>();
-
- List<String> prevControlCategories = mControlCategories;
- mControlCategories = newControlCategories;
-
- for (MediaRoute2Info route : mRoutes.values()) {
- boolean preSupported = route.supportsControlCategories(prevControlCategories);
- boolean postSupported = route.supportsControlCategories(newControlCategories);
- if (preSupported == postSupported) {
- continue;
- }
- if (preSupported) {
- removedRoutes.add(route);
- } else {
- addedRoutes.add(route);
- }
- }
-
- if (removedRoutes.size() > 0) {
- mHandler.sendMessage(obtainMessage(MediaRouter2::notifyRoutesRemoved,
- MediaRouter2.this, removedRoutes));
- }
- if (addedRoutes.size() > 0) {
- mHandler.sendMessage(obtainMessage(MediaRouter2::notifyRoutesAdded,
- MediaRouter2.this, addedRoutes));
- }
- }
-
void addRoutesOnHandler(List<MediaRoute2Info> routes) {
// TODO: When onRoutesAdded is first called,
// 1) clear mRoutes before adding the routes
@@ -500,7 +444,7 @@ public class MediaRouter2 {
synchronized (sRouterLock) {
for (MediaRoute2Info route : routes) {
mRoutes.put(route.getId(), route);
- if (route.supportsControlCategories(mControlCategories)) {
+ if (route.containsRouteTypes(mDiscoveryRequest.getRouteTypes())) {
addedRoutes.add(route);
}
}
@@ -516,7 +460,7 @@ public class MediaRouter2 {
synchronized (sRouterLock) {
for (MediaRoute2Info route : routes) {
mRoutes.remove(route.getId());
- if (route.supportsControlCategories(mControlCategories)) {
+ if (route.containsRouteTypes(mDiscoveryRequest.getRouteTypes())) {
removedRoutes.add(route);
}
}
@@ -532,7 +476,7 @@ public class MediaRouter2 {
synchronized (sRouterLock) {
for (MediaRoute2Info route : routes) {
mRoutes.put(route.getId(), route);
- if (route.supportsControlCategories(mControlCategories)) {
+ if (route.containsRouteTypes(mDiscoveryRequest.getRouteTypes())) {
changedRoutes.add(route);
}
}
@@ -562,27 +506,27 @@ public class MediaRouter2 {
mSessionCreationRequests.remove(matchingRequest);
MediaRoute2Info requestedRoute = matchingRequest.mRoute;
- String requestedControlCategory = matchingRequest.mControlCategory;
+ String requestedRouteType = matchingRequest.mRouteType;
if (sessionInfo == null) {
// TODO: We may need to distinguish between failure and rejection.
// One way can be introducing 'reason'.
- notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+ notifySessionCreationFailed(requestedRoute, requestedRouteType);
return;
- } else if (!TextUtils.equals(requestedControlCategory,
- sessionInfo.getControlCategory())) {
- Log.w(TAG, "The session has different control category from what we requested. "
- + "(requested=" + requestedControlCategory
- + ", actual=" + sessionInfo.getControlCategory()
+ } else if (!TextUtils.equals(requestedRouteType,
+ sessionInfo.getRouteType())) {
+ Log.w(TAG, "The session has different route type from what we requested. "
+ + "(requested=" + requestedRouteType
+ + ", actual=" + sessionInfo.getRouteType()
+ ")");
- notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+ notifySessionCreationFailed(requestedRoute, requestedRouteType);
return;
} else if (!sessionInfo.getSelectedRoutes().contains(requestedRoute.getId())) {
Log.w(TAG, "The session does not contain the requested route. "
+ "(requestedRouteId=" + requestedRoute.getId()
+ ", actualRoutes=" + sessionInfo.getSelectedRoutes()
+ ")");
- notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+ notifySessionCreationFailed(requestedRoute, requestedRouteType);
return;
} else if (!TextUtils.equals(requestedRoute.getProviderId(),
sessionInfo.getProviderId())) {
@@ -590,7 +534,7 @@ public class MediaRouter2 {
+ "(requested route's providerId=" + requestedRoute.getProviderId()
+ ", actual providerId=" + sessionInfo.getProviderId()
+ ")");
- notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+ notifySessionCreationFailed(requestedRoute, requestedRouteType);
return;
}
}
@@ -666,24 +610,41 @@ public class MediaRouter2 {
notifyControllerReleased(matchingController);
}
+ private List<MediaRoute2Info> filterRoutes(List<MediaRoute2Info> routes,
+ RouteDiscoveryRequest discoveryRequest) {
+ return routes.stream()
+ .filter(
+ route -> route.containsRouteTypes(discoveryRequest.getRouteTypes()))
+ .collect(Collectors.toList());
+ }
+
private void notifyRoutesAdded(List<MediaRoute2Info> routes) {
for (RouteCallbackRecord record: mRouteCallbackRecords) {
- record.mExecutor.execute(
- () -> record.mRouteCallback.onRoutesAdded(routes));
+ List<MediaRoute2Info> filteredRoutes = filterRoutes(routes, record.mRequest);
+ if (!filteredRoutes.isEmpty()) {
+ record.mExecutor.execute(
+ () -> record.mRouteCallback.onRoutesAdded(filteredRoutes));
+ }
}
}
private void notifyRoutesRemoved(List<MediaRoute2Info> routes) {
for (RouteCallbackRecord record: mRouteCallbackRecords) {
- record.mExecutor.execute(
- () -> record.mRouteCallback.onRoutesRemoved(routes));
+ List<MediaRoute2Info> filteredRoutes = filterRoutes(routes, record.mRequest);
+ if (!filteredRoutes.isEmpty()) {
+ record.mExecutor.execute(
+ () -> record.mRouteCallback.onRoutesRemoved(filteredRoutes));
+ }
}
}
private void notifyRoutesChanged(List<MediaRoute2Info> routes) {
for (RouteCallbackRecord record: mRouteCallbackRecords) {
- record.mExecutor.execute(
- () -> record.mRouteCallback.onRoutesChanged(routes));
+ List<MediaRoute2Info> filteredRoutes = filterRoutes(routes, record.mRequest);
+ if (!filteredRoutes.isEmpty()) {
+ record.mExecutor.execute(
+ () -> record.mRouteCallback.onRoutesChanged(filteredRoutes));
+ }
}
}
@@ -694,10 +655,10 @@ public class MediaRouter2 {
}
}
- private void notifySessionCreationFailed(MediaRoute2Info route, String controlCategory) {
+ private void notifySessionCreationFailed(MediaRoute2Info route, String routeType) {
for (SessionCallbackRecord record: mSessionCallbackRecords) {
record.mExecutor.execute(
- () -> record.mSessionCallback.onSessionCreationFailed(route, controlCategory));
+ () -> record.mSessionCallback.onSessionCreationFailed(route, routeType));
}
}
@@ -764,10 +725,10 @@ public class MediaRouter2 {
* Called when the session creation request failed.
*
* @param requestedRoute the route info which was used for the request
- * @param requestedControlCategory the control category which was used for the request
+ * @param requestedRouteType the route type which was used for the request
*/
public void onSessionCreationFailed(@NonNull MediaRoute2Info requestedRoute,
- @NonNull String requestedControlCategory) {}
+ @NonNull String requestedRouteType) {}
/**
* Called when the session info has changed.
@@ -840,12 +801,12 @@ public class MediaRouter2 {
}
/**
- * @return the category of routes that the session includes.
+ * @return the type of routes that the session includes.
*/
@NonNull
- public String getControlCategory() {
+ public String getRouteType() {
synchronized (mControllerLock) {
- return mSessionInfo.getControlCategory();
+ return mSessionInfo.getRouteType();
}
}
@@ -1104,11 +1065,11 @@ public class MediaRouter2 {
// TODO: This method uses two locks (mLock outside, sLock inside).
// Check if there is any possiblity of deadlock.
private List<MediaRoute2Info> getRoutesWithIdsLocked(List<String> routeIds) {
+
List<MediaRoute2Info> routes = new ArrayList<>();
synchronized (sRouterLock) {
for (String routeId : routeIds) {
- MediaRoute2Info route = mRoutes.get(
- MediaRoute2Info.toUniqueId(mSessionInfo.mProviderId, routeId));
+ MediaRoute2Info route = mRoutes.get(routeId);
if (route != null) {
routes.add(route);
}
@@ -1121,13 +1082,13 @@ public class MediaRouter2 {
final class RouteCallbackRecord {
public final Executor mExecutor;
public final RouteCallback mRouteCallback;
- public final int mFlags;
+ public final RouteDiscoveryRequest mRequest;
RouteCallbackRecord(@Nullable Executor executor, @NonNull RouteCallback routeCallback,
- int flags) {
+ @Nullable RouteDiscoveryRequest request) {
mRouteCallback = routeCallback;
mExecutor = executor;
- mFlags = flags;
+ mRequest = request;
}
@Override
@@ -1176,13 +1137,13 @@ public class MediaRouter2 {
final class SessionCreationRequest {
public final MediaRoute2Info mRoute;
- public final String mControlCategory;
+ public final String mRouteType;
public final int mRequestId;
SessionCreationRequest(int requestId, @NonNull MediaRoute2Info route,
- @NonNull String controlCategory) {
+ @NonNull String routeType) {
mRoute = route;
- mControlCategory = controlCategory;
+ mRouteType = routeType;
mRequestId = requestId;
}
}
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 3cbbea1f3c07..1e6ec51442d6 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -65,7 +65,7 @@ public class MediaRouter2Manager {
@GuardedBy("mRoutesLock")
private final Map<String, MediaRoute2Info> mRoutes = new HashMap<>();
@NonNull
- final ConcurrentMap<String, List<String>> mControlCategoryMap = new ConcurrentHashMap<>();
+ final ConcurrentMap<String, List<String>> mRouteTypeMap = new ConcurrentHashMap<>();
private AtomicInteger mNextRequestId = new AtomicInteger(1);
@@ -144,7 +144,7 @@ public class MediaRouter2Manager {
}
//TODO: clear mRoutes?
mClient = null;
- mControlCategoryMap.clear();
+ mRouteTypeMap.clear();
}
}
}
@@ -160,14 +160,14 @@ public class MediaRouter2Manager {
public List<MediaRoute2Info> getAvailableRoutes(@NonNull String packageName) {
Objects.requireNonNull(packageName, "packageName must not be null");
- List<String> controlCategories = mControlCategoryMap.get(packageName);
- if (controlCategories == null) {
+ List<String> routeTypes = mRouteTypeMap.get(packageName);
+ if (routeTypes == null) {
return Collections.emptyList();
}
List<MediaRoute2Info> routes = new ArrayList<>();
synchronized (mRoutesLock) {
for (MediaRoute2Info route : mRoutes.values()) {
- if (route.supportsControlCategories(controlCategories)) {
+ if (route.containsRouteTypes(routeTypes)) {
routes.add(route);
}
}
@@ -352,15 +352,15 @@ public class MediaRouter2Manager {
}
}
- void updateControlCategories(String packageName, List<String> categories) {
- List<String> prevCategories = mControlCategoryMap.put(packageName, categories);
- if ((prevCategories == null && categories.size() == 0)
- || Objects.equals(categories, prevCategories)) {
+ void updateRouteTypes(String packageName, List<String> routeTypes) {
+ List<String> prevTypes = mRouteTypeMap.put(packageName, routeTypes);
+ if ((prevTypes == null && routeTypes.size() == 0)
+ || Objects.equals(routeTypes, prevTypes)) {
return;
}
for (CallbackRecord record : mCallbackRecords) {
record.mExecutor.execute(
- () -> record.mCallback.onControlCategoriesChanged(packageName, categories));
+ () -> record.mCallback.onControlCategoriesChanged(packageName, routeTypes));
}
}
@@ -398,13 +398,13 @@ public class MediaRouter2Manager {
/**
- * Called when the control categories of an app is changed.
+ * Called when the route types of an app is changed.
*
* @param packageName the package name of the application
- * @param controlCategories the list of control categories set by an application.
+ * @param routeTypes the list of route types set by an application.
*/
public void onControlCategoriesChanged(@NonNull String packageName,
- @NonNull List<String> controlCategories) {}
+ @NonNull List<String> routeTypes) {}
}
final class CallbackRecord {
@@ -440,10 +440,9 @@ public class MediaRouter2Manager {
MediaRouter2Manager.this, packageName, route));
}
- @Override
- public void notifyControlCategoriesChanged(String packageName, List<String> categories) {
- mHandler.sendMessage(obtainMessage(MediaRouter2Manager::updateControlCategories,
- MediaRouter2Manager.this, packageName, categories));
+ public void notifyRouteTypesChanged(String packageName, List<String> routeTypes) {
+ mHandler.sendMessage(obtainMessage(MediaRouter2Manager::updateRouteTypes,
+ MediaRouter2Manager.this, packageName, routeTypes));
}
@Override
diff --git a/media/java/android/media/MediaScannerConnection.java b/media/java/android/media/MediaScannerConnection.java
index 40e90731f2a2..05fa511fc81a 100644
--- a/media/java/android/media/MediaScannerConnection.java
+++ b/media/java/android/media/MediaScannerConnection.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
diff --git a/media/java/android/media/RouteDiscoveryRequest.aidl b/media/java/android/media/RouteDiscoveryRequest.aidl
new file mode 100644
index 000000000000..744f6569325d
--- /dev/null
+++ b/media/java/android/media/RouteDiscoveryRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+parcelable RouteDiscoveryRequest;
diff --git a/media/java/android/media/RouteDiscoveryRequest.java b/media/java/android/media/RouteDiscoveryRequest.java
new file mode 100644
index 000000000000..88b31fb30ffc
--- /dev/null
+++ b/media/java/android/media/RouteDiscoveryRequest.java
@@ -0,0 +1,200 @@
+/*
+ * 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.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+
+/**
+ * @hide
+ */
+public final class RouteDiscoveryRequest implements Parcelable {
+ @NonNull
+ public static final Creator<RouteDiscoveryRequest> CREATOR =
+ new Creator<RouteDiscoveryRequest>() {
+ @Override
+ public RouteDiscoveryRequest createFromParcel(Parcel in) {
+ return new RouteDiscoveryRequest(in);
+ }
+
+ @Override
+ public RouteDiscoveryRequest[] newArray(int size) {
+ return new RouteDiscoveryRequest[size];
+ }
+ };
+
+ @NonNull
+ private final List<String> mRouteTypes;
+ private final boolean mActiveScan;
+ @Nullable
+ private final Bundle mExtras;
+
+ /**
+ * @hide
+ */
+ public static final RouteDiscoveryRequest EMPTY =
+ new Builder(Collections.emptyList(), false).build();
+
+ RouteDiscoveryRequest(@NonNull Builder builder) {
+ mRouteTypes = builder.mRouteTypes;
+ mActiveScan = builder.mActiveScan;
+ mExtras = builder.mExtras;
+ }
+
+ RouteDiscoveryRequest(@NonNull Parcel in) {
+ mRouteTypes = in.createStringArrayList();
+ mActiveScan = in.readBoolean();
+ mExtras = in.readBundle();
+ }
+
+ @NonNull
+ public List<String> getRouteTypes() {
+ return mRouteTypes;
+ }
+
+ public boolean isActiveScan() {
+ return mActiveScan;
+ }
+
+ /**
+ * @hide
+ */
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeStringList(mRouteTypes);
+ dest.writeBoolean(mActiveScan);
+ dest.writeBundle(mExtras);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder()
+ .append("RouteDiscoveryRequest{ ")
+ .append("routeTypes={")
+ .append(String.join(", ", mRouteTypes))
+ .append("}")
+ .append(", activeScan=")
+ .append(mActiveScan)
+ .append(" }");
+
+ return result.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof RouteDiscoveryRequest)) {
+ return false;
+ }
+ RouteDiscoveryRequest other = (RouteDiscoveryRequest) o;
+ return Objects.equals(mRouteTypes, other.mRouteTypes)
+ && mActiveScan == other.mActiveScan;
+ }
+
+ /**
+ * Builder for {@link RouteDiscoveryRequest}.
+ */
+ public static final class Builder {
+ List<String> mRouteTypes;
+ boolean mActiveScan;
+ Bundle mExtras;
+
+ public Builder(@NonNull List<String> routeTypes, boolean activeScan) {
+ mRouteTypes = new ArrayList<>(
+ Objects.requireNonNull(routeTypes, "routeTypes must not be null"));
+ mActiveScan = activeScan;
+ }
+
+ public Builder(@NonNull RouteDiscoveryRequest request) {
+ Objects.requireNonNull(request, "request must not be null");
+
+ mRouteTypes = request.getRouteTypes();
+ mActiveScan = request.isActiveScan();
+ mExtras = request.getExtras();
+ }
+
+ /**
+ * A constructor to combine all of the requests into a single request.
+ * It ignores extras of requests.
+ */
+ Builder(@NonNull Collection<RouteDiscoveryRequest> requests) {
+ Set<String> routeTypeSet = new HashSet<>();
+ mActiveScan = false;
+ for (RouteDiscoveryRequest request : requests) {
+ routeTypeSet.addAll(request.mRouteTypes);
+ mActiveScan |= request.mActiveScan;
+ }
+ mRouteTypes = new ArrayList<>(routeTypeSet);
+ }
+
+ /**
+ * Sets route types to discover.
+ */
+ public Builder setRouteTypes(@NonNull List<String> routeTypes) {
+ mRouteTypes = new ArrayList<>(
+ Objects.requireNonNull(routeTypes, "routeTypes must not be null"));
+ return this;
+ }
+
+ /**
+ * Sets if active scanning should be performed.
+ */
+ public Builder setActiveScan(boolean activeScan) {
+ mActiveScan = activeScan;
+ return this;
+ }
+
+ /**
+ * Sets the extras of the route.
+ * @hide
+ */
+ public Builder setExtras(@Nullable Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ /**
+ * Builds the {@link RouteDiscoveryRequest}.
+ */
+ public RouteDiscoveryRequest build() {
+ return new RouteDiscoveryRequest(this);
+ }
+ }
+}
diff --git a/media/java/android/media/RouteSessionInfo.java b/media/java/android/media/RouteSessionInfo.java
index 4a9298ac64be..cb1688600fac 100644
--- a/media/java/android/media/RouteSessionInfo.java
+++ b/media/java/android/media/RouteSessionInfo.java
@@ -48,7 +48,7 @@ public class RouteSessionInfo implements Parcelable {
final int mSessionId;
final String mPackageName;
- final String mControlCategory;
+ final String mRouteType;
@Nullable
final String mProviderId;
final List<String> mSelectedRoutes;
@@ -63,7 +63,7 @@ public class RouteSessionInfo implements Parcelable {
mSessionId = builder.mSessionId;
mPackageName = builder.mPackageName;
- mControlCategory = builder.mControlCategory;
+ mRouteType = builder.mRouteType;
mProviderId = builder.mProviderId;
mSelectedRoutes = Collections.unmodifiableList(builder.mSelectedRoutes);
@@ -79,7 +79,7 @@ public class RouteSessionInfo implements Parcelable {
mSessionId = src.readInt();
mPackageName = ensureString(src.readString());
- mControlCategory = ensureString(src.readString());
+ mRouteType = ensureString(src.readString());
mProviderId = src.readString();
mSelectedRoutes = ensureList(src.createStringArrayList());
@@ -154,7 +154,7 @@ public class RouteSessionInfo implements Parcelable {
*/
public boolean isValid() {
return !TextUtils.isEmpty(mPackageName)
- && !TextUtils.isEmpty(mControlCategory)
+ && !TextUtils.isEmpty(mRouteType)
&& mSelectedRoutes.size() > 0;
}
@@ -175,12 +175,12 @@ public class RouteSessionInfo implements Parcelable {
}
/**
- * Gets the control category of the session.
- * Routes that don't support the category can't be added to the session.
+ * Gets the route type of the session.
+ * Routes that don't have the type can't be added to the session.
*/
@NonNull
- public String getControlCategory() {
- return mControlCategory;
+ public String getRouteType() {
+ return mRouteType;
}
/**
@@ -254,7 +254,7 @@ public class RouteSessionInfo implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mSessionId);
dest.writeString(mPackageName);
- dest.writeString(mControlCategory);
+ dest.writeString(mRouteType);
dest.writeString(mProviderId);
dest.writeStringList(mSelectedRoutes);
dest.writeStringList(mSelectableRoutes);
@@ -268,7 +268,7 @@ public class RouteSessionInfo implements Parcelable {
StringBuilder result = new StringBuilder()
.append("RouteSessionInfo{ ")
.append("sessionId=").append(mSessionId)
- .append(", controlCategory=").append(mControlCategory)
+ .append(", routeType=").append(mRouteType)
.append(", selectedRoutes={")
.append(String.join(",", mSelectedRoutes))
.append("}")
@@ -291,7 +291,7 @@ public class RouteSessionInfo implements Parcelable {
public static final class Builder {
final String mPackageName;
final int mSessionId;
- final String mControlCategory;
+ final String mRouteType;
String mProviderId;
final List<String> mSelectedRoutes;
final List<String> mSelectableRoutes;
@@ -300,11 +300,11 @@ public class RouteSessionInfo implements Parcelable {
Bundle mControlHints;
public Builder(int sessionId, @NonNull String packageName,
- @NonNull String controlCategory) {
+ @NonNull String routeType) {
mSessionId = sessionId;
mPackageName = Objects.requireNonNull(packageName, "packageName must not be null");
- mControlCategory = Objects.requireNonNull(controlCategory,
- "controlCategory must not be null");
+ mRouteType = Objects.requireNonNull(routeType,
+ "routeType must not be null");
mSelectedRoutes = new ArrayList<>();
mSelectableRoutes = new ArrayList<>();
@@ -315,7 +315,7 @@ public class RouteSessionInfo implements Parcelable {
public Builder(RouteSessionInfo sessionInfo) {
mSessionId = sessionInfo.mSessionId;
mPackageName = sessionInfo.mPackageName;
- mControlCategory = sessionInfo.mControlCategory;
+ mRouteType = sessionInfo.mRouteType;
mProviderId = sessionInfo.mProviderId;
mSelectedRoutes = new ArrayList<>(sessionInfo.mSelectedRoutes);
diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
index 56e5566df29c..77596a5de815 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerDetector.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -22,7 +22,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.SoundTrigger;
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index 61b3e76e7cee..1c38301c7935 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -23,7 +23,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.hardware.soundtrigger.ModelParams;
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 1b9cac0c8c99..377b2bc19c6b 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -20,7 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.StringRes;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 5c11ed9bb7b4..7fbb3376d5fb 100755
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -22,9 +22,9 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.Service;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
diff --git a/media/java/android/media/tv/TvTrackInfo.java b/media/java/android/media/tv/TvTrackInfo.java
index c17beba2b9d1..4318a0ae7d06 100644
--- a/media/java/android/media/tv/TvTrackInfo.java
+++ b/media/java/android/media/tv/TvTrackInfo.java
@@ -63,6 +63,7 @@ public final class TvTrackInfo implements Parcelable {
private final int mAudioSampleRate;
private final boolean mAudioDescription;
private final boolean mHardOfHearing;
+ private final boolean mSpokenSubtitle;
private final int mVideoWidth;
private final int mVideoHeight;
private final float mVideoFrameRate;
@@ -73,8 +74,9 @@ public final class TvTrackInfo implements Parcelable {
private TvTrackInfo(int type, String id, String language, CharSequence description,
boolean encrypted, int audioChannelCount, int audioSampleRate, boolean audioDescription,
- boolean hardOfHearing, int videoWidth, int videoHeight, float videoFrameRate,
- float videoPixelAspectRatio, byte videoActiveFormatDescription, Bundle extra) {
+ boolean hardOfHearing, boolean spokenSubtitle, int videoWidth, int videoHeight,
+ float videoFrameRate, float videoPixelAspectRatio, byte videoActiveFormatDescription,
+ Bundle extra) {
mType = type;
mId = id;
mLanguage = language;
@@ -84,6 +86,7 @@ public final class TvTrackInfo implements Parcelable {
mAudioSampleRate = audioSampleRate;
mAudioDescription = audioDescription;
mHardOfHearing = hardOfHearing;
+ mSpokenSubtitle = spokenSubtitle;
mVideoWidth = videoWidth;
mVideoHeight = videoHeight;
mVideoFrameRate = videoFrameRate;
@@ -102,6 +105,7 @@ public final class TvTrackInfo implements Parcelable {
mAudioSampleRate = in.readInt();
mAudioDescription = in.readInt() != 0;
mHardOfHearing = in.readInt() != 0;
+ mSpokenSubtitle = in.readInt() != 0;
mVideoWidth = in.readInt();
mVideoHeight = in.readInt();
mVideoFrameRate = in.readFloat();
@@ -212,6 +216,22 @@ public final class TvTrackInfo implements Parcelable {
}
/**
+ * Returns {@code true} if the track is a spoken subtitle for people with visual impairment,
+ * {@code false} otherwise. Valid only for {@link #TYPE_AUDIO} tracks.
+ *
+ * <p>For example of broadcast, spoken subtitle information may be referred to broadcast
+ * standard (e.g. Supplementary Audio Language Descriptor of ETSI EN 300 468).
+ *
+ * @throws IllegalStateException if not called on an audio track
+ */
+ public boolean isSpokenSubtitle() {
+ if (mType != TYPE_AUDIO) {
+ throw new IllegalStateException("Not an audio track");
+ }
+ return mSpokenSubtitle;
+ }
+
+ /**
* Returns the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
* tracks.
*
@@ -308,6 +328,7 @@ public final class TvTrackInfo implements Parcelable {
dest.writeInt(mAudioSampleRate);
dest.writeInt(mAudioDescription ? 1 : 0);
dest.writeInt(mHardOfHearing ? 1 : 0);
+ dest.writeInt(mSpokenSubtitle ? 1 : 0);
dest.writeInt(mVideoWidth);
dest.writeInt(mVideoHeight);
dest.writeFloat(mVideoFrameRate);
@@ -331,6 +352,7 @@ public final class TvTrackInfo implements Parcelable {
if (!TextUtils.equals(mId, obj.mId) || mType != obj.mType
|| !TextUtils.equals(mLanguage, obj.mLanguage)
|| !TextUtils.equals(mDescription, obj.mDescription)
+ || mEncrypted != obj.mEncrypted
|| !Objects.equals(mExtra, obj.mExtra)) {
return false;
}
@@ -340,7 +362,8 @@ public final class TvTrackInfo implements Parcelable {
return mAudioChannelCount == obj.mAudioChannelCount
&& mAudioSampleRate == obj.mAudioSampleRate
&& mAudioDescription == obj.mAudioDescription
- && mHardOfHearing == obj.mHardOfHearing;
+ && mHardOfHearing == obj.mHardOfHearing
+ && mSpokenSubtitle == obj.mSpokenSubtitle;
case TYPE_VIDEO:
return mVideoWidth == obj.mVideoWidth
@@ -387,6 +410,7 @@ public final class TvTrackInfo implements Parcelable {
private int mAudioSampleRate;
private boolean mAudioDescription;
private boolean mHardOfHearing;
+ private boolean mSpokenSubtitle;
private int mVideoWidth;
private int mVideoHeight;
private float mVideoFrameRate;
@@ -521,6 +545,25 @@ public final class TvTrackInfo implements Parcelable {
}
/**
+ * Sets the spoken subtitle attribute of the audio. Valid only for {@link #TYPE_AUDIO}
+ * tracks.
+ *
+ * <p>For example of broadcast, spoken subtitle information may be referred to broadcast
+ * standard (e.g. Supplementary Audio Language Descriptor of ETSI EN 300 468).
+ *
+ * @param spokenSubtitle The spoken subtitle attribute of the audio.
+ * @throws IllegalStateException if not called on an audio track
+ */
+ @NonNull
+ public Builder setSpokenSubtitle(boolean spokenSubtitle) {
+ if (mType != TYPE_AUDIO) {
+ throw new IllegalStateException("Not an audio track");
+ }
+ mSpokenSubtitle = spokenSubtitle;
+ return this;
+ }
+
+ /**
* Sets the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
* tracks.
*
@@ -623,8 +666,8 @@ public final class TvTrackInfo implements Parcelable {
public TvTrackInfo build() {
return new TvTrackInfo(mType, mId, mLanguage, mDescription, mEncrypted,
mAudioChannelCount, mAudioSampleRate, mAudioDescription, mHardOfHearing,
- mVideoWidth, mVideoHeight, mVideoFrameRate, mVideoPixelAspectRatio,
- mVideoActiveFormatDescription, mExtra);
+ mSpokenSubtitle, mVideoWidth, mVideoHeight, mVideoFrameRate,
+ mVideoPixelAspectRatio, mVideoActiveFormatDescription, mExtra);
}
}
}
diff --git a/media/java/android/media/tv/tuner/FrontendCapabilities.java b/media/java/android/media/tv/tuner/FrontendCapabilities.java
deleted file mode 100644
index fcfd7c8c8639..000000000000
--- a/media/java/android/media/tv/tuner/FrontendCapabilities.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.tv.tuner;
-
-/**
- * Frontend Capabilities.
- * @hide
- */
-public class FrontendCapabilities {
- /** Analog Capabilities. */
- public class Analog extends FrontendCapabilities {
- private final int mTypeCap;
- private final int mSifStandardCap;
-
- Analog(int typeCap, int sifStandardCap) {
- mTypeCap = typeCap;
- mSifStandardCap = sifStandardCap;
- }
- /**
- * Gets type capability.
- */
- public int getTypeCapability() {
- return mTypeCap;
- }
- /** Gets SIF standard capability. */
- public int getSifStandardCapability() {
- return mSifStandardCap;
- }
- }
-
- /** ATSC Capabilities. */
- public class Atsc extends FrontendCapabilities {
- private final int mModulationCap;
-
- Atsc(int modulationCap) {
- mModulationCap = modulationCap;
- }
- /** Gets modulation capability. */
- public int getModulationCapability() {
- return mModulationCap;
- }
- }
-
- /** ATSC-3 Capabilities. */
- public class Atsc3 extends FrontendCapabilities {
- private final int mBandwidthCap;
- private final int mModulationCap;
- private final int mTimeInterleaveModeCap;
- private final int mCodeRateCap;
- private final int mFecCap;
- private final int mDemodOutputFormatCap;
-
- Atsc3(int bandwidthCap, int modulationCap, int timeInterleaveModeCap, int codeRateCap,
- int fecCap, int demodOutputFormatCap) {
- mBandwidthCap = bandwidthCap;
- mModulationCap = modulationCap;
- mTimeInterleaveModeCap = timeInterleaveModeCap;
- mCodeRateCap = codeRateCap;
- mFecCap = fecCap;
- mDemodOutputFormatCap = demodOutputFormatCap;
- }
-
- /** Gets bandwidth capability. */
- public int getBandwidthCapability() {
- return mBandwidthCap;
- }
- /** Gets modulation capability. */
- public int getModulationCapability() {
- return mModulationCap;
- }
- /** Gets time interleave mod capability. */
- public int getTimeInterleaveModeCapability() {
- return mTimeInterleaveModeCap;
- }
- /** Gets code rate capability. */
- public int getCodeRateCapability() {
- return mCodeRateCap;
- }
- /** Gets FEC capability. */
- public int getFecCapability() {
- return mFecCap;
- }
- /** Gets demodulator output format capability. */
- public int getDemodOutputFormatCapability() {
- return mDemodOutputFormatCap;
- }
- }
-
- /** DVBS Capabilities. */
- public class Dvbs extends FrontendCapabilities {
- private final int mModulationCap;
- private final long mInnerFecCap;
- private final int mStandard;
-
- Dvbs(int modulationCap, long innerFecCap, int standard) {
- mModulationCap = modulationCap;
- mInnerFecCap = innerFecCap;
- mStandard = standard;
- }
-
- /** Gets modulation capability. */
- public int getModulationCapability() {
- return mModulationCap;
- }
- /** Gets inner FEC capability. */
- public long getInnerFecCapability() {
- return mInnerFecCap;
- }
- /** Gets DVBS standard capability. */
- public int getStandardCapability() {
- return mStandard;
- }
- }
-
- /** DVBC Capabilities. */
- public class Dvbc extends FrontendCapabilities {
- private final int mModulationCap;
- private final int mFecCap;
- private final int mAnnexCap;
-
- Dvbc(int modulationCap, int fecCap, int annexCap) {
- mModulationCap = modulationCap;
- mFecCap = fecCap;
- mAnnexCap = annexCap;
- }
-
- /** Gets modulation capability. */
- public int getModulationCapability() {
- return mModulationCap;
- }
- /** Gets FEC capability. */
- public int getFecCapability() {
- return mFecCap;
- }
- /** Gets annex capability. */
- public int getAnnexCapability() {
- return mAnnexCap;
- }
- }
-
- /** DVBT Capabilities. */
- public class Dvbt extends FrontendCapabilities {
- private final int mTransmissionModeCap;
- private final int mBandwidthCap;
- private final int mConstellationCap;
- private final int mCoderateCap;
- private final int mHierarchyCap;
- private final int mGuardIntervalCap;
- private final boolean mIsT2Supported;
- private final boolean mIsMisoSupported;
-
- Dvbt(int transmissionModeCap, int bandwidthCap, int constellationCap, int coderateCap,
- int hierarchyCap, int guardIntervalCap, boolean isT2Supported,
- boolean isMisoSupported) {
- mTransmissionModeCap = transmissionModeCap;
- mBandwidthCap = bandwidthCap;
- mConstellationCap = constellationCap;
- mCoderateCap = coderateCap;
- mHierarchyCap = hierarchyCap;
- mGuardIntervalCap = guardIntervalCap;
- mIsT2Supported = isT2Supported;
- mIsMisoSupported = isMisoSupported;
- }
-
- /** Gets transmission mode capability. */
- public int getTransmissionModeCapability() {
- return mTransmissionModeCap;
- }
- /** Gets bandwidth capability. */
- public int getBandwidthCapability() {
- return mBandwidthCap;
- }
- /** Gets constellation capability. */
- public int getConstellationCapability() {
- return mConstellationCap;
- }
- /** Gets code rate capability. */
- public int getCodeRateCapability() {
- return mCoderateCap;
- }
- /** Gets hierarchy capability. */
- public int getHierarchyCapability() {
- return mHierarchyCap;
- }
- /** Gets guard interval capability. */
- public int getGuardIntervalCapability() {
- return mGuardIntervalCap;
- }
- /** Returns whether T2 is supported. */
- public boolean getIsT2Supported() {
- return mIsT2Supported;
- }
- /** Returns whether MISO is supported. */
- public boolean getIsMisoSupported() {
- return mIsMisoSupported;
- }
- }
-
- /** ISDBS Capabilities. */
- public class Isdbs extends FrontendCapabilities {
- private final int mModulationCap;
- private final int mCoderateCap;
-
- Isdbs(int modulationCap, int coderateCap) {
- mModulationCap = modulationCap;
- mCoderateCap = coderateCap;
- }
-
- /** Gets modulation capability. */
- public int getModulationCapability() {
- return mModulationCap;
- }
- /** Gets code rate capability. */
- public int getCodeRateCapability() {
- return mCoderateCap;
- }
- }
-
- /** ISDBS-3 Capabilities. */
- public class Isdbs3 extends FrontendCapabilities {
- private final int mModulationCap;
- private final int mCoderateCap;
-
- Isdbs3(int modulationCap, int coderateCap) {
- mModulationCap = modulationCap;
- mCoderateCap = coderateCap;
- }
-
- /** Gets modulation capability. */
- public int getModulationCapability() {
- return mModulationCap;
- }
- /** Gets code rate capability. */
- public int getCodeRateCapability() {
- return mCoderateCap;
- }
- }
-
- /** ISDBC Capabilities. */
- public class Isdbc extends FrontendCapabilities {
- private final int mModeCap;
- private final int mBandwidthCap;
- private final int mModulationCap;
- private final int mCoderateCap;
- private final int mGuardIntervalCap;
-
- Isdbc(int modeCap, int bandwidthCap, int modulationCap, int coderateCap,
- int guardIntervalCap) {
- mModeCap = modeCap;
- mBandwidthCap = bandwidthCap;
- mModulationCap = modulationCap;
- mCoderateCap = coderateCap;
- mGuardIntervalCap = guardIntervalCap;
- }
-
- /** Gets mode capability. */
- public int getModeCapability() {
- return mModeCap;
- }
- /** Gets bandwidth capability. */
- public int getBandwidthCapability() {
- return mBandwidthCap;
- }
- /** Gets modulation capability. */
- public int getModulationCapability() {
- return mModulationCap;
- }
- /** Gets code rate capability. */
- public int getCodeRateCapability() {
- return mCoderateCap;
- }
- /** Gets guard interval capability. */
- public int getGuardIntervalCapability() {
- return mGuardIntervalCap;
- }
- }
-}
diff --git a/media/java/android/media/tv/tuner/frontend/AnalogFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/AnalogFrontendCapabilities.java
new file mode 100644
index 000000000000..2962e98790e5
--- /dev/null
+++ b/media/java/android/media/tv/tuner/frontend/AnalogFrontendCapabilities.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner.frontend;
+
+/**
+ * Analog Capabilities.
+ * @hide
+ */
+public class AnalogFrontendCapabilities extends FrontendCapabilities {
+ private final int mTypeCap;
+ private final int mSifStandardCap;
+
+ AnalogFrontendCapabilities(int typeCap, int sifStandardCap) {
+ mTypeCap = typeCap;
+ mSifStandardCap = sifStandardCap;
+ }
+ /**
+ * Gets type capability.
+ */
+ public int getTypeCapability() {
+ return mTypeCap;
+ }
+ /** Gets SIF standard capability. */
+ public int getSifStandardCapability() {
+ return mSifStandardCap;
+ }
+}
diff --git a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendCapabilities.java
new file mode 100644
index 000000000000..677f9387c6d2
--- /dev/null
+++ b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendCapabilities.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner.frontend;
+
+/**
+ * ATSC-3 Capabilities.
+ * @hide
+ */
+public class Atsc3FrontendCapabilities extends FrontendCapabilities {
+ private final int mBandwidthCap;
+ private final int mModulationCap;
+ private final int mTimeInterleaveModeCap;
+ private final int mCodeRateCap;
+ private final int mFecCap;
+ private final int mDemodOutputFormatCap;
+
+ Atsc3FrontendCapabilities(int bandwidthCap, int modulationCap, int timeInterleaveModeCap,
+ int codeRateCap, int fecCap, int demodOutputFormatCap) {
+ mBandwidthCap = bandwidthCap;
+ mModulationCap = modulationCap;
+ mTimeInterleaveModeCap = timeInterleaveModeCap;
+ mCodeRateCap = codeRateCap;
+ mFecCap = fecCap;
+ mDemodOutputFormatCap = demodOutputFormatCap;
+ }
+
+ /** Gets bandwidth capability. */
+ public int getBandwidthCapability() {
+ return mBandwidthCap;
+ }
+ /** Gets modulation capability. */
+ public int getModulationCapability() {
+ return mModulationCap;
+ }
+ /** Gets time interleave mod capability. */
+ public int getTimeInterleaveModeCapability() {
+ return mTimeInterleaveModeCap;
+ }
+ /** Gets code rate capability. */
+ public int getCodeRateCapability() {
+ return mCodeRateCap;
+ }
+ /** Gets FEC capability. */
+ public int getFecCapability() {
+ return mFecCap;
+ }
+ /** Gets demodulator output format capability. */
+ public int getDemodOutputFormatCapability() {
+ return mDemodOutputFormatCap;
+ }
+}
diff --git a/media/java/android/media/tv/tuner/frontend/AtscFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/AtscFrontendCapabilities.java
new file mode 100644
index 000000000000..6ae3c632f5db
--- /dev/null
+++ b/media/java/android/media/tv/tuner/frontend/AtscFrontendCapabilities.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner.frontend;
+
+/**
+ * ATSC Capabilities.
+ * @hide
+ */
+public class AtscFrontendCapabilities extends FrontendCapabilities {
+ private final int mModulationCap;
+
+ AtscFrontendCapabilities(int modulationCap) {
+ mModulationCap = modulationCap;
+ }
+ /** Gets modulation capability. */
+ public int getModulationCapability() {
+ return mModulationCap;
+ }
+}
diff --git a/media/java/android/media/tv/tuner/frontend/DvbcFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/DvbcFrontendCapabilities.java
new file mode 100644
index 000000000000..edea7af06774
--- /dev/null
+++ b/media/java/android/media/tv/tuner/frontend/DvbcFrontendCapabilities.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner.frontend;
+
+/**
+ * DVBC Capabilities.
+ * @hide
+ */
+public class DvbcFrontendCapabilities extends FrontendCapabilities {
+ private final int mModulationCap;
+ private final int mFecCap;
+ private final int mAnnexCap;
+
+ DvbcFrontendCapabilities(int modulationCap, int fecCap, int annexCap) {
+ mModulationCap = modulationCap;
+ mFecCap = fecCap;
+ mAnnexCap = annexCap;
+ }
+
+ /** Gets modulation capability. */
+ public int getModulationCapability() {
+ return mModulationCap;
+ }
+ /** Gets FEC capability. */
+ public int getFecCapability() {
+ return mFecCap;
+ }
+ /** Gets annex capability. */
+ public int getAnnexCapability() {
+ return mAnnexCap;
+ }
+}
diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendCapabilities.java
new file mode 100644
index 000000000000..f5a41574cd04
--- /dev/null
+++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendCapabilities.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner.frontend;
+
+/**
+ * DVBS Capabilities.
+ * @hide
+ */
+public class DvbsFrontendCapabilities extends FrontendCapabilities {
+ private final int mModulationCap;
+ private final long mInnerFecCap;
+ private final int mStandard;
+
+ DvbsFrontendCapabilities(int modulationCap, long innerFecCap, int standard) {
+ mModulationCap = modulationCap;
+ mInnerFecCap = innerFecCap;
+ mStandard = standard;
+ }
+
+ /** Gets modulation capability. */
+ public int getModulationCapability() {
+ return mModulationCap;
+ }
+ /** Gets inner FEC capability. */
+ public long getInnerFecCapability() {
+ return mInnerFecCap;
+ }
+ /** Gets DVBS standard capability. */
+ public int getStandardCapability() {
+ return mStandard;
+ }
+}
diff --git a/media/java/android/media/tv/tuner/frontend/DvbtFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/DvbtFrontendCapabilities.java
new file mode 100644
index 000000000000..e9c16ddd4dc8
--- /dev/null
+++ b/media/java/android/media/tv/tuner/frontend/DvbtFrontendCapabilities.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner.frontend;
+
+/**
+ * DVBT Capabilities.
+ * @hide
+ */
+public class DvbtFrontendCapabilities extends FrontendCapabilities {
+ private final int mTransmissionModeCap;
+ private final int mBandwidthCap;
+ private final int mConstellationCap;
+ private final int mCoderateCap;
+ private final int mHierarchyCap;
+ private final int mGuardIntervalCap;
+ private final boolean mIsT2Supported;
+ private final boolean mIsMisoSupported;
+
+ DvbtFrontendCapabilities(int transmissionModeCap, int bandwidthCap, int constellationCap,
+ int coderateCap, int hierarchyCap, int guardIntervalCap, boolean isT2Supported,
+ boolean isMisoSupported) {
+ mTransmissionModeCap = transmissionModeCap;
+ mBandwidthCap = bandwidthCap;
+ mConstellationCap = constellationCap;
+ mCoderateCap = coderateCap;
+ mHierarchyCap = hierarchyCap;
+ mGuardIntervalCap = guardIntervalCap;
+ mIsT2Supported = isT2Supported;
+ mIsMisoSupported = isMisoSupported;
+ }
+
+ /** Gets transmission mode capability. */
+ public int getTransmissionModeCapability() {
+ return mTransmissionModeCap;
+ }
+ /** Gets bandwidth capability. */
+ public int getBandwidthCapability() {
+ return mBandwidthCap;
+ }
+ /** Gets constellation capability. */
+ public int getConstellationCapability() {
+ return mConstellationCap;
+ }
+ /** Gets code rate capability. */
+ public int getCodeRateCapability() {
+ return mCoderateCap;
+ }
+ /** Gets hierarchy capability. */
+ public int getHierarchyCapability() {
+ return mHierarchyCap;
+ }
+ /** Gets guard interval capability. */
+ public int getGuardIntervalCapability() {
+ return mGuardIntervalCap;
+ }
+ /** Returns whether T2 is supported. */
+ public boolean getIsT2Supported() {
+ return mIsT2Supported;
+ }
+ /** Returns whether MISO is supported. */
+ public boolean getIsMisoSupported() {
+ return mIsMisoSupported;
+ }
+}
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/FrontendCapabilities.java
new file mode 100644
index 000000000000..7350bc0c3914
--- /dev/null
+++ b/media/java/android/media/tv/tuner/frontend/FrontendCapabilities.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner.frontend;
+
+/**
+ * Frontend Capabilities.
+ * @hide
+ */
+public abstract class FrontendCapabilities {
+}
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendInfo.java b/media/java/android/media/tv/tuner/frontend/FrontendInfo.java
index ef6c029fe626..5d03570eea80 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendInfo.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendInfo.java
@@ -16,7 +16,6 @@
package android.media.tv.tuner.frontend;
-import android.media.tv.tuner.FrontendCapabilities;
import android.media.tv.tuner.TunerConstants.FrontendType;
/**
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbcFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/IsdbcFrontendCapabilities.java
new file mode 100644
index 000000000000..6544b17609c2
--- /dev/null
+++ b/media/java/android/media/tv/tuner/frontend/IsdbcFrontendCapabilities.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner.frontend;
+
+/**
+ * ISDBC Capabilities.
+ * @hide
+ */
+public class IsdbcFrontendCapabilities extends FrontendCapabilities {
+ private final int mModeCap;
+ private final int mBandwidthCap;
+ private final int mModulationCap;
+ private final int mCoderateCap;
+ private final int mGuardIntervalCap;
+
+ IsdbcFrontendCapabilities(int modeCap, int bandwidthCap, int modulationCap, int coderateCap,
+ int guardIntervalCap) {
+ mModeCap = modeCap;
+ mBandwidthCap = bandwidthCap;
+ mModulationCap = modulationCap;
+ mCoderateCap = coderateCap;
+ mGuardIntervalCap = guardIntervalCap;
+ }
+
+ /** Gets mode capability. */
+ public int getModeCapability() {
+ return mModeCap;
+ }
+ /** Gets bandwidth capability. */
+ public int getBandwidthCapability() {
+ return mBandwidthCap;
+ }
+ /** Gets modulation capability. */
+ public int getModulationCapability() {
+ return mModulationCap;
+ }
+ /** Gets code rate capability. */
+ public int getCodeRateCapability() {
+ return mCoderateCap;
+ }
+ /** Gets guard interval capability. */
+ public int getGuardIntervalCapability() {
+ return mGuardIntervalCap;
+ }
+}
diff --git a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendCapabilities.java
new file mode 100644
index 000000000000..92832b7fcbdd
--- /dev/null
+++ b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendCapabilities.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner.frontend;
+
+/**
+ * ISDBS-3 Capabilities.
+ * @hide
+ */
+public class Isdbs3FrontendCapabilities extends FrontendCapabilities {
+ private final int mModulationCap;
+ private final int mCoderateCap;
+
+ Isdbs3FrontendCapabilities(int modulationCap, int coderateCap) {
+ mModulationCap = modulationCap;
+ mCoderateCap = coderateCap;
+ }
+
+ /** Gets modulation capability. */
+ public int getModulationCapability() {
+ return mModulationCap;
+ }
+ /** Gets code rate capability. */
+ public int getCodeRateCapability() {
+ return mCoderateCap;
+ }
+}
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendCapabilities.java
new file mode 100644
index 000000000000..b930b2578092
--- /dev/null
+++ b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendCapabilities.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner.frontend;
+
+/**
+ * ISDBS Capabilities.
+ * @hide
+ */
+public class IsdbsFrontendCapabilities extends FrontendCapabilities {
+ private final int mModulationCap;
+ private final int mCoderateCap;
+
+ IsdbsFrontendCapabilities(int modulationCap, int coderateCap) {
+ mModulationCap = modulationCap;
+ mCoderateCap = coderateCap;
+ }
+
+ /** Gets modulation capability. */
+ public int getModulationCapability() {
+ return mModulationCap;
+ }
+ /** Gets code rate capability. */
+ public int getCodeRateCapability() {
+ return mCoderateCap;
+ }
+}
diff --git a/media/java/android/mtp/MtpPropertyList.java b/media/java/android/mtp/MtpPropertyList.java
index 557f099c25c1..53d838d84518 100644
--- a/media/java/android/mtp/MtpPropertyList.java
+++ b/media/java/android/mtp/MtpPropertyList.java
@@ -16,7 +16,8 @@
package android.mtp;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.util.ArrayList;
import java.util.List;
diff --git a/media/java/android/mtp/MtpStorage.java b/media/java/android/mtp/MtpStorage.java
index c7dbca61f90a..ba752633718c 100644
--- a/media/java/android/mtp/MtpStorage.java
+++ b/media/java/android/mtp/MtpStorage.java
@@ -16,9 +16,8 @@
package android.mtp;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.storage.StorageVolume;
-import android.provider.MediaStore;
/**
* This class represents a storage unit on an MTP device.
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 86a1076af122..06adf30a8303 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -21,8 +21,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.UnsupportedAppUsage;
import android.app.Service;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
diff --git a/media/mca/effect/java/android/media/effect/SingleFilterEffect.java b/media/mca/effect/java/android/media/effect/SingleFilterEffect.java
index dfbf5d20e074..121443f56285 100644
--- a/media/mca/effect/java/android/media/effect/SingleFilterEffect.java
+++ b/media/mca/effect/java/android/media/effect/SingleFilterEffect.java
@@ -17,12 +17,11 @@
package android.media.effect;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.filterfw.core.Filter;
import android.filterfw.core.FilterFactory;
import android.filterfw.core.FilterFunction;
import android.filterfw.core.Frame;
-import android.media.effect.EffectContext;
/**
* Effect subclass for effects based on a single Filter. Subclasses need only invoke the
diff --git a/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java b/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java
index 52615bf09faa..3a7f1ed4f7ec 100644
--- a/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java
+++ b/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java
@@ -17,11 +17,11 @@
package android.filterfw;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.filterfw.core.AsyncRunner;
-import android.filterfw.core.FilterGraph;
import android.filterfw.core.FilterContext;
+import android.filterfw.core.FilterGraph;
import android.filterfw.core.FrameManager;
import android.filterfw.core.GraphRunner;
import android.filterfw.core.RoundRobinScheduler;
diff --git a/media/mca/filterfw/java/android/filterfw/core/Filter.java b/media/mca/filterfw/java/android/filterfw/core/Filter.java
index 4f56b923f6ed..a608ef5be3f4 100644
--- a/media/mca/filterfw/java/android/filterfw/core/Filter.java
+++ b/media/mca/filterfw/java/android/filterfw/core/Filter.java
@@ -17,19 +17,15 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.FilterContext;
-import android.filterfw.core.FilterPort;
-import android.filterfw.core.KeyValueMap;
-import android.filterfw.io.TextGraphReader;
-import android.filterfw.io.GraphIOException;
+import android.compat.annotation.UnsupportedAppUsage;
import android.filterfw.format.ObjectFormat;
+import android.filterfw.io.GraphIOException;
+import android.filterfw.io.TextGraphReader;
import android.util.Log;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
-import java.lang.Thread;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
diff --git a/media/mca/filterfw/java/android/filterfw/core/FilterContext.java b/media/mca/filterfw/java/android/filterfw/core/FilterContext.java
index a19220ef85f8..6b0a2193dceb 100644
--- a/media/mca/filterfw/java/android/filterfw/core/FilterContext.java
+++ b/media/mca/filterfw/java/android/filterfw/core/FilterContext.java
@@ -17,11 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.Filter;
-import android.filterfw.core.Frame;
-import android.filterfw.core.FrameManager;
-import android.filterfw.core.GLEnvironment;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.HashMap;
import java.util.HashSet;
diff --git a/media/mca/filterfw/java/android/filterfw/core/FilterGraph.java b/media/mca/filterfw/java/android/filterfw/core/FilterGraph.java
index e6ca11ffca3c..35a298fd6dfb 100644
--- a/media/mca/filterfw/java/android/filterfw/core/FilterGraph.java
+++ b/media/mca/filterfw/java/android/filterfw/core/FilterGraph.java
@@ -17,6 +17,11 @@
package android.filterfw.core;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.filterpacks.base.FrameBranch;
+import android.filterpacks.base.NullFilter;
+import android.util.Log;
+
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -25,14 +30,6 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
-import android.filterfw.core.FilterContext;
-import android.filterfw.core.KeyValueMap;
-import android.filterpacks.base.FrameBranch;
-import android.filterpacks.base.NullFilter;
-
-import android.annotation.UnsupportedAppUsage;
-import android.util.Log;
-
/**
* @hide
*/
diff --git a/media/mca/filterfw/java/android/filterfw/core/Frame.java b/media/mca/filterfw/java/android/filterfw/core/Frame.java
index e880783247a3..c4d935ae4873 100644
--- a/media/mca/filterfw/java/android/filterfw/core/Frame.java
+++ b/media/mca/filterfw/java/android/filterfw/core/Frame.java
@@ -17,9 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.FrameFormat;
-import android.filterfw.core.FrameManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
import java.nio.ByteBuffer;
diff --git a/media/mca/filterfw/java/android/filterfw/core/FrameFormat.java b/media/mca/filterfw/java/android/filterfw/core/FrameFormat.java
index eb0ff0a32c3f..a87e9b9ffbcf 100644
--- a/media/mca/filterfw/java/android/filterfw/core/FrameFormat.java
+++ b/media/mca/filterfw/java/android/filterfw/core/FrameFormat.java
@@ -17,9 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.KeyValueMap;
-import android.filterfw.core.MutableFrameFormat;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.Arrays;
import java.util.Map.Entry;
diff --git a/media/mca/filterfw/java/android/filterfw/core/FrameManager.java b/media/mca/filterfw/java/android/filterfw/core/FrameManager.java
index 85c8fcd9787d..e49aaf1d6fad 100644
--- a/media/mca/filterfw/java/android/filterfw/core/FrameManager.java
+++ b/media/mca/filterfw/java/android/filterfw/core/FrameManager.java
@@ -17,10 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.Frame;
-import android.filterfw.core.FrameFormat;
-import android.filterfw.core.MutableFrameFormat;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* @hide
diff --git a/media/mca/filterfw/java/android/filterfw/core/GLEnvironment.java b/media/mca/filterfw/java/android/filterfw/core/GLEnvironment.java
index e25d6a7d70ab..7e4e8a64a81f 100644
--- a/media/mca/filterfw/java/android/filterfw/core/GLEnvironment.java
+++ b/media/mca/filterfw/java/android/filterfw/core/GLEnvironment.java
@@ -17,13 +17,12 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.NativeAllocatorTag;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.SurfaceTexture;
+import android.media.MediaRecorder;
import android.os.Looper;
import android.util.Log;
import android.view.Surface;
-import android.media.MediaRecorder;
/**
* @hide
diff --git a/media/mca/filterfw/java/android/filterfw/core/GLFrame.java b/media/mca/filterfw/java/android/filterfw/core/GLFrame.java
index 9e3025fafb6e..1ccd7feaa7c3 100644
--- a/media/mca/filterfw/java/android/filterfw/core/GLFrame.java
+++ b/media/mca/filterfw/java/android/filterfw/core/GLFrame.java
@@ -17,15 +17,10 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.Frame;
-import android.filterfw.core.FrameFormat;
-import android.filterfw.core.FrameManager;
-import android.filterfw.core.NativeFrame;
-import android.filterfw.core.StopWatchMap;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
-import android.opengl.GLES20;
import android.graphics.Rect;
+import android.opengl.GLES20;
import java.nio.ByteBuffer;
diff --git a/media/mca/filterfw/java/android/filterfw/core/GraphRunner.java b/media/mca/filterfw/java/android/filterfw/core/GraphRunner.java
index 250cfaaba9d4..b57e8bb7262e 100644
--- a/media/mca/filterfw/java/android/filterfw/core/GraphRunner.java
+++ b/media/mca/filterfw/java/android/filterfw/core/GraphRunner.java
@@ -17,7 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* @hide
diff --git a/media/mca/filterfw/java/android/filterfw/core/MutableFrameFormat.java b/media/mca/filterfw/java/android/filterfw/core/MutableFrameFormat.java
index ae2ad99899f0..da00b1ffb180 100644
--- a/media/mca/filterfw/java/android/filterfw/core/MutableFrameFormat.java
+++ b/media/mca/filterfw/java/android/filterfw/core/MutableFrameFormat.java
@@ -17,9 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.FrameFormat;
-import android.filterfw.core.KeyValueMap;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.Arrays;
diff --git a/media/mca/filterfw/java/android/filterfw/core/Program.java b/media/mca/filterfw/java/android/filterfw/core/Program.java
index 376c08554eb2..145388e4437e 100644
--- a/media/mca/filterfw/java/android/filterfw/core/Program.java
+++ b/media/mca/filterfw/java/android/filterfw/core/Program.java
@@ -17,8 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.Frame;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* @hide
diff --git a/media/mca/filterfw/java/android/filterfw/core/ShaderProgram.java b/media/mca/filterfw/java/android/filterfw/core/ShaderProgram.java
index f41636e7cf76..e043be0e27bd 100644
--- a/media/mca/filterfw/java/android/filterfw/core/ShaderProgram.java
+++ b/media/mca/filterfw/java/android/filterfw/core/ShaderProgram.java
@@ -17,12 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.Frame;
-import android.filterfw.core.NativeAllocatorTag;
-import android.filterfw.core.Program;
-import android.filterfw.core.StopWatchMap;
-import android.filterfw.core.VertexFrame;
+import android.compat.annotation.UnsupportedAppUsage;
import android.filterfw.geometry.Quad;
import android.opengl.GLES20;
diff --git a/media/mca/filterfw/java/android/filterfw/format/ImageFormat.java b/media/mca/filterfw/java/android/filterfw/format/ImageFormat.java
index ac087305287f..0e05092d0cdd 100644
--- a/media/mca/filterfw/java/android/filterfw/format/ImageFormat.java
+++ b/media/mca/filterfw/java/android/filterfw/format/ImageFormat.java
@@ -17,7 +17,7 @@
package android.filterfw.format;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.filterfw.core.FrameFormat;
import android.filterfw.core.MutableFrameFormat;
import android.graphics.Bitmap;
diff --git a/media/mca/filterfw/java/android/filterfw/geometry/Point.java b/media/mca/filterfw/java/android/filterfw/geometry/Point.java
index d7acf12dd1de..96d2d7b08b74 100644
--- a/media/mca/filterfw/java/android/filterfw/geometry/Point.java
+++ b/media/mca/filterfw/java/android/filterfw/geometry/Point.java
@@ -17,8 +17,7 @@
package android.filterfw.geometry;
-import android.annotation.UnsupportedAppUsage;
-import java.lang.Math;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* @hide
diff --git a/media/mca/filterfw/java/android/filterfw/geometry/Quad.java b/media/mca/filterfw/java/android/filterfw/geometry/Quad.java
index 610e5b80399d..2b308a91576f 100644
--- a/media/mca/filterfw/java/android/filterfw/geometry/Quad.java
+++ b/media/mca/filterfw/java/android/filterfw/geometry/Quad.java
@@ -17,10 +17,8 @@
package android.filterfw.geometry;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.geometry.Point;
+import android.compat.annotation.UnsupportedAppUsage;
-import java.lang.Float;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
diff --git a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
index 04fccc7e0f94..ec177321bba3 100644
--- a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
@@ -46,8 +46,8 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
public static final String ROUTE_ID5_TO_TRANSFER_TO = "route_id5_to_transfer_to";
public static final String ROUTE_NAME5 = "Sample Route 5 - Route to transfer to";
- public static final String ROUTE_ID_SPECIAL_CATEGORY = "route_special_category";
- public static final String ROUTE_NAME_SPECIAL_CATEGORY = "Special Category Route";
+ public static final String ROUTE_ID_SPECIAL_TYPE = "route_special_type";
+ public static final String ROUTE_NAME_SPECIAL_TYPE = "Special Type Route";
public static final int VOLUME_MAX = 100;
public static final String ROUTE_ID_FIXED_VOLUME = "route_fixed_volume";
@@ -58,10 +58,10 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
public static final String ACTION_REMOVE_ROUTE =
"com.android.mediarouteprovider.action_remove_route";
- public static final String CATEGORY_SAMPLE =
- "com.android.mediarouteprovider.CATEGORY_SAMPLE";
- public static final String CATEGORY_SPECIAL =
- "com.android.mediarouteprovider.CATEGORY_SPECIAL";
+ public static final String TYPE_SAMPLE =
+ "com.android.mediarouteprovider.TYPE_SAMPLE";
+ public static final String TYPE_SPECIAL =
+ "com.android.mediarouteprovider.TYPE_SPECIAL";
Map<String, MediaRoute2Info> mRoutes = new HashMap<>();
Map<String, Integer> mRouteSessionMap = new HashMap<>();
@@ -69,38 +69,38 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
private void initializeRoutes() {
MediaRoute2Info route1 = new MediaRoute2Info.Builder(ROUTE_ID1, ROUTE_NAME1)
- .addSupportedCategory(CATEGORY_SAMPLE)
+ .addRouteType(TYPE_SAMPLE)
.setDeviceType(DEVICE_TYPE_TV)
.build();
MediaRoute2Info route2 = new MediaRoute2Info.Builder(ROUTE_ID2, ROUTE_NAME2)
- .addSupportedCategory(CATEGORY_SAMPLE)
+ .addRouteType(TYPE_SAMPLE)
.setDeviceType(DEVICE_TYPE_SPEAKER)
.build();
MediaRoute2Info route3 = new MediaRoute2Info.Builder(
ROUTE_ID3_SESSION_CREATION_FAILED, ROUTE_NAME3)
- .addSupportedCategory(CATEGORY_SAMPLE)
+ .addRouteType(TYPE_SAMPLE)
.build();
MediaRoute2Info route4 = new MediaRoute2Info.Builder(
ROUTE_ID4_TO_SELECT_AND_DESELECT, ROUTE_NAME4)
- .addSupportedCategory(CATEGORY_SAMPLE)
+ .addRouteType(TYPE_SAMPLE)
.build();
MediaRoute2Info route5 = new MediaRoute2Info.Builder(
ROUTE_ID5_TO_TRANSFER_TO, ROUTE_NAME5)
- .addSupportedCategory(CATEGORY_SAMPLE)
+ .addRouteType(TYPE_SAMPLE)
.build();
MediaRoute2Info routeSpecial =
- new MediaRoute2Info.Builder(ROUTE_ID_SPECIAL_CATEGORY, ROUTE_NAME_SPECIAL_CATEGORY)
- .addSupportedCategory(CATEGORY_SAMPLE)
- .addSupportedCategory(CATEGORY_SPECIAL)
+ new MediaRoute2Info.Builder(ROUTE_ID_SPECIAL_TYPE, ROUTE_NAME_SPECIAL_TYPE)
+ .addRouteType(TYPE_SAMPLE)
+ .addRouteType(TYPE_SPECIAL)
.build();
MediaRoute2Info fixedVolumeRoute =
new MediaRoute2Info.Builder(ROUTE_ID_FIXED_VOLUME, ROUTE_NAME_FIXED_VOLUME)
- .addSupportedCategory(CATEGORY_SAMPLE)
+ .addRouteType(TYPE_SAMPLE)
.setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_FIXED)
.build();
MediaRoute2Info variableVolumeRoute =
new MediaRoute2Info.Builder(ROUTE_ID_VARIABLE_VOLUME, ROUTE_NAME_VARIABLE_VOLUME)
- .addSupportedCategory(CATEGORY_SAMPLE)
+ .addRouteType(TYPE_SAMPLE)
.setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
.setVolumeMax(VOLUME_MAX)
.build();
@@ -167,7 +167,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
}
@Override
- public void onCreateSession(String packageName, String routeId, String controlCategory,
+ public void onCreateSession(String packageName, String routeId, String routeType,
long requestId) {
MediaRoute2Info route = mRoutes.get(routeId);
if (route == null || TextUtils.equals(ROUTE_ID3_SESSION_CREATION_FAILED, routeId)) {
@@ -186,7 +186,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
mRouteSessionMap.put(routeId, sessionId);
RouteSessionInfo sessionInfo = new RouteSessionInfo.Builder(
- sessionId, packageName, controlCategory)
+ sessionId, packageName, routeType)
.addSelectedRoute(routeId)
.addSelectableRoute(ROUTE_ID4_TO_SELECT_AND_DESELECT)
.addTransferrableRoute(ROUTE_ID5_TO_TRANSFER_TO)
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
index 86b9706bf590..af69c7e8699f 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java
@@ -23,18 +23,18 @@ import static android.media.MediaRoute2Info.DEVICE_TYPE_TV;
import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_FIXED;
import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
-import static com.android.mediaroutertest.MediaRouterManagerTest.CATEGORIES_ALL;
-import static com.android.mediaroutertest.MediaRouterManagerTest.CATEGORIES_SPECIAL;
-import static com.android.mediaroutertest.MediaRouterManagerTest.CATEGORY_SAMPLE;
-import static com.android.mediaroutertest.MediaRouterManagerTest.CATEGORY_SPECIAL;
import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID1;
import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID2;
import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID3_SESSION_CREATION_FAILED;
import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID4_TO_SELECT_AND_DESELECT;
import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID5_TO_TRANSFER_TO;
-import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID_SPECIAL_CATEGORY;
+import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID_SPECIAL_TYPE;
import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID_VARIABLE_VOLUME;
import static com.android.mediaroutertest.MediaRouterManagerTest.SYSTEM_PROVIDER_ID;
+import static com.android.mediaroutertest.MediaRouterManagerTest.TYPES_ALL;
+import static com.android.mediaroutertest.MediaRouterManagerTest.TYPES_SPECIAL;
+import static com.android.mediaroutertest.MediaRouterManagerTest.TYPE_SAMPLE;
+import static com.android.mediaroutertest.MediaRouterManagerTest.TYPE_SPECIAL;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -50,6 +50,7 @@ import android.media.MediaRouter2;
import android.media.MediaRouter2.RouteCallback;
import android.media.MediaRouter2.RouteSessionController;
import android.media.MediaRouter2.SessionCallback;
+import android.media.RouteDiscoveryRequest;
import android.media.RouteSessionInfo;
import android.net.Uri;
import android.os.Parcel;
@@ -95,14 +96,14 @@ public class MediaRouter2Test {
}
/**
- * Tests if we get proper routes for application that has special control category.
+ * Tests if we get proper routes for application that has special route type.
*/
@Test
public void testGetRoutes() throws Exception {
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_SPECIAL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(TYPES_SPECIAL);
assertEquals(1, routes.size());
- assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
+ assertNotNull(routes.get(ROUTE_ID_SPECIAL_TYPE));
}
@Test
@@ -114,7 +115,7 @@ public class MediaRouter2Test {
.setIconUri(new Uri.Builder().path("icon").build())
.setVolume(5)
.setVolumeMax(20)
- .addSupportedCategory(CATEGORY_SAMPLE)
+ .addRouteType(TYPE_SAMPLE)
.setVolumeHandling(PLAYBACK_VOLUME_VARIABLE)
.setDeviceType(DEVICE_TYPE_SPEAKER)
.build();
@@ -137,7 +138,7 @@ public class MediaRouter2Test {
.setClientPackageName("com.android.mediaroutertest")
.setConnectionState(CONNECTION_STATE_CONNECTING)
.setIconUri(new Uri.Builder().path("icon").build())
- .addSupportedCategory(CATEGORY_SAMPLE)
+ .addRouteType(TYPE_SAMPLE)
.setVolume(5)
.setVolumeMax(20)
.setVolumeHandling(PLAYBACK_VOLUME_VARIABLE)
@@ -168,9 +169,9 @@ public class MediaRouter2Test {
.setClientPackageName("another.client.package").build();
assertNotEquals(route, routeClient);
- MediaRoute2Info routeCategory = new MediaRoute2Info.Builder(route)
- .addSupportedCategory(CATEGORY_SPECIAL).build();
- assertNotEquals(route, routeCategory);
+ MediaRoute2Info routeType = new MediaRoute2Info.Builder(route)
+ .addRouteType(TYPE_SPECIAL).build();
+ assertNotEquals(route, routeType);
MediaRoute2Info routeVolume = new MediaRoute2Info.Builder(route)
.setVolume(10).build();
@@ -191,7 +192,7 @@ public class MediaRouter2Test {
@Test
public void testControlVolumeWithRouter() throws Exception {
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CATEGORIES_ALL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(TYPES_ALL);
MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
assertNotNull(volRoute);
@@ -202,12 +203,14 @@ public class MediaRouter2Test {
awaitOnRouteChanged(
() -> mRouter2.requestUpdateVolume(volRoute, deltaVolume),
ROUTE_ID_VARIABLE_VOLUME,
- (route -> route.getVolume() == originalVolume + deltaVolume));
+ (route -> route.getVolume() == originalVolume + deltaVolume),
+ TYPES_ALL);
awaitOnRouteChanged(
() -> mRouter2.requestSetVolume(volRoute, originalVolume),
ROUTE_ID_VARIABLE_VOLUME,
- (route -> route.getVolume() == originalVolume));
+ (route -> route.getVolume() == originalVolume),
+ TYPES_ALL);
}
@Test
@@ -234,13 +237,13 @@ public class MediaRouter2Test {
@Test
public void testRequestCreateSessionWithInvalidArguments() {
MediaRoute2Info route = new MediaRoute2Info.Builder("id", "name").build();
- String controlCategory = "controlCategory";
+ String routeType = "routeType";
// Tests null route
assertThrows(NullPointerException.class,
- () -> mRouter2.requestCreateSession(null, controlCategory));
+ () -> mRouter2.requestCreateSession(null, routeType));
- // Tests null or empty control category
+ // Tests null or empty route type
assertThrows(IllegalArgumentException.class,
() -> mRouter2.requestCreateSession(route, null));
assertThrows(IllegalArgumentException.class,
@@ -249,10 +252,10 @@ public class MediaRouter2Test {
@Test
public void testRequestCreateSessionSuccess() throws Exception {
- final List<String> sampleControlCategory = new ArrayList<>();
- sampleControlCategory.add(CATEGORY_SAMPLE);
+ final List<String> sampleRouteType = new ArrayList<>();
+ sampleRouteType.add(TYPE_SAMPLE);
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleControlCategory);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteType);
MediaRoute2Info route = routes.get(ROUTE_ID1);
assertNotNull(route);
@@ -266,25 +269,25 @@ public class MediaRouter2Test {
public void onSessionCreated(RouteSessionController controller) {
assertNotNull(controller);
assertTrue(createRouteMap(controller.getSelectedRoutes()).containsKey(ROUTE_ID1));
- assertTrue(TextUtils.equals(CATEGORY_SAMPLE, controller.getControlCategory()));
+ assertTrue(TextUtils.equals(TYPE_SAMPLE, controller.getRouteType()));
controllers.add(controller);
successLatch.countDown();
}
@Override
public void onSessionCreationFailed(MediaRoute2Info requestedRoute,
- String requestedControlCategory) {
+ String requestedRouteType) {
failureLatch.countDown();
}
};
// TODO: Remove this once the MediaRouter2 becomes always connected to the service.
RouteCallback routeCallback = new RouteCallback();
- mRouter2.registerRouteCallback(mExecutor, routeCallback);
+ mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryRequest.EMPTY);
try {
mRouter2.registerSessionCallback(mExecutor, sessionCallback);
- mRouter2.requestCreateSession(route, CATEGORY_SAMPLE);
+ mRouter2.requestCreateSession(route, TYPE_SAMPLE);
assertTrue(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
// onSessionCreationFailed should not be called.
@@ -298,10 +301,10 @@ public class MediaRouter2Test {
@Test
public void testRequestCreateSessionFailure() throws Exception {
- final List<String> sampleControlCategory = new ArrayList<>();
- sampleControlCategory.add(CATEGORY_SAMPLE);
+ final List<String> sampleRouteType = new ArrayList<>();
+ sampleRouteType.add(TYPE_SAMPLE);
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleControlCategory);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteType);
MediaRoute2Info route = routes.get(ROUTE_ID3_SESSION_CREATION_FAILED);
assertNotNull(route);
@@ -319,20 +322,20 @@ public class MediaRouter2Test {
@Override
public void onSessionCreationFailed(MediaRoute2Info requestedRoute,
- String requestedControlCategory) {
+ String requestedRouteType) {
assertEquals(route, requestedRoute);
- assertTrue(TextUtils.equals(CATEGORY_SAMPLE, requestedControlCategory));
+ assertTrue(TextUtils.equals(TYPE_SAMPLE, requestedRouteType));
failureLatch.countDown();
}
};
// TODO: Remove this once the MediaRouter2 becomes always connected to the service.
RouteCallback routeCallback = new RouteCallback();
- mRouter2.registerRouteCallback(mExecutor, routeCallback);
+ mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryRequest.EMPTY);
try {
mRouter2.registerSessionCallback(mExecutor, sessionCallback);
- mRouter2.requestCreateSession(route, CATEGORY_SAMPLE);
+ mRouter2.requestCreateSession(route, TYPE_SAMPLE);
assertTrue(failureLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
// onSessionCreated should not be called.
@@ -346,8 +349,8 @@ public class MediaRouter2Test {
@Test
public void testRequestCreateSessionMultipleSessions() throws Exception {
- final List<String> sampleControlCategory = new ArrayList<>();
- sampleControlCategory.add(CATEGORY_SAMPLE);
+ final List<String> sampleRouteType = new ArrayList<>();
+ sampleRouteType.add(TYPE_SAMPLE);
final CountDownLatch successLatch = new CountDownLatch(2);
final CountDownLatch failureLatch = new CountDownLatch(1);
@@ -363,12 +366,12 @@ public class MediaRouter2Test {
@Override
public void onSessionCreationFailed(MediaRoute2Info requestedRoute,
- String requestedControlCategory) {
+ String requestedRouteType) {
failureLatch.countDown();
}
};
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleControlCategory);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteType);
MediaRoute2Info route1 = routes.get(ROUTE_ID1);
MediaRoute2Info route2 = routes.get(ROUTE_ID2);
assertNotNull(route1);
@@ -376,12 +379,12 @@ public class MediaRouter2Test {
// TODO: Remove this once the MediaRouter2 becomes always connected to the service.
RouteCallback routeCallback = new RouteCallback();
- mRouter2.registerRouteCallback(mExecutor, routeCallback);
+ mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryRequest.EMPTY);
try {
mRouter2.registerSessionCallback(mExecutor, sessionCallback);
- mRouter2.requestCreateSession(route1, CATEGORY_SAMPLE);
- mRouter2.requestCreateSession(route2, CATEGORY_SAMPLE);
+ mRouter2.requestCreateSession(route1, TYPE_SAMPLE);
+ mRouter2.requestCreateSession(route2, TYPE_SAMPLE);
assertTrue(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
// onSessionCreationFailed should not be called.
@@ -395,8 +398,8 @@ public class MediaRouter2Test {
assertNotEquals(controller1.getSessionId(), controller2.getSessionId());
assertTrue(createRouteMap(controller1.getSelectedRoutes()).containsKey(ROUTE_ID1));
assertTrue(createRouteMap(controller2.getSelectedRoutes()).containsKey(ROUTE_ID2));
- assertTrue(TextUtils.equals(CATEGORY_SAMPLE, controller1.getControlCategory()));
- assertTrue(TextUtils.equals(CATEGORY_SAMPLE, controller2.getControlCategory()));
+ assertTrue(TextUtils.equals(TYPE_SAMPLE, controller1.getRouteType()));
+ assertTrue(TextUtils.equals(TYPE_SAMPLE, controller2.getRouteType()));
} finally {
releaseControllers(createdControllers);
mRouter2.unregisterRouteCallback(routeCallback);
@@ -406,10 +409,10 @@ public class MediaRouter2Test {
@Test
public void testSessionCallbackIsNotCalledAfterUnregistered() throws Exception {
- final List<String> sampleControlCategory = new ArrayList<>();
- sampleControlCategory.add(CATEGORY_SAMPLE);
+ final List<String> sampleRouteType = new ArrayList<>();
+ sampleRouteType.add(TYPE_SAMPLE);
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleControlCategory);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteType);
MediaRoute2Info route = routes.get(ROUTE_ID1);
assertNotNull(route);
@@ -427,18 +430,18 @@ public class MediaRouter2Test {
@Override
public void onSessionCreationFailed(MediaRoute2Info requestedRoute,
- String requestedControlCategory) {
+ String requestedRouteType) {
failureLatch.countDown();
}
};
// TODO: Remove this once the MediaRouter2 becomes always connected to the service.
RouteCallback routeCallback = new RouteCallback();
- mRouter2.registerRouteCallback(mExecutor, routeCallback);
+ mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryRequest.EMPTY);
try {
mRouter2.registerSessionCallback(mExecutor, sessionCallback);
- mRouter2.requestCreateSession(route, CATEGORY_SAMPLE);
+ mRouter2.requestCreateSession(route, TYPE_SAMPLE);
// Unregisters session callback
mRouter2.unregisterSessionCallback(sessionCallback);
@@ -456,10 +459,10 @@ public class MediaRouter2Test {
// TODO: Add tests for illegal inputs if needed (e.g. selecting already selected route)
@Test
public void testRouteSessionControllerSelectAndDeselectRoute() throws Exception {
- final List<String> sampleControlCategory = new ArrayList<>();
- sampleControlCategory.add(CATEGORY_SAMPLE);
+ final List<String> sampleRouteType = new ArrayList<>();
+ sampleRouteType.add(TYPE_SAMPLE);
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleControlCategory);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteType);
MediaRoute2Info routeToCreateSessionWith = routes.get(ROUTE_ID1);
assertNotNull(routeToCreateSessionWith);
@@ -474,7 +477,7 @@ public class MediaRouter2Test {
public void onSessionCreated(RouteSessionController controller) {
assertNotNull(controller);
assertTrue(getRouteIds(controller.getSelectedRoutes()).contains(ROUTE_ID1));
- assertTrue(TextUtils.equals(CATEGORY_SAMPLE, controller.getControlCategory()));
+ assertTrue(TextUtils.equals(TYPE_SAMPLE, controller.getRouteType()));
controllers.add(controller);
onSessionCreatedLatch.countDown();
}
@@ -522,11 +525,11 @@ public class MediaRouter2Test {
// TODO: Remove this once the MediaRouter2 becomes always connected to the service.
RouteCallback routeCallback = new RouteCallback();
- mRouter2.registerRouteCallback(mExecutor, routeCallback);
+ mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryRequest.EMPTY);
try {
mRouter2.registerSessionCallback(mExecutor, sessionCallback);
- mRouter2.requestCreateSession(routeToCreateSessionWith, CATEGORY_SAMPLE);
+ mRouter2.requestCreateSession(routeToCreateSessionWith, TYPE_SAMPLE);
assertTrue(onSessionCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
assertEquals(1, controllers.size());
@@ -554,10 +557,10 @@ public class MediaRouter2Test {
@Test
public void testRouteSessionControllerTransferToRoute() throws Exception {
- final List<String> sampleControlCategory = new ArrayList<>();
- sampleControlCategory.add(CATEGORY_SAMPLE);
+ final List<String> sampleRouteType = new ArrayList<>();
+ sampleRouteType.add(TYPE_SAMPLE);
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleControlCategory);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteType);
MediaRoute2Info routeToCreateSessionWith = routes.get(ROUTE_ID1);
assertNotNull(routeToCreateSessionWith);
@@ -570,8 +573,12 @@ public class MediaRouter2Test {
@Override
public void onSessionCreated(RouteSessionController controller) {
assertNotNull(controller);
+ android.util.Log.d(TAG, "selected route ids ");
+ for (String routeId : getRouteIds(controller.getSelectedRoutes())) {
+ android.util.Log.d(TAG, "route id : " + routeId);
+ }
assertTrue(getRouteIds(controller.getSelectedRoutes()).contains(ROUTE_ID1));
- assertTrue(TextUtils.equals(CATEGORY_SAMPLE, controller.getControlCategory()));
+ assertTrue(TextUtils.equals(TYPE_SAMPLE, controller.getRouteType()));
controllers.add(controller);
onSessionCreatedLatch.countDown();
}
@@ -603,11 +610,11 @@ public class MediaRouter2Test {
// TODO: Remove this once the MediaRouter2 becomes always connected to the service.
RouteCallback routeCallback = new RouteCallback();
- mRouter2.registerRouteCallback(mExecutor, routeCallback);
+ mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryRequest.EMPTY);
try {
mRouter2.registerSessionCallback(mExecutor, sessionCallback);
- mRouter2.requestCreateSession(routeToCreateSessionWith, CATEGORY_SAMPLE);
+ mRouter2.requestCreateSession(routeToCreateSessionWith, TYPE_SAMPLE);
assertTrue(onSessionCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
assertEquals(1, controllers.size());
@@ -632,10 +639,10 @@ public class MediaRouter2Test {
@Test
public void testRouteSessionControllerReleaseShouldIgnoreTransferTo() throws Exception {
- final List<String> sampleControlCategory = new ArrayList<>();
- sampleControlCategory.add(CATEGORY_SAMPLE);
+ final List<String> sampleRouteType = new ArrayList<>();
+ sampleRouteType.add(TYPE_SAMPLE);
- Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleControlCategory);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteType);
MediaRoute2Info routeToCreateSessionWith = routes.get(ROUTE_ID1);
assertNotNull(routeToCreateSessionWith);
@@ -649,7 +656,7 @@ public class MediaRouter2Test {
public void onSessionCreated(RouteSessionController controller) {
assertNotNull(controller);
assertTrue(getRouteIds(controller.getSelectedRoutes()).contains(ROUTE_ID1));
- assertTrue(TextUtils.equals(CATEGORY_SAMPLE, controller.getControlCategory()));
+ assertTrue(TextUtils.equals(TYPE_SAMPLE, controller.getRouteType()));
controllers.add(controller);
onSessionCreatedLatch.countDown();
}
@@ -667,11 +674,11 @@ public class MediaRouter2Test {
// TODO: Remove this once the MediaRouter2 becomes always connected to the service.
RouteCallback routeCallback = new RouteCallback();
- mRouter2.registerRouteCallback(mExecutor, routeCallback);
+ mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryRequest.EMPTY);
try {
mRouter2.registerSessionCallback(mExecutor, sessionCallback);
- mRouter2.requestCreateSession(routeToCreateSessionWith, CATEGORY_SAMPLE);
+ mRouter2.requestCreateSession(routeToCreateSessionWith, TYPE_SAMPLE);
assertTrue(onSessionCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
assertEquals(1, controllers.size());
@@ -706,11 +713,11 @@ public class MediaRouter2Test {
return routeMap;
}
- Map<String, MediaRoute2Info> waitAndGetRoutes(List<String> controlCategories)
+ Map<String, MediaRoute2Info> waitAndGetRoutes(List<String> routeTypes)
throws Exception {
CountDownLatch latch = new CountDownLatch(1);
- // A dummy callback is required to send control category info.
+ // A dummy callback is required to send route type info.
RouteCallback routeCallback = new RouteCallback() {
@Override
public void onRoutesAdded(List<MediaRoute2Info> routes) {
@@ -723,8 +730,8 @@ public class MediaRouter2Test {
}
};
- mRouter2.setControlCategories(controlCategories);
- mRouter2.registerRouteCallback(mExecutor, routeCallback);
+ mRouter2.registerRouteCallback(mExecutor, routeCallback,
+ new RouteDiscoveryRequest.Builder(routeTypes, true).build());
try {
latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
return createRouteMap(mRouter2.getRoutes());
@@ -751,7 +758,8 @@ public class MediaRouter2Test {
}
void awaitOnRouteChanged(Runnable task, String routeId,
- Predicate<MediaRoute2Info> predicate) throws Exception {
+ Predicate<MediaRoute2Info> predicate,
+ List<String> routeTypes) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
RouteCallback routeCallback = new RouteCallback() {
@Override
@@ -762,7 +770,8 @@ public class MediaRouter2Test {
}
}
};
- mRouter2.registerRouteCallback(mExecutor, routeCallback);
+ mRouter2.registerRouteCallback(mExecutor, routeCallback,
+ new RouteDiscoveryRequest.Builder(routeTypes, true).build());
try {
task.run();
assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index 1fd014113299..c23a5b0d76e3 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -31,6 +31,7 @@ import android.media.MediaRouter2;
import android.media.MediaRouter2.RouteCallback;
import android.media.MediaRouter2.SessionCallback;
import android.media.MediaRouter2Manager;
+import android.media.RouteDiscoveryRequest;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -75,9 +76,9 @@ public class MediaRouterManagerTest {
SAMPLE_PROVIDER_ROUTES_ID_PREFIX + "route_id5_to_transfer_to";
public static final String ROUTE_NAME5 = "Sample Route 5 - Route to transfer to";
- public static final String ROUTE_ID_SPECIAL_CATEGORY =
- SAMPLE_PROVIDER_ROUTES_ID_PREFIX + "route_special_category";
- public static final String ROUTE_NAME_SPECIAL_CATEGORY = "Special Category Route";
+ public static final String ROUTE_ID_SPECIAL_TYPE =
+ SAMPLE_PROVIDER_ROUTES_ID_PREFIX + "route_special_type";
+ public static final String ROUTE_NAME_SPECIAL_TYPE = "Special Type Route";
public static final String SYSTEM_PROVIDER_ID =
"com.android.server.media/.SystemMediaRoute2Provider";
@@ -93,12 +94,12 @@ public class MediaRouterManagerTest {
public static final String ACTION_REMOVE_ROUTE =
"com.android.mediarouteprovider.action_remove_route";
- public static final String CATEGORY_SAMPLE =
- "com.android.mediarouteprovider.CATEGORY_SAMPLE";
- public static final String CATEGORY_SPECIAL =
- "com.android.mediarouteprovider.CATEGORY_SPECIAL";
+ public static final String TYPE_SAMPLE =
+ "com.android.mediarouteprovider.TYPE_SAMPLE";
+ public static final String TYPE_SPECIAL =
+ "com.android.mediarouteprovider.TYPE_SPECIAL";
- private static final String CATEGORY_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO";
+ private static final String TYPE_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO";
private static final int TIMEOUT_MS = 5000;
@@ -112,18 +113,18 @@ public class MediaRouterManagerTest {
private final List<RouteCallback> mRouteCallbacks = new ArrayList<>();
private final List<SessionCallback> mSessionCallbacks = new ArrayList<>();
- public static final List<String> CATEGORIES_ALL = new ArrayList();
- public static final List<String> CATEGORIES_SPECIAL = new ArrayList();
- private static final List<String> CATEGORIES_LIVE_AUDIO = new ArrayList<>();
+ public static final List<String> TYPES_ALL = new ArrayList();
+ public static final List<String> TYPES_SPECIAL = new ArrayList();
+ private static final List<String> TYPES_LIVE_AUDIO = new ArrayList<>();
static {
- CATEGORIES_ALL.add(CATEGORY_SAMPLE);
- CATEGORIES_ALL.add(CATEGORY_SPECIAL);
- CATEGORIES_ALL.add(CATEGORY_LIVE_AUDIO);
+ TYPES_ALL.add(TYPE_SAMPLE);
+ TYPES_ALL.add(TYPE_SPECIAL);
+ TYPES_ALL.add(TYPE_LIVE_AUDIO);
- CATEGORIES_SPECIAL.add(CATEGORY_SPECIAL);
+ TYPES_SPECIAL.add(TYPE_SPECIAL);
- CATEGORIES_LIVE_AUDIO.add(CATEGORY_LIVE_AUDIO);
+ TYPES_LIVE_AUDIO.add(TYPE_LIVE_AUDIO);
}
@Before
@@ -180,7 +181,7 @@ public class MediaRouterManagerTest {
@Test
public void testOnRoutesRemoved() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
- Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(TYPES_ALL);
addRouterCallback(new RouteCallback());
addManagerCallback(new MediaRouter2Manager.Callback() {
@@ -202,14 +203,14 @@ public class MediaRouterManagerTest {
}
/**
- * Tests if we get proper routes for application that has special control category.
+ * Tests if we get proper routes for application that has special route type.
*/
@Test
- public void testControlCategory() throws Exception {
- Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_SPECIAL);
+ public void testRouteType() throws Exception {
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(TYPES_SPECIAL);
assertEquals(1, routes.size());
- assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
+ assertNotNull(routes.get(ROUTE_ID_SPECIAL_TYPE));
}
/**
@@ -218,7 +219,7 @@ public class MediaRouterManagerTest {
*/
@Test
public void testRouterOnSessionCreated() throws Exception {
- Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(TYPES_ALL);
CountDownLatch latch = new CountDownLatch(1);
@@ -254,7 +255,7 @@ public class MediaRouterManagerTest {
@Ignore("TODO: test session created callback instead of onRouteSelected")
public void testManagerOnRouteSelected() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
- Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(TYPES_ALL);
addRouterCallback(new RouteCallback());
addManagerCallback(new MediaRouter2Manager.Callback() {
@@ -284,7 +285,7 @@ public class MediaRouterManagerTest {
public void testGetActiveRoutes() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
- Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(TYPES_ALL);
addRouterCallback(new RouteCallback());
addManagerCallback(new MediaRouter2Manager.Callback() {
@Override
@@ -320,7 +321,7 @@ public class MediaRouterManagerTest {
@Test
@Ignore("TODO: enable when session is released")
public void testSingleProviderSelect() throws Exception {
- Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(TYPES_ALL);
addRouterCallback(new RouteCallback());
awaitOnRouteChangedManager(
@@ -345,7 +346,7 @@ public class MediaRouterManagerTest {
@Test
public void testControlVolumeWithManager() throws Exception {
- Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(TYPES_ALL);
MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
int originalVolume = volRoute.getVolume();
@@ -364,7 +365,7 @@ public class MediaRouterManagerTest {
@Test
public void testVolumeHandling() throws Exception {
- Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(TYPES_ALL);
MediaRoute2Info fixedVolumeRoute = routes.get(ROUTE_ID_FIXED_VOLUME);
MediaRoute2Info variableVolumeRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
@@ -374,11 +375,11 @@ public class MediaRouterManagerTest {
assertEquals(VOLUME_MAX, variableVolumeRoute.getVolumeMax());
}
- Map<String, MediaRoute2Info> waitAndGetRoutesWithManager(List<String> controlCategories)
+ Map<String, MediaRoute2Info> waitAndGetRoutesWithManager(List<String> routeTypes)
throws Exception {
CountDownLatch latch = new CountDownLatch(2);
- // A dummy callback is required to send control category info.
+ // A dummy callback is required to send route type info.
RouteCallback routeCallback = new RouteCallback();
MediaRouter2Manager.Callback managerCallback = new MediaRouter2Manager.Callback() {
@Override
@@ -393,16 +394,16 @@ public class MediaRouterManagerTest {
}
@Override
- public void onControlCategoriesChanged(String packageName, List<String> categories) {
+ public void onControlCategoriesChanged(String packageName, List<String> routeTypes) {
if (TextUtils.equals(mPackageName, packageName)
- && controlCategories.equals(categories)) {
+ && routeTypes.equals(routeTypes)) {
latch.countDown();
}
}
};
mManager.registerCallback(mExecutor, managerCallback);
- mRouter2.setControlCategories(controlCategories);
- mRouter2.registerRouteCallback(mExecutor, routeCallback);
+ mRouter2.registerRouteCallback(mExecutor, routeCallback,
+ new RouteDiscoveryRequest.Builder(routeTypes, true).build());
try {
latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
return createRouteMap(mManager.getAvailableRoutes(mPackageName));
@@ -449,7 +450,7 @@ public class MediaRouterManagerTest {
private void addRouterCallback(RouteCallback routeCallback) {
mRouteCallbacks.add(routeCallback);
- mRouter2.registerRouteCallback(mExecutor, routeCallback);
+ mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryRequest.EMPTY);
}
private void addSessionCallback(SessionCallback sessionCallback) {
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/RouteDiscoveryRequestTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/RouteDiscoveryRequestTest.java
new file mode 100644
index 000000000000..60d131a8fb7e
--- /dev/null
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/RouteDiscoveryRequestTest.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 com.android.mediaroutertest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.media.RouteDiscoveryRequest;
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class RouteDiscoveryRequestTest {
+ @Before
+ public void setUp() throws Exception { }
+
+ @After
+ public void tearDown() throws Exception { }
+
+ @Test
+ public void testEquality() {
+ List<String> testTypes = new ArrayList<>();
+ testTypes.add("TEST_TYPE_1");
+ testTypes.add("TEST_TYPE_2");
+ RouteDiscoveryRequest request = new RouteDiscoveryRequest.Builder(testTypes, true)
+ .build();
+
+ RouteDiscoveryRequest requestRebuilt = new RouteDiscoveryRequest.Builder(request)
+ .build();
+
+ assertEquals(request, requestRebuilt);
+
+ Parcel parcel = Parcel.obtain();
+ parcel.writeParcelable(request, 0);
+ parcel.setDataPosition(0);
+ RouteDiscoveryRequest requestFromParcel = parcel.readParcelable(null);
+
+ assertEquals(request, requestFromParcel);
+ }
+
+ @Test
+ public void testInequality() {
+ List<String> testTypes = new ArrayList<>();
+ testTypes.add("TEST_TYPE_1");
+ testTypes.add("TEST_TYPE_2");
+
+ List<String> testTypes2 = new ArrayList<>();
+ testTypes.add("TEST_TYPE_3");
+
+ RouteDiscoveryRequest request = new RouteDiscoveryRequest.Builder(testTypes, true)
+ .build();
+
+ RouteDiscoveryRequest requestTypes = new RouteDiscoveryRequest.Builder(request)
+ .setRouteTypes(testTypes2)
+ .build();
+ assertNotEquals(request, requestTypes);
+
+ RouteDiscoveryRequest requestActiveScan = new RouteDiscoveryRequest.Builder(request)
+ .setActiveScan(false)
+ .build();
+ assertNotEquals(request, requestActiveScan);
+ }
+}
diff --git a/opengl/java/android/opengl/EGL14.java b/opengl/java/android/opengl/EGL14.java
index 728e6e18cc31..90b46fd5901a 100644
--- a/opengl/java/android/opengl/EGL14.java
+++ b/opengl/java/android/opengl/EGL14.java
@@ -18,11 +18,11 @@
package android.opengl;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.SurfaceTexture;
import android.view.Surface;
-import android.view.SurfaceView;
import android.view.SurfaceHolder;
+import android.view.SurfaceView;
/**
* EGL 1.4
diff --git a/opengl/java/android/opengl/GLES20.java b/opengl/java/android/opengl/GLES20.java
index d66e7ac84a3b..e853e4447daa 100644
--- a/opengl/java/android/opengl/GLES20.java
+++ b/opengl/java/android/opengl/GLES20.java
@@ -19,7 +19,7 @@
package android.opengl;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/** OpenGL ES 2.0
*/
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 8a3e6a0b0fd5..75131b0f6b9c 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -16,7 +16,7 @@
package android.opengl;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Trace;
import android.util.AttributeSet;
diff --git a/opengl/java/javax/microedition/khronos/egl/EGL10.java b/opengl/java/javax/microedition/khronos/egl/EGL10.java
index 8a2517062d4d..ea571c7311a1 100644
--- a/opengl/java/javax/microedition/khronos/egl/EGL10.java
+++ b/opengl/java/javax/microedition/khronos/egl/EGL10.java
@@ -16,8 +16,7 @@
package javax.microedition.khronos.egl;
-import android.annotation.UnsupportedAppUsage;
-import java.lang.String;
+import android.compat.annotation.UnsupportedAppUsage;
public interface EGL10 extends EGL {
int EGL_SUCCESS = 0x3000;
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 1e19786f5d41..ec445d4dcbee 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -160,7 +160,7 @@ public class ExternalStorageProvider extends FileSystemProvider {
final int userId = UserHandle.myUserId();
final List<VolumeInfo> volumes = mStorageManager.getVolumes();
for (VolumeInfo volume : volumes) {
- if (!volume.isMountedReadable()) continue;
+ if (!volume.isMountedReadable() || volume.getMountUserId() != userId) continue;
final String rootId;
final String title;
@@ -192,9 +192,8 @@ public class ExternalStorageProvider extends FileSystemProvider {
title = mStorageManager.getBestVolumeDescription(privateVol);
storageUuid = StorageManager.convert(privateVol.fsUuid);
}
- } else if ((volume.getType() == VolumeInfo.TYPE_PUBLIC
- || volume.getType() == VolumeInfo.TYPE_STUB)
- && volume.getMountUserId() == userId) {
+ } else if (volume.getType() == VolumeInfo.TYPE_PUBLIC
+ || volume.getType() == VolumeInfo.TYPE_STUB) {
rootId = volume.getFsUuid();
title = mStorageManager.getBestVolumeDescription(volume);
storageUuid = null;
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index 5b4ef3a47386..70b56ed0b391 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -194,6 +194,14 @@ public class LocalMediaManager implements BluetoothCallback {
}
}
+ void dispatchDeviceAttributesChanged() {
+ synchronized (mCallbacks) {
+ for (DeviceCallback callback : mCallbacks) {
+ callback.onDeviceAttributesChanged();
+ }
+ }
+ }
+
/**
* Stop scan MediaDevice
*/
@@ -306,14 +314,12 @@ public class LocalMediaManager implements BluetoothCallback {
}
mCurrentConnectedDevice = connectDevice;
updatePhoneMediaDeviceSummary();
- dispatchDeviceListUpdate();
+ dispatchDeviceAttributesChanged();
}
@Override
public void onDeviceAttributesChanged() {
- addPhoneDeviceIfNecessary();
- removePhoneMediaDeviceIfNecessary();
- dispatchDeviceListUpdate();
+ dispatchDeviceAttributesChanged();
}
}
@@ -327,7 +333,7 @@ public class LocalMediaManager implements BluetoothCallback {
*
* @param devices MediaDevice list
*/
- void onDeviceListUpdate(List<MediaDevice> devices);
+ default void onDeviceListUpdate(List<MediaDevice> devices) {};
/**
* Callback for notifying the connected device is changed.
@@ -338,6 +344,12 @@ public class LocalMediaManager implements BluetoothCallback {
* {@link MediaDeviceState#STATE_CONNECTING},
* {@link MediaDeviceState#STATE_DISCONNECTED}
*/
- void onSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state);
+ default void onSelectedDeviceStateChanged(MediaDevice device,
+ @MediaDeviceState int state) {};
+
+ /**
+ * Callback for notifying the device attributes is changed.
+ */
+ default void onDeviceAttributesChanged() {};
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
index 98bb74ad0718..894aa78a978e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
@@ -355,7 +355,7 @@ public class LocalMediaManagerTest {
mLocalMediaManager.mMediaDeviceCallback.onConnectedDeviceChanged(TEST_DEVICE_ID_2);
assertThat(mLocalMediaManager.getCurrentConnectedDevice()).isEqualTo(device2);
- verify(mCallback).onDeviceListUpdate(any());
+ verify(mCallback).onDeviceAttributesChanged();
}
@Test
@@ -373,7 +373,7 @@ public class LocalMediaManagerTest {
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.mMediaDeviceCallback.onConnectedDeviceChanged(TEST_DEVICE_ID_1);
- verify(mCallback, never()).onDeviceListUpdate(any());
+ verify(mCallback, never()).onDeviceAttributesChanged();
}
@Test
@@ -382,6 +382,6 @@ public class LocalMediaManagerTest {
mLocalMediaManager.mMediaDeviceCallback.onDeviceAttributesChanged();
- verify(mCallback).onDeviceListUpdate(any());
+ verify(mCallback).onDeviceAttributesChanged();
}
}
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
index f40d3a160513..96a98dca8a5b 100644
--- a/packages/SettingsProvider/Android.bp
+++ b/packages/SettingsProvider/Android.bp
@@ -8,6 +8,7 @@ android_app {
libs: [
"telephony-common",
"ims-common",
+ "unsupportedappusage",
],
static_libs: [
"junit",
@@ -40,6 +41,7 @@ android_test {
libs: [
"android.test.base",
"android.test.mock",
+ "unsupportedappusage",
],
resource_dirs: ["res"],
aaptflags: [
diff --git a/packages/SettingsProvider/res/values/overlayable.xml b/packages/SettingsProvider/res/values/overlayable.xml
deleted file mode 100644
index dc41a77d0e2d..000000000000
--- a/packages/SettingsProvider/res/values/overlayable.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!-- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <overlayable name="SettingsToNotRestore">
- <policy type="product|system|vendor">
- <item type="array" name="restore_blocked_device_specific_settings" />
- <item type="array" name="restore_blocked_global_settings" />
- <item type="array" name="restore_blocked_secure_settings" />
- <item type="array" name="restore_blocked_system_settings" />
- </policy>
- </overlayable>
-</resources>
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 049b9f0e903e..5636cc8a3ca3 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -16,7 +16,7 @@
package android.provider.settings.backup;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.provider.Settings;
/** Information relating to the Secure settings which should be backed up */
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
index 89b19de8dfcb..3f5b0daa06a7 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
@@ -16,7 +16,7 @@
package android.provider.settings.backup;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.provider.Settings;
/** Information about the system settings to back up */
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index 94ab0f11927d..c5d4fa9f1b40 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -25,7 +25,7 @@ import static android.provider.settings.validators.SettingsValidators.URI_VALIDA
import static android.provider.settings.validators.SettingsValidators.VIBRATION_INTENSITY_VALIDATOR;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.hardware.display.ColorDisplayManager;
import android.os.BatteryManager;
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 0be853a81fb2..797b713d8614 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -20,7 +20,7 @@ java_defaults {
srcs: [
"src/**/*.java",
":framework-tethering-shared-srcs",
- ":net-module-utils-srcs",
+ ":tethering-module-utils-srcs",
":services-tethering-shared-srcs",
],
static_libs: [
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index a49ab85d2faf..11e57186c666 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -15,8 +15,6 @@
*/
package android.net;
-import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-
import android.annotation.NonNull;
import android.content.Context;
import android.net.ConnectivityManager.OnTetheringEventCallback;
@@ -52,6 +50,103 @@ public class TetheringManager {
private TetheringConfigurationParcel mTetheringConfiguration;
private TetherStatesParcel mTetherStatesParcel;
+ /**
+ * Broadcast Action: A tetherable connection has come or gone.
+ * Uses {@code TetheringManager.EXTRA_AVAILABLE_TETHER},
+ * {@code TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY},
+ * {@code TetheringManager.EXTRA_ACTIVE_TETHER}, and
+ * {@code TetheringManager.EXTRA_ERRORED_TETHER} to indicate
+ * the current state of tethering. Each include a list of
+ * interface names in that state (may be empty).
+ */
+ public static final String ACTION_TETHER_STATE_CHANGED =
+ "android.net.conn.TETHER_STATE_CHANGED";
+
+ /**
+ * gives a String[] listing all the interfaces configured for
+ * tethering and currently available for tethering.
+ */
+ public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
+
+ /**
+ * gives a String[] listing all the interfaces currently in local-only
+ * mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding)
+ */
+ public static final String EXTRA_ACTIVE_LOCAL_ONLY = "localOnlyArray";
+
+ /**
+ * gives a String[] listing all the interfaces currently tethered
+ * (ie, has DHCPv4 support and packets potentially forwarded/NATed)
+ */
+ public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
+
+ /**
+ * gives a String[] listing all the interfaces we tried to tether and
+ * failed. Use {@link #getLastTetherError} to find the error code
+ * for any interfaces listed here.
+ */
+ public static final String EXTRA_ERRORED_TETHER = "erroredArray";
+
+ /**
+ * Invalid tethering type.
+ * @see #startTethering.
+ */
+ public static final int TETHERING_INVALID = -1;
+
+ /**
+ * Wifi tethering type.
+ * @see #startTethering.
+ */
+ public static final int TETHERING_WIFI = 0;
+
+ /**
+ * USB tethering type.
+ * @see #startTethering.
+ */
+ public static final int TETHERING_USB = 1;
+
+ /**
+ * Bluetooth tethering type.
+ * @see #startTethering.
+ */
+ public static final int TETHERING_BLUETOOTH = 2;
+
+ /**
+ * Wifi P2p tethering type.
+ * Wifi P2p tethering is set through events automatically, and don't
+ * need to start from #startTethering.
+ */
+ public static final int TETHERING_WIFI_P2P = 3;
+
+ /**
+ * Extra used for communicating with the TetherService. Includes the type of tethering to
+ * enable if any.
+ */
+ public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
+
+ /**
+ * Extra used for communicating with the TetherService. Includes the type of tethering for
+ * which to cancel provisioning.
+ */
+ public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
+
+ /**
+ * Extra used for communicating with the TetherService. True to schedule a recheck of tether
+ * provisioning.
+ */
+ public static final String EXTRA_SET_ALARM = "extraSetAlarm";
+
+ /**
+ * Tells the TetherService to run a provision check now.
+ */
+ public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
+
+ /**
+ * Extra used for communicating with the TetherService. Contains the {@link ResultReceiver}
+ * which will receive provisioning results. Can be left empty.
+ */
+ public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
+
public static final int TETHER_ERROR_NO_ERROR = 0;
public static final int TETHER_ERROR_UNKNOWN_IFACE = 1;
public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2;
@@ -470,7 +565,7 @@ public class TetheringManager {
* failed. Re-attempting to tether may cause them to reset to the Tethered
* state. Alternatively, causing the interface to be destroyed and recreated
* may cause them to reset to the available state.
- * {@link ConnectivityManager#getLastTetherError} can be used to get more
+ * {@link TetheringManager#getLastTetherError} can be used to get more
* information on the cause of the errors.
*
* @return an array of 0 or more String indicating the interface names
diff --git a/packages/Tethering/jarjar-rules.txt b/packages/Tethering/jarjar-rules.txt
index d93531bac58e..c6efa41e580a 100644
--- a/packages/Tethering/jarjar-rules.txt
+++ b/packages/Tethering/jarjar-rules.txt
@@ -11,6 +11,7 @@ rule com.android.internal.util.MessageUtils* com.android.networkstack.tethering.
rule com.android.internal.util.Preconditions* com.android.networkstack.tethering.util.Preconditions@1
rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1
rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1
+rule com.android.internal.util.TrafficStatsConstants* com.android.networkstack.tethering.util.TrafficStatsConstants@1
rule android.net.LocalLog* com.android.networkstack.tethering.LocalLog@1
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index abfb33c7af9e..6ac467e39a9d 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -24,25 +24,24 @@ import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
import static android.net.util.NetworkConstants.asByte;
import static android.net.util.TetheringMessageBase.BASE_IPSERVER;
-import android.net.ConnectivityManager;
import android.net.INetd;
import android.net.INetworkStackStatusCallback;
import android.net.INetworkStatsService;
-import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.RouteInfo;
+import android.net.TetheringManager;
import android.net.dhcp.DhcpServerCallbacks;
import android.net.dhcp.DhcpServingParamsParcel;
import android.net.dhcp.DhcpServingParamsParcelExt;
import android.net.dhcp.IDhcpServer;
import android.net.ip.RouterAdvertisementDaemon.RaParams;
+import android.net.shared.NetdUtils;
+import android.net.shared.RouteUtils;
import android.net.util.InterfaceParams;
import android.net.util.InterfaceSet;
-import android.net.util.NetdService;
import android.net.util.SharedLog;
-import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
@@ -119,7 +118,7 @@ public class IpServer extends StateMachine {
*
* @param who the calling instance of IpServer
* @param state one of STATE_*
- * @param lastError one of ConnectivityManager.TETHER_ERROR_*
+ * @param lastError one of TetheringManager.TETHER_ERROR_*
*/
public void updateInterfaceState(IpServer who, int state, int lastError) { }
@@ -144,10 +143,6 @@ public class IpServer extends StateMachine {
return InterfaceParams.getByName(ifName);
}
- public INetd getNetdService() {
- return NetdService.getInstance();
- }
-
/** Create a DhcpServer instance to be used by IpServer. */
public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
DhcpServerCallbacks cb);
@@ -180,7 +175,6 @@ public class IpServer extends StateMachine {
private final State mUnavailableState;
private final SharedLog mLog;
- private final INetworkManagementService mNMService;
private final INetd mNetd;
private final INetworkStatsService mStatsService;
private final Callback mCallback;
@@ -210,15 +204,15 @@ public class IpServer extends StateMachine {
private int mDhcpServerStartIndex = 0;
private IDhcpServer mDhcpServer;
private RaParams mLastRaParams;
+ private LinkAddress mIpv4Address;
public IpServer(
String ifaceName, Looper looper, int interfaceType, SharedLog log,
- INetworkManagementService nMService, INetworkStatsService statsService,
- Callback callback, boolean usingLegacyDhcp, Dependencies deps) {
+ INetd netd, INetworkStatsService statsService, Callback callback,
+ boolean usingLegacyDhcp, Dependencies deps) {
super(ifaceName, looper);
mLog = log.forSubComponent(ifaceName);
- mNMService = nMService;
- mNetd = deps.getNetdService();
+ mNetd = netd;
mStatsService = statsService;
mCallback = callback;
mInterfaceCtrl = new InterfaceController(ifaceName, mNetd, mLog);
@@ -228,7 +222,7 @@ public class IpServer extends StateMachine {
mUsingLegacyDhcp = usingLegacyDhcp;
mDeps = deps;
resetLinkProperties();
- mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
mServingMode = STATE_AVAILABLE;
mInitialState = new InitialState();
@@ -249,7 +243,7 @@ public class IpServer extends StateMachine {
}
/**
- * Tethering downstream type. It would be one of ConnectivityManager#TETHERING_*.
+ * Tethering downstream type. It would be one of TetheringManager#TETHERING_*.
*/
public int interfaceType() {
return mInterfaceType;
@@ -347,13 +341,13 @@ public class IpServer extends StateMachine {
}
});
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw new IllegalStateException(e);
}
});
}
private void handleError() {
- mLastError = ConnectivityManager.TETHER_ERROR_DHCPSERVER_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR;
transitionTo(mInitialState);
}
}
@@ -388,14 +382,15 @@ public class IpServer extends StateMachine {
public void callback(int statusCode) {
if (statusCode != STATUS_SUCCESS) {
mLog.e("Error stopping DHCP server: " + statusCode);
- mLastError = ConnectivityManager.TETHER_ERROR_DHCPSERVER_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR;
// Not much more we can do here
}
}
});
mDhcpServer = null;
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ mLog.e("Error stopping DHCP", e);
+ // Not much more we can do here
}
}
}
@@ -414,85 +409,69 @@ public class IpServer extends StateMachine {
// NOTE: All of configureIPv4() will be refactored out of existence
// into calls to InterfaceController, shared with startIPv4().
mInterfaceCtrl.clearIPv4Address();
+ mIpv4Address = null;
}
- // TODO: Refactor this in terms of calls to InterfaceController.
private boolean configureIPv4(boolean enabled) {
if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")");
// TODO: Replace this hard-coded information with dynamically selected
// config passed down to us by a higher layer IP-coordinating element.
- String ipAsString = null;
+ final Inet4Address srvAddr;
int prefixLen = 0;
- if (mInterfaceType == ConnectivityManager.TETHERING_USB) {
- ipAsString = USB_NEAR_IFACE_ADDR;
- prefixLen = USB_PREFIX_LENGTH;
- } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
- ipAsString = getRandomWifiIPv4Address();
- prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
- } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI_P2P) {
- ipAsString = WIFI_P2P_IFACE_ADDR;
- prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH;
- } else {
- // BT configures the interface elsewhere: only start DHCP.
- final Inet4Address srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR);
- return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
- }
-
- final LinkAddress linkAddr;
try {
- final InterfaceConfiguration ifcg = mNMService.getInterfaceConfig(mIfaceName);
- if (ifcg == null) {
- mLog.e("Received null interface config");
- return false;
- }
-
- InetAddress addr = parseNumericAddress(ipAsString);
- linkAddr = new LinkAddress(addr, prefixLen);
- ifcg.setLinkAddress(linkAddr);
- if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
- // The WiFi stack has ownership of the interface up/down state.
- // It is unclear whether the Bluetooth or USB stacks will manage their own
- // state.
- ifcg.ignoreInterfaceUpDownStatus();
+ if (mInterfaceType == TetheringManager.TETHERING_USB) {
+ srvAddr = (Inet4Address) parseNumericAddress(USB_NEAR_IFACE_ADDR);
+ prefixLen = USB_PREFIX_LENGTH;
+ } else if (mInterfaceType == TetheringManager.TETHERING_WIFI) {
+ srvAddr = (Inet4Address) parseNumericAddress(getRandomWifiIPv4Address());
+ prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
+ } else if (mInterfaceType == TetheringManager.TETHERING_WIFI_P2P) {
+ srvAddr = (Inet4Address) parseNumericAddress(WIFI_P2P_IFACE_ADDR);
+ prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH;
} else {
- if (enabled) {
- ifcg.setInterfaceUp();
- } else {
- ifcg.setInterfaceDown();
- }
+ // BT configures the interface elsewhere: only start DHCP.
+ // TODO: make all tethering types behave the same way, and delete the bluetooth
+ // code that calls into NetworkManagementService directly.
+ srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR);
+ mIpv4Address = new LinkAddress(srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
+ return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
}
- ifcg.clearFlag("running");
+ mIpv4Address = new LinkAddress(srvAddr, prefixLen);
+ } catch (IllegalArgumentException e) {
+ mLog.e("Error selecting ipv4 address", e);
+ if (!enabled) stopDhcp();
+ return false;
+ }
- // TODO: this may throw if the interface is already gone. Do proper handling and
- // simplify the DHCP server start/stop.
- mNMService.setInterfaceConfig(mIfaceName, ifcg);
+ final Boolean setIfaceUp;
+ if (mInterfaceType == TetheringManager.TETHERING_WIFI) {
+ // The WiFi stack has ownership of the interface up/down state.
+ // It is unclear whether the Bluetooth or USB stacks will manage their own
+ // state.
+ setIfaceUp = null;
+ } else {
+ setIfaceUp = enabled;
+ }
+ if (!mInterfaceCtrl.setInterfaceConfiguration(mIpv4Address, setIfaceUp)) {
+ mLog.e("Error configuring interface");
+ if (!enabled) stopDhcp();
+ return false;
+ }
- if (!configureDhcp(enabled, (Inet4Address) addr, prefixLen)) {
- return false;
- }
- } catch (Exception e) {
- mLog.e("Error configuring interface " + e);
- if (!enabled) {
- try {
- // Calling stopDhcp several times is fine
- stopDhcp();
- } catch (Exception dhcpError) {
- mLog.e("Error stopping DHCP", dhcpError);
- }
- }
+ if (!configureDhcp(enabled, srvAddr, prefixLen)) {
return false;
}
// Directly-connected route.
- final IpPrefix ipv4Prefix = new IpPrefix(linkAddr.getAddress(),
- linkAddr.getPrefixLength());
+ final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(),
+ mIpv4Address.getPrefixLength());
final RouteInfo route = new RouteInfo(ipv4Prefix, null, null, RTN_UNICAST);
if (enabled) {
- mLinkProperties.addLinkAddress(linkAddr);
+ mLinkProperties.addLinkAddress(mIpv4Address);
mLinkProperties.addRoute(route);
} else {
- mLinkProperties.removeLinkAddress(linkAddr);
+ mLinkProperties.removeLinkAddress(mIpv4Address);
mLinkProperties.removeRoute(route);
}
return true;
@@ -584,14 +563,12 @@ public class IpServer extends StateMachine {
if (!deprecatedPrefixes.isEmpty()) {
final ArrayList<RouteInfo> toBeRemoved =
getLocalRoutesFor(mIfaceName, deprecatedPrefixes);
- try {
- final int removalFailures = mNMService.removeRoutesFromLocalNetwork(toBeRemoved);
- if (removalFailures > 0) {
- mLog.e(String.format("Failed to remove %d IPv6 routes from local table.",
- removalFailures));
- }
- } catch (RemoteException e) {
- mLog.e("Failed to remove IPv6 routes from local table: " + e);
+ // Remove routes from local network.
+ final int removalFailures = RouteUtils.removeRoutesFromLocalNetwork(
+ mNetd, toBeRemoved);
+ if (removalFailures > 0) {
+ mLog.e(String.format("Failed to remove %d IPv6 routes from local table.",
+ removalFailures));
}
for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route);
@@ -608,13 +585,18 @@ public class IpServer extends StateMachine {
final ArrayList<RouteInfo> toBeAdded =
getLocalRoutesFor(mIfaceName, addedPrefixes);
try {
- // It's safe to call addInterfaceToLocalNetwork() even if
- // the interface is already in the local_network. Note also
- // that adding routes that already exist does not cause an
- // error (EEXIST is silently ignored).
- mNMService.addInterfaceToLocalNetwork(mIfaceName, toBeAdded);
- } catch (Exception e) {
- mLog.e("Failed to add IPv6 routes to local table: " + e);
+ // It's safe to call networkAddInterface() even if
+ // the interface is already in the local_network.
+ mNetd.networkAddInterface(INetd.LOCAL_NET_ID, mIfaceName);
+ try {
+ // Add routes from local network. Note that adding routes that
+ // already exist does not cause an error (EEXIST is silently ignored).
+ RouteUtils.addRoutesToLocalNetwork(mNetd, mIfaceName, toBeAdded);
+ } catch (IllegalStateException e) {
+ mLog.e("Failed to add IPv6 routes to local table: " + e);
+ }
+ } catch (ServiceSpecificException | RemoteException e) {
+ mLog.e("Failed to add " + mIfaceName + " to local table: ", e);
}
for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route);
@@ -728,7 +710,7 @@ public class IpServer extends StateMachine {
logMessage(this, message.what);
switch (message.what) {
case CMD_TETHER_REQUESTED:
- mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
switch (message.arg1) {
case STATE_LOCAL_ONLY:
transitionTo(mLocalHotspotState);
@@ -757,15 +739,17 @@ public class IpServer extends StateMachine {
@Override
public void enter() {
if (!startIPv4()) {
- mLastError = ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
return;
}
try {
- mNMService.tetherInterface(mIfaceName);
- } catch (Exception e) {
+ final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(),
+ mIpv4Address.getPrefixLength());
+ NetdUtils.tetherInterface(mNetd, mIfaceName, ipv4Prefix);
+ } catch (RemoteException | ServiceSpecificException e) {
mLog.e("Error Tethering: " + e);
- mLastError = ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
return;
}
@@ -784,9 +768,9 @@ public class IpServer extends StateMachine {
stopIPv6();
try {
- mNMService.untetherInterface(mIfaceName);
- } catch (Exception e) {
- mLastError = ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
+ NetdUtils.untetherInterface(mNetd, mIfaceName);
+ } catch (RemoteException | ServiceSpecificException e) {
+ mLastError = TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
mLog.e("Failed to untether interface: " + e);
}
@@ -816,7 +800,7 @@ public class IpServer extends StateMachine {
case CMD_START_TETHERING_ERROR:
case CMD_STOP_TETHERING_ERROR:
case CMD_SET_DNS_FORWARDERS_ERROR:
- mLastError = ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_MASTER_ERROR;
transitionTo(mInitialState);
break;
default:
@@ -835,7 +819,7 @@ public class IpServer extends StateMachine {
@Override
public void enter() {
super.enter();
- if (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+ if (mLastError != TetheringManager.TETHER_ERROR_NO_ERROR) {
transitionTo(mInitialState);
}
@@ -871,7 +855,7 @@ public class IpServer extends StateMachine {
@Override
public void enter() {
super.enter();
- if (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+ if (mLastError != TetheringManager.TETHER_ERROR_NO_ERROR) {
transitionTo(mInitialState);
}
@@ -901,17 +885,17 @@ public class IpServer extends StateMachine {
// About to tear down NAT; gather remaining statistics.
mStatsService.forceUpdate();
} catch (Exception e) {
- if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString());
+ mLog.e("Exception in forceUpdate: " + e.toString());
}
try {
- mNMService.stopInterfaceForwarding(mIfaceName, upstreamIface);
- } catch (Exception e) {
- if (VDBG) Log.e(TAG, "Exception in removeInterfaceForward: " + e.toString());
+ mNetd.ipfwdRemoveInterfaceForward(mIfaceName, upstreamIface);
+ } catch (RemoteException | ServiceSpecificException e) {
+ mLog.e("Exception in ipfwdRemoveInterfaceForward: " + e.toString());
}
try {
- mNMService.disableNat(mIfaceName, upstreamIface);
- } catch (Exception e) {
- if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString());
+ mNetd.tetherRemoveForward(mIfaceName, upstreamIface);
+ } catch (RemoteException | ServiceSpecificException e) {
+ mLog.e("Exception in disableNat: " + e.toString());
}
}
@@ -947,12 +931,12 @@ public class IpServer extends StateMachine {
for (String ifname : added) {
try {
- mNMService.enableNat(mIfaceName, ifname);
- mNMService.startInterfaceForwarding(mIfaceName, ifname);
- } catch (Exception e) {
- mLog.e("Exception enabling NAT: " + e);
+ mNetd.tetherAddForward(mIfaceName, ifname);
+ mNetd.ipfwdAddInterfaceForward(mIfaceName, ifname);
+ } catch (RemoteException | ServiceSpecificException e) {
+ mLog.e("Exception enabling NAT: " + e.toString());
cleanupUpstream();
- mLastError = ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_ENABLE_NAT_ERROR;
transitionTo(mInitialState);
return true;
}
@@ -997,7 +981,7 @@ public class IpServer extends StateMachine {
class UnavailableState extends State {
@Override
public void enter() {
- mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
sendInterfaceState(STATE_UNAVAILABLE);
}
}
diff --git a/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java b/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
index bba61d72d8d6..6f017dcb623f 100644
--- a/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
+++ b/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
@@ -668,7 +668,7 @@ public class RouterAdvertisementDaemon {
}
private final class UnicastResponder extends Thread {
- private final InetSocketAddress mSolicitor = new InetSocketAddress();
+ private final InetSocketAddress mSolicitor = new InetSocketAddress(0);
// The recycled buffer for receiving Router Solicitations from clients.
// If the RS is larger than IPV6_MIN_MTU the packets are truncated.
// This is fine since currently only byte 0 is examined anyway.
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
index 7e685fbe97f1..4e2a2c1c7af7 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
@@ -16,16 +16,16 @@
package com.android.server.connectivity.tethering;
-import static android.net.ConnectivityManager.EXTRA_ADD_TETHER_TYPE;
-import static android.net.ConnectivityManager.EXTRA_PROVISION_CALLBACK;
-import static android.net.ConnectivityManager.EXTRA_RUN_PROVISION;
-import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
-import static android.net.ConnectivityManager.TETHERING_INVALID;
-import static android.net.ConnectivityManager.TETHERING_USB;
-import static android.net.ConnectivityManager.TETHERING_WIFI;
-import static android.net.ConnectivityManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
-import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
+import static android.net.TetheringManager.EXTRA_ADD_TETHER_TYPE;
+import static android.net.TetheringManager.EXTRA_PROVISION_CALLBACK;
+import static android.net.TetheringManager.EXTRA_RUN_PROVISION;
+import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_INVALID;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_PROVISION_FAILED;
import static com.android.internal.R.string.config_wifi_tether_enable;
@@ -59,7 +59,7 @@ import java.io.PrintWriter;
/**
* Re-check tethering provisioning for enabled downstream tether types.
- * Reference ConnectivityManager.TETHERING_{@code *} for each tether type.
+ * Reference TetheringManager.TETHERING_{@code *} for each tether type.
*
* All methods of this class must be accessed from the thread of tethering
* state machine.
@@ -86,9 +86,9 @@ public class EntitlementManager {
private static final int EVENT_GET_ENTITLEMENT_VALUE = 4;
// The ArraySet contains enabled downstream types, ex:
- // {@link ConnectivityManager.TETHERING_WIFI}
- // {@link ConnectivityManager.TETHERING_USB}
- // {@link ConnectivityManager.TETHERING_BLUETOOTH}
+ // {@link TetheringManager.TETHERING_WIFI}
+ // {@link TetheringManager.TETHERING_USB}
+ // {@link TetheringManager.TETHERING_BLUETOOTH}
private final ArraySet<Integer> mCurrentTethers;
private final Context mContext;
private final int mPermissionChangeMessageCode;
@@ -96,8 +96,8 @@ public class EntitlementManager {
private final SparseIntArray mEntitlementCacheValue;
private final EntitlementHandler mHandler;
private final StateMachine mTetherMasterSM;
- // Key: ConnectivityManager.TETHERING_*(downstream).
- // Value: ConnectivityManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result).
+ // Key: TetheringManager.TETHERING_*(downstream).
+ // Value: TetheringManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result).
private final SparseIntArray mCellularPermitted;
private PendingIntent mProvisioningRecheckAlarm;
private boolean mCellularUpstreamPermitted = true;
@@ -133,7 +133,7 @@ public class EntitlementManager {
/**
* Ui entitlement check fails in |downstream|.
*
- * @param downstream tethering type from ConnectivityManager.TETHERING_{@code *}.
+ * @param downstream tethering type from TetheringManager.TETHERING_{@code *}.
*/
void onUiEntitlementFailed(int downstream);
}
@@ -169,7 +169,7 @@ public class EntitlementManager {
* This is called when tethering starts.
* Launch provisioning app if upstream is cellular.
*
- * @param downstreamType tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param downstreamType tethering type from TetheringManager.TETHERING_{@code *}
* @param showProvisioningUi a boolean indicating whether to show the
* provisioning app UI if there is one.
*/
@@ -210,7 +210,7 @@ public class EntitlementManager {
/**
* Tell EntitlementManager that a given type of tethering has been disabled
*
- * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param type tethering type from TetheringManager.TETHERING_{@code *}
*/
public void stopProvisioningIfNeeded(int type) {
mHandler.sendMessage(mHandler.obtainMessage(EVENT_STOP_PROVISIONING, type, 0));
@@ -296,7 +296,7 @@ public class EntitlementManager {
/**
* Re-check tethering provisioning for all enabled tether types.
- * Reference ConnectivityManager.TETHERING_{@code *} for each tether type.
+ * Reference TetheringManager.TETHERING_{@code *} for each tether type.
*
* @param config an object that encapsulates the various tethering configuration elements.
* Note: this method is only called from TetherMaster on the handler thread.
@@ -363,7 +363,7 @@ public class EntitlementManager {
/**
* Run no UI tethering provisioning check.
- * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param type tethering type from TetheringManager.TETHERING_{@code *}
* @param subId default data subscription ID.
*/
@VisibleForTesting
@@ -390,7 +390,7 @@ public class EntitlementManager {
/**
* Run the UI-enabled tethering provisioning check.
- * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param type tethering type from TetheringManager.TETHERING_{@code *}
* @param subId default data subscription ID.
* @param receiver to receive entitlement check result.
*/
@@ -398,7 +398,7 @@ public class EntitlementManager {
protected void runUiTetherProvisioning(int type, int subId, ResultReceiver receiver) {
if (DBG) mLog.i("runUiTetherProvisioning: " + type);
- Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING);
+ Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING_UI);
intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
intent.putExtra(EXTRA_SUBID, subId);
@@ -461,7 +461,7 @@ public class EntitlementManager {
* Add the mapping between provisioning result and tethering type.
* Notify UpstreamNetworkMonitor if Cellular permission changes.
*
- * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param type tethering type from TetheringManager.TETHERING_{@code *}
* @param resultCode Provisioning result
*/
protected void addDownstreamMapping(int type, int resultCode) {
@@ -476,7 +476,7 @@ public class EntitlementManager {
/**
* Remove the mapping for input tethering type.
- * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param type tethering type from TetheringManager.TETHERING_{@code *}
*/
protected void removeDownstreamMapping(int type) {
mLog.i("removeDownstreamMapping: " + type);
@@ -625,7 +625,7 @@ public class EntitlementManager {
/**
* Update the last entitlement value to internal cache
*
- * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param type tethering type from TetheringManager.TETHERING_{@code *}
* @param resultCode last entitlement value
* @return the last updated entitlement value
*/
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
index 38fa91e7387e..ce7c2a669f0a 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
@@ -279,7 +279,7 @@ public class OffloadController {
entry.iface = kv.getKey();
entry.rxBytes = value.rxBytes;
entry.txBytes = value.txBytes;
- stats.addValues(entry);
+ stats.addEntry(entry);
}
return stats;
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index 5b267046a851..d6abfb922a9c 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -20,23 +20,23 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
-import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
-import static android.net.ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY;
-import static android.net.ConnectivityManager.EXTRA_ACTIVE_TETHER;
-import static android.net.ConnectivityManager.EXTRA_AVAILABLE_TETHER;
-import static android.net.ConnectivityManager.EXTRA_ERRORED_TETHER;
import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
-import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
-import static android.net.ConnectivityManager.TETHERING_INVALID;
-import static android.net.ConnectivityManager.TETHERING_USB;
-import static android.net.ConnectivityManager.TETHERING_WIFI;
-import static android.net.ConnectivityManager.TETHERING_WIFI_P2P;
-import static android.net.ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL;
-import static android.net.ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
-import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
+import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
+import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY;
+import static android.net.TetheringManager.EXTRA_ACTIVE_TETHER;
+import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER;
+import static android.net.TetheringManager.EXTRA_ERRORED_TETHER;
+import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_INVALID;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHERING_WIFI_P2P;
+import static android.net.TetheringManager.TETHER_ERROR_MASTER_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
+import static android.net.TetheringManager.TETHER_ERROR_UNAVAIL_IFACE;
+import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
import static android.net.util.TetheringMessageBase.BASE_MASTER;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
@@ -71,10 +71,10 @@ import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkInfo;
-import android.net.NetworkUtils;
import android.net.TetherStatesParcel;
import android.net.TetheringConfigurationParcel;
import android.net.ip.IpServer;
+import android.net.shared.NetdUtils;
import android.net.util.BaseNetdUnsolicitedEventListener;
import android.net.util.InterfaceSet;
import android.net.util.PrefixUtils;
@@ -87,12 +87,12 @@ import android.net.wifi.p2p.WifiP2pManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
-import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.os.ServiceSpecificException;
import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.PhoneStateListener;
@@ -102,6 +102,9 @@ import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
@@ -139,6 +142,8 @@ public class Tethering {
};
private static final SparseArray<String> sMagicDecoderRing =
MessageUtils.findMessageNames(sMessageClasses);
+ // Keep in sync with NETID_UNSET in system/netd/include/netid_client.h
+ private static final int NETID_UNSET = 0;
private static class TetherState {
public final IpServer ipServer;
@@ -172,8 +177,6 @@ public class Tethering {
private final Context mContext;
private final ArrayMap<String, TetherState> mTetherStates;
private final BroadcastReceiver mStateReceiver;
- // Stopship: replace mNMService before production.
- private final INetworkManagementService mNMService;
private final INetworkStatsService mStatsService;
private final INetworkPolicyManager mPolicyManager;
private final Looper mLooper;
@@ -210,7 +213,6 @@ public class Tethering {
mLog.mark("Tethering.constructed");
mDeps = deps;
mContext = mDeps.getContext();
- mNMService = mDeps.getINetworkManagementService();
mStatsService = mDeps.getINetworkStatsService();
mPolicyManager = mDeps.getINetworkPolicyManager();
mNetd = mDeps.getINetd(mContext);
@@ -225,10 +227,9 @@ public class Tethering {
mHandler = mTetherMasterSM.getHandler();
mOffloadController = new OffloadController(mHandler,
- mDeps.getOffloadHardwareInterface(mHandler, mLog),
- mContext.getContentResolver(), mNMService,
- mLog);
- mUpstreamNetworkMonitor = deps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog,
+ mDeps.getOffloadHardwareInterface(mHandler, mLog), mContext.getContentResolver(),
+ mDeps.getINetworkManagementService(), mLog);
+ mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog,
TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
mForwardedDownstreams = new HashSet<>();
@@ -289,13 +290,6 @@ public class Tethering {
filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED);
mContext.registerReceiver(mStateReceiver, filter, null, handler);
-
- filter = new IntentFilter();
- filter.addAction(Intent.ACTION_MEDIA_SHARED);
- filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
- filter.addDataScheme("file");
- mContext.registerReceiver(mStateReceiver, filter, null, handler);
-
}
private class TetheringThreadExecutor implements Executor {
@@ -421,7 +415,6 @@ public class Tethering {
}
}
-
void interfaceRemoved(String iface) {
if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
synchronized (mPublicSync) {
@@ -1022,8 +1015,8 @@ public class Tethering {
String[] ifaces = null;
try {
- ifaces = mNMService.listInterfaces();
- } catch (Exception e) {
+ ifaces = mNetd.interfaceGetList();
+ } catch (RemoteException | ServiceSpecificException e) {
Log.e(TAG, "Error listing Interfaces", e);
return;
}
@@ -1282,25 +1275,25 @@ public class Tethering {
protected boolean turnOnMasterTetherSettings() {
final TetheringConfiguration cfg = mConfig;
try {
- mNMService.setIpForwardingEnabled(true);
- } catch (Exception e) {
+ mNetd.ipfwdEnableForwarding(TAG);
+ } catch (RemoteException | ServiceSpecificException e) {
mLog.e(e);
transitionTo(mSetIpForwardingEnabledErrorState);
return false;
}
+
// TODO: Randomize DHCPv4 ranges, especially in hotspot mode.
// Legacy DHCP server is disabled if passed an empty ranges array
final String[] dhcpRanges = cfg.enableLegacyDhcpServer
- ? cfg.legacyDhcpRanges
- : new String[0];
+ ? cfg.legacyDhcpRanges : new String[0];
try {
- // TODO: Find a more accurate method name (startDHCPv4()?).
- mNMService.startTethering(dhcpRanges);
- } catch (Exception e) {
+ NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges);
+ } catch (RemoteException | ServiceSpecificException e) {
try {
- mNMService.stopTethering();
- mNMService.startTethering(dhcpRanges);
- } catch (Exception ee) {
+ // Stop and retry.
+ mNetd.tetherStop();
+ NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges);
+ } catch (RemoteException | ServiceSpecificException ee) {
mLog.e(ee);
transitionTo(mStartTetheringErrorState);
return false;
@@ -1312,15 +1305,15 @@ public class Tethering {
protected boolean turnOffMasterTetherSettings() {
try {
- mNMService.stopTethering();
- } catch (Exception e) {
+ mNetd.tetherStop();
+ } catch (RemoteException | ServiceSpecificException e) {
mLog.e(e);
transitionTo(mStopTetheringErrorState);
return false;
}
try {
- mNMService.setIpForwardingEnabled(false);
- } catch (Exception e) {
+ mNetd.ipfwdDisableForwarding(TAG);
+ } catch (RemoteException | ServiceSpecificException e) {
mLog.e(e);
transitionTo(mSetIpForwardingDisabledErrorState);
return false;
@@ -1383,19 +1376,25 @@ public class Tethering {
protected void setDnsForwarders(final Network network, final LinkProperties lp) {
// TODO: Set v4 and/or v6 DNS per available connectivity.
- String[] dnsServers = mConfig.defaultIPv4DNS;
final Collection<InetAddress> dnses = lp.getDnsServers();
// TODO: Properly support the absence of DNS servers.
+ final String[] dnsServers;
if (dnses != null && !dnses.isEmpty()) {
- // TODO: remove this invocation of NetworkUtils.makeStrings().
- dnsServers = NetworkUtils.makeStrings(dnses);
+ dnsServers = new String[dnses.size()];
+ int i = 0;
+ for (InetAddress dns : dnses) {
+ dnsServers[i++] = dns.getHostAddress();
+ }
+ } else {
+ dnsServers = mConfig.defaultIPv4DNS;
}
+ final int netId = (network != null) ? network.netId : NETID_UNSET;
try {
- mNMService.setDnsForwarders(network, dnsServers);
+ mNetd.tetherDnsSet(netId, dnsServers);
mLog.log(String.format(
"SET DNS forwarders: network=%s dnsServers=%s",
network, Arrays.toString(dnsServers)));
- } catch (Exception e) {
+ } catch (RemoteException | ServiceSpecificException e) {
// TODO: Investigate how this can fail and what exactly
// happens if/when such failures occur.
mLog.e("setting DNS forwarders failed, " + e);
@@ -1698,8 +1697,8 @@ public class Tethering {
Log.e(TAG, "Error in startTethering");
notify(IpServer.CMD_START_TETHERING_ERROR);
try {
- mNMService.setIpForwardingEnabled(false);
- } catch (Exception e) { }
+ mNetd.ipfwdDisableForwarding(TAG);
+ } catch (RemoteException | ServiceSpecificException e) { }
}
}
@@ -1709,8 +1708,8 @@ public class Tethering {
Log.e(TAG, "Error in stopTethering");
notify(IpServer.CMD_STOP_TETHERING_ERROR);
try {
- mNMService.setIpForwardingEnabled(false);
- } catch (Exception e) { }
+ mNetd.ipfwdDisableForwarding(TAG);
+ } catch (RemoteException | ServiceSpecificException e) { }
}
}
@@ -1720,11 +1719,11 @@ public class Tethering {
Log.e(TAG, "Error in setDnsForwarders");
notify(IpServer.CMD_SET_DNS_FORWARDERS_ERROR);
try {
- mNMService.stopTethering();
- } catch (Exception e) { }
+ mNetd.tetherStop();
+ } catch (RemoteException | ServiceSpecificException e) { }
try {
- mNMService.setIpForwardingEnabled(false);
- } catch (Exception e) { }
+ mNetd.ipfwdDisableForwarding(TAG);
+ } catch (RemoteException | ServiceSpecificException e) { }
}
}
@@ -1884,7 +1883,7 @@ public class Tethering {
}
}
- void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) {
// Binder.java closes the resource for us.
@SuppressWarnings("resource")
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
@@ -2065,7 +2064,7 @@ public class Tethering {
mLog.log("adding TetheringInterfaceStateMachine for: " + iface);
final TetherState tetherState = new TetherState(
- new IpServer(iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
+ new IpServer(iface, mLooper, interfaceType, mLog, mNetd, mStatsService,
makeControlCallback(), mConfig.enableLegacyDhcpServer,
mDeps.getIpServerDependencies()));
mTetherStates.put(iface, tetherState);
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 490614b03149..397ba8ada551 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -37,7 +37,6 @@ import static com.android.internal.R.string.config_mobile_hotspot_provision_app_
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
-import android.net.ConnectivityManager;
import android.net.TetheringConfigurationParcel;
import android.net.util.SharedLog;
import android.provider.Settings;
@@ -179,8 +178,8 @@ public class TetheringConfiguration {
pw.print("chooseUpstreamAutomatically: ");
pw.println(chooseUpstreamAutomatically);
- dumpStringArray(pw, "preferredUpstreamIfaceTypes",
- preferredUpstreamNames(preferredUpstreamIfaceTypes));
+ pw.print("legacyPreredUpstreamIfaceTypes: ");
+ pw.println(Arrays.toString(toIntArray(preferredUpstreamIfaceTypes)));
dumpStringArray(pw, "legacyDhcpRanges", legacyDhcpRanges);
dumpStringArray(pw, "defaultIPv4DNS", defaultIPv4DNS);
@@ -205,7 +204,7 @@ public class TetheringConfiguration {
sj.add(String.format("isDunRequired:%s", isDunRequired));
sj.add(String.format("chooseUpstreamAutomatically:%s", chooseUpstreamAutomatically));
sj.add(String.format("preferredUpstreamIfaceTypes:%s",
- makeString(preferredUpstreamNames(preferredUpstreamIfaceTypes))));
+ toIntArray(preferredUpstreamIfaceTypes)));
sj.add(String.format("provisioningApp:%s", makeString(provisioningApp)));
sj.add(String.format("provisioningAppNoUi:%s", provisioningAppNoUi));
sj.add(String.format("enableLegacyDhcpServer:%s", enableLegacyDhcpServer));
@@ -234,21 +233,6 @@ public class TetheringConfiguration {
return sj.toString();
}
- private static String[] preferredUpstreamNames(Collection<Integer> upstreamTypes) {
- String[] upstreamNames = null;
-
- if (upstreamTypes != null) {
- upstreamNames = new String[upstreamTypes.size()];
- int i = 0;
- for (Integer netType : upstreamTypes) {
- upstreamNames[i] = ConnectivityManager.getNetworkTypeName(netType);
- i++;
- }
- }
-
- return upstreamNames;
- }
-
/** Check whether dun is required. */
public static boolean checkDunRequired(Context ctx) {
final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE);
@@ -388,6 +372,15 @@ public class TetheringConfiguration {
return false;
}
+ private static int[] toIntArray(Collection<Integer> values) {
+ final int[] result = new int[values.size()];
+ int index = 0;
+ for (Integer value : values) {
+ result[index++] = value;
+ }
+ return result;
+ }
+
/**
* Convert this TetheringConfiguration to a TetheringConfigurationParcel.
*/
@@ -400,12 +393,7 @@ public class TetheringConfiguration {
parcel.isDunRequired = isDunRequired;
parcel.chooseUpstreamAutomatically = chooseUpstreamAutomatically;
- int[] preferredTypes = new int[preferredUpstreamIfaceTypes.size()];
- int index = 0;
- for (Integer type : preferredUpstreamIfaceTypes) {
- preferredTypes[index++] = type;
- }
- parcel.preferredUpstreamIfaceTypes = preferredTypes;
+ parcel.preferredUpstreamIfaceTypes = toIntArray(preferredUpstreamIfaceTypes);
parcel.legacyDhcpRanges = legacyDhcpRanges;
parcel.defaultIPv4DNS = defaultIPv4DNS;
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java
index 6334c20c2acc..d5cdd8a004dc 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java
@@ -22,14 +22,17 @@ import android.net.NetworkCapabilities;
import android.net.RouteInfo;
import android.net.util.InterfaceSet;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
import java.net.InetAddress;
+import java.net.UnknownHostException;
/**
* @hide
*/
public final class TetheringInterfaceUtils {
+ private static final InetAddress IN6ADDR_ANY = getByAddress(
+ new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
+ private static final InetAddress INADDR_ANY = getByAddress(new byte[] {0, 0, 0, 0});
+
/**
* Get upstream interfaces for tethering based on default routes for IPv4/IPv6.
* @return null if there is no usable interface, or a set of at least one interface otherwise.
@@ -40,7 +43,7 @@ public final class TetheringInterfaceUtils {
}
final LinkProperties lp = ns.linkProperties;
- final String if4 = getInterfaceForDestination(lp, Inet4Address.ANY);
+ final String if4 = getInterfaceForDestination(lp, INADDR_ANY);
final String if6 = getIPv6Interface(ns);
return (if4 == null && if6 == null) ? null : new InterfaceSet(if4, if6);
@@ -76,7 +79,7 @@ public final class TetheringInterfaceUtils {
&& ns.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
return canTether
- ? getInterfaceForDestination(ns.linkProperties, Inet6Address.ANY)
+ ? getInterfaceForDestination(ns.linkProperties, IN6ADDR_ANY)
: null;
}
@@ -86,4 +89,12 @@ public final class TetheringInterfaceUtils {
: null;
return (ri != null) ? ri.getInterface() : null;
}
+
+ private static InetAddress getByAddress(final byte[] addr) {
+ try {
+ return InetAddress.getByAddress(null, addr);
+ } catch (UnknownHostException e) {
+ throw new AssertionError("illegal address length" + addr.length);
+ }
+ }
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
index 775484eabfa3..e4e4a090603d 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
@@ -26,11 +26,11 @@ import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
-import android.net.ConnectivityManager;
import android.net.IIntResultListener;
import android.net.INetworkStackConnector;
import android.net.ITetheringConnector;
import android.net.ITetheringEventCallback;
+import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.dhcp.DhcpServerCallbacks;
import android.net.dhcp.DhcpServingParamsParcel;
@@ -307,9 +307,15 @@ public class TetheringService extends Service {
mDeps = new TetheringDependencies() {
@Override
public NetworkRequest getDefaultNetworkRequest() {
- ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
- Context.CONNECTIVITY_SERVICE);
- return cm.getDefaultRequest();
+ // TODO: b/147280869, add a proper system API to replace this.
+ final NetworkRequest trackDefaultRequest = new NetworkRequest.Builder()
+ .clearCapabilities()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .build();
+ return trackDefaultRequest;
}
@Override
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index 22150f623a35..fe3f51700df9 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -19,7 +19,6 @@ package com.android.server.connectivity.tethering;
import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
import static android.net.ConnectivityManager.TYPE_NONE;
-import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@@ -35,7 +34,6 @@ import android.net.NetworkRequest;
import android.net.util.PrefixUtils;
import android.net.util.SharedLog;
import android.os.Handler;
-import android.os.Process;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -130,15 +128,15 @@ public class UpstreamNetworkMonitor {
*/
public void startTrackDefaultNetwork(NetworkRequest defaultNetworkRequest,
EntitlementManager entitle) {
- // This is not really a "request", just a way of tracking the system default network.
- // It's guaranteed not to actually bring up any networks because it's the same request
- // as the ConnectivityService default request, and thus shares fate with it. We can't
- // use registerDefaultNetworkCallback because it will not track the system default
- // network if there is a VPN that applies to our UID.
+
+ // defaultNetworkRequest is not really a "request", just a way of tracking the system
+ // default network. It's guaranteed not to actually bring up any networks because it's
+ // the should be the same request as the ConnectivityService default request, and thus
+ // shares fate with it. We can't use registerDefaultNetworkCallback because it will not
+ // track the system default network if there is a VPN that applies to our UID.
if (mDefaultNetworkCallback == null) {
- final NetworkRequest trackDefaultRequest = new NetworkRequest(defaultNetworkRequest);
mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_DEFAULT_INTERNET);
- cm().requestNetwork(trackDefaultRequest, mDefaultNetworkCallback, mHandler);
+ cm().requestNetwork(defaultNetworkRequest, mDefaultNetworkCallback, mHandler);
}
if (mEntitlementMgr == null) {
mEntitlementMgr = entitle;
@@ -239,7 +237,7 @@ public class UpstreamNetworkMonitor {
final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType(
mNetworkMap.values(), preferredTypes, isCellularUpstreamPermitted());
- mLog.log("preferred upstream type: " + getNetworkTypeName(typeStatePair.type));
+ mLog.log("preferred upstream type: " + typeStatePair.type);
switch (typeStatePair.type) {
case TYPE_MOBILE_DUN:
@@ -514,16 +512,13 @@ public class UpstreamNetworkMonitor {
try {
nc = ConnectivityManager.networkCapabilitiesForType(type);
} catch (IllegalArgumentException iae) {
- Log.e(TAG, "No NetworkCapabilities mapping for legacy type: "
- + ConnectivityManager.getNetworkTypeName(type));
+ Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + type);
continue;
}
if (!isCellularUpstreamPermitted && isCellular(nc)) {
continue;
}
- nc.setSingleUid(Process.myUid());
-
for (UpstreamNetworkState value : netStates) {
if (!nc.satisfiedByNetworkCapabilities(value.networkCapabilities)) {
continue;
diff --git a/packages/Tethering/tests/unit/jarjar-rules.txt b/packages/Tethering/tests/unit/jarjar-rules.txt
index 64fdebd92726..921fbed373b0 100644
--- a/packages/Tethering/tests/unit/jarjar-rules.txt
+++ b/packages/Tethering/tests/unit/jarjar-rules.txt
@@ -7,5 +7,6 @@ rule com.android.internal.util.MessageUtils* com.android.networkstack.tethering.
rule com.android.internal.util.Preconditions* com.android.networkstack.tethering.util.Preconditions@1
rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1
rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1
+rule com.android.internal.util.TrafficStatsConstants* com.android.networkstack.tethering.util.TrafficStatsConstants@1
rule android.net.LocalLog* com.android.networkstack.tethering.LocalLog@1
diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index fd2f708aea30..65a0ac13a84b 100644
--- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -16,13 +16,14 @@
package android.net.ip;
-import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
-import static android.net.ConnectivityManager.TETHERING_USB;
-import static android.net.ConnectivityManager.TETHERING_WIFI;
-import static android.net.ConnectivityManager.TETHERING_WIFI_P2P;
-import static android.net.ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
+import static android.net.INetd.IF_STATE_UP;
+import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHERING_WIFI_P2P;
+import static android.net.TetheringManager.TETHER_ERROR_ENABLE_NAT_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
import static android.net.ip.IpServer.STATE_AVAILABLE;
import static android.net.ip.IpServer.STATE_LOCAL_ONLY;
@@ -52,7 +53,7 @@ import static org.mockito.Mockito.when;
import android.net.INetd;
import android.net.INetworkStatsService;
-import android.net.InterfaceConfiguration;
+import android.net.InterfaceConfigurationParcel;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -64,7 +65,6 @@ import android.net.dhcp.IDhcpServerCallbacks;
import android.net.util.InterfaceParams;
import android.net.util.InterfaceSet;
import android.net.util.SharedLog;
-import android.os.INetworkManagementService;
import android.os.RemoteException;
import android.os.test.TestLooper;
import android.text.TextUtils;
@@ -89,6 +89,8 @@ public class IpServerTest {
private static final String IFACE_NAME = "testnet1";
private static final String UPSTREAM_IFACE = "upstream0";
private static final String UPSTREAM_IFACE2 = "upstream1";
+ private static final String BLUETOOTH_IFACE_ADDR = "192.168.42.1";
+ private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24;
private static final int DHCP_LEASE_TIME_SECS = 3600;
private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams(
@@ -96,11 +98,9 @@ public class IpServerTest {
private static final int MAKE_DHCPSERVER_TIMEOUT_MS = 1000;
- @Mock private INetworkManagementService mNMService;
@Mock private INetd mNetd;
@Mock private INetworkStatsService mStatsService;
@Mock private IpServer.Callback mCallback;
- @Mock private InterfaceConfiguration mInterfaceConfiguration;
@Mock private SharedLog mSharedLog;
@Mock private IDhcpServer mDhcpServer;
@Mock private RouterAdvertisementDaemon mRaDaemon;
@@ -112,6 +112,7 @@ public class IpServerTest {
private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor =
ArgumentCaptor.forClass(LinkProperties.class);
private IpServer mIpServer;
+ private InterfaceConfigurationParcel mInterfaceConfiguration;
private void initStateMachine(int interfaceType) throws Exception {
initStateMachine(interfaceType, false /* usingLegacyDhcp */);
@@ -131,17 +132,20 @@ public class IpServerTest {
}).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any());
when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
- when(mDependencies.getNetdService()).thenReturn(mNetd);
-
+ mInterfaceConfiguration = new InterfaceConfigurationParcel();
+ mInterfaceConfiguration.flags = new String[0];
+ if (interfaceType == TETHERING_BLUETOOTH) {
+ mInterfaceConfiguration.ipv4Addr = BLUETOOTH_IFACE_ADDR;
+ mInterfaceConfiguration.prefixLength = BLUETOOTH_DHCP_PREFIX_LENGTH;
+ }
mIpServer = new IpServer(
- IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog,
- mNMService, mStatsService, mCallback, usingLegacyDhcp, mDependencies);
+ IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd, mStatsService,
+ mCallback, usingLegacyDhcp, mDependencies);
mIpServer.start();
// Starting the state machine always puts us in a consistent state and notifies
// the rest of the world that we've changed from an unknown to available state.
mLooper.dispatchAll();
- reset(mNMService, mStatsService, mCallback);
- when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
+ reset(mNetd, mStatsService, mCallback);
when(mRaDaemon.start()).thenReturn(true);
}
@@ -158,8 +162,7 @@ public class IpServerTest {
if (upstreamIface != null) {
dispatchTetherConnectionChanged(upstreamIface);
}
- reset(mNMService, mStatsService, mCallback);
- when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
+ reset(mNetd, mStatsService, mCallback);
}
@Before public void setUp() throws Exception {
@@ -169,15 +172,14 @@ public class IpServerTest {
@Test
public void startsOutAvailable() {
- mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(),
- TETHERING_BLUETOOTH, mSharedLog, mNMService, mStatsService, mCallback,
- false /* usingLegacyDhcp */, mDependencies);
+ mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), TETHERING_BLUETOOTH, mSharedLog,
+ mNetd, mStatsService, mCallback, false /* usingLegacyDhcp */, mDependencies);
mIpServer.start();
mLooper.dispatchAll();
verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mCallback, mNMService, mStatsService);
+ verifyNoMoreInteractions(mCallback, mNetd, mStatsService);
}
@Test
@@ -196,7 +198,7 @@ public class IpServerTest {
// None of these commands should trigger us to request action from
// the rest of the system.
dispatchCommand(command);
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
}
}
@@ -208,7 +210,7 @@ public class IpServerTest {
verify(mCallback).updateInterfaceState(
mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
}
@Test
@@ -216,13 +218,17 @@ public class IpServerTest {
initStateMachine(TETHERING_BLUETOOTH);
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
- InOrder inOrder = inOrder(mCallback, mNMService);
- inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
+ InOrder inOrder = inOrder(mCallback, mNetd);
+ inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
+ inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
+ // One for ipv4 route, one for ipv6 link local route.
+ inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
+ any(), any());
inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
}
@Test
@@ -230,14 +236,16 @@ public class IpServerTest {
initTetheredStateMachine(TETHERING_BLUETOOTH, null);
dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
- InOrder inOrder = inOrder(mNMService, mNetd, mStatsService, mCallback);
- inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
+ InOrder inOrder = inOrder(mNetd, mStatsService, mCallback);
+ inOrder.verify(mNetd).tetherApplyDnsInterfaces();
+ inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME);
+ inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
}
@Test
@@ -245,16 +253,19 @@ public class IpServerTest {
initStateMachine(TETHERING_USB);
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
- InOrder inOrder = inOrder(mCallback, mNMService);
- inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME);
- inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
- inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
+ InOrder inOrder = inOrder(mCallback, mNetd);
+ inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
+ IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP)));
+ inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
+ inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
+ inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
+ any(), any());
inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), mLinkPropertiesCaptor.capture());
assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
}
@Test
@@ -262,16 +273,19 @@ public class IpServerTest {
initStateMachine(TETHERING_WIFI_P2P);
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
- InOrder inOrder = inOrder(mCallback, mNMService);
- inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME);
- inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
- inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
+ InOrder inOrder = inOrder(mCallback, mNetd);
+ inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
+ IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP)));
+ inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
+ inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
+ inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
+ any(), any());
inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), mLinkPropertiesCaptor.capture());
assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
}
@Test
@@ -281,10 +295,10 @@ public class IpServerTest {
// Telling the state machine about its upstream interface triggers
// a little more configuration.
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
- InOrder inOrder = inOrder(mNMService);
- inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ InOrder inOrder = inOrder(mNetd);
+ inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
+ verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
}
@Test
@@ -292,49 +306,49 @@ public class IpServerTest {
initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
- InOrder inOrder = inOrder(mNMService, mStatsService);
+ InOrder inOrder = inOrder(mNetd, mStatsService);
inOrder.verify(mStatsService).forceUpdate();
- inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
+ inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
+ verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
}
@Test
public void handlesChangingUpstreamNatFailure() throws Exception {
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
- doThrow(RemoteException.class).when(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
+ doThrow(RemoteException.class).when(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
- InOrder inOrder = inOrder(mNMService, mStatsService);
+ InOrder inOrder = inOrder(mNetd, mStatsService);
inOrder.verify(mStatsService).forceUpdate();
- inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
+ inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
inOrder.verify(mStatsService).forceUpdate();
- inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE2);
+ inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
+ inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2);
}
@Test
public void handlesChangingUpstreamInterfaceForwardingFailure() throws Exception {
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
- doThrow(RemoteException.class).when(mNMService).startInterfaceForwarding(
+ doThrow(RemoteException.class).when(mNetd).ipfwdAddInterfaceForward(
IFACE_NAME, UPSTREAM_IFACE2);
dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
- InOrder inOrder = inOrder(mNMService, mStatsService);
+ InOrder inOrder = inOrder(mNetd, mStatsService);
inOrder.verify(mStatsService).forceUpdate();
- inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
+ inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
+ inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
inOrder.verify(mStatsService).forceUpdate();
- inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE2);
+ inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
+ inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2);
}
@Test
@@ -342,17 +356,19 @@ public class IpServerTest {
initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
- InOrder inOrder = inOrder(mNMService, mNetd, mStatsService, mCallback);
+ InOrder inOrder = inOrder(mNetd, mStatsService, mCallback);
inOrder.verify(mStatsService).forceUpdate();
- inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
+ inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherApplyDnsInterfaces();
+ inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME);
+ inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
}
@Test
@@ -361,13 +377,14 @@ public class IpServerTest {
initTetheredStateMachine(TETHERING_USB, null);
if (shouldThrow) {
- doThrow(RemoteException.class).when(mNMService).untetherInterface(IFACE_NAME);
+ doThrow(RemoteException.class).when(mNetd).tetherInterfaceRemove(IFACE_NAME);
}
dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
- InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback);
- usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
- usbTeardownOrder.verify(mNMService).setInterfaceConfig(
- IFACE_NAME, mInterfaceConfiguration);
+ InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
+ // Currently IpServer interfaceSetCfg twice to stop IPv4. One just set interface down
+ // Another one is set IPv4 to 0.0.0.0/0 as clearng ipv4 address.
+ usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
+ argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
usbTeardownOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
usbTeardownOrder.verify(mCallback).updateLinkProperties(
@@ -380,12 +397,15 @@ public class IpServerTest {
public void usbShouldBeTornDownOnTetherError() throws Exception {
initStateMachine(TETHERING_USB);
- doThrow(RemoteException.class).when(mNMService).tetherInterface(IFACE_NAME);
+ doThrow(RemoteException.class).when(mNetd).tetherInterfaceAdd(IFACE_NAME);
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
- InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback);
- usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
- usbTeardownOrder.verify(mNMService).setInterfaceConfig(
- IFACE_NAME, mInterfaceConfiguration);
+ InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
+ usbTeardownOrder.verify(mNetd).interfaceSetCfg(
+ argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
+ usbTeardownOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
+
+ usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
+ argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
usbTeardownOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
usbTeardownOrder.verify(mCallback).updateLinkProperties(
@@ -397,11 +417,13 @@ public class IpServerTest {
public void shouldTearDownUsbOnUpstreamError() throws Exception {
initTetheredStateMachine(TETHERING_USB, null);
- doThrow(RemoteException.class).when(mNMService).enableNat(anyString(), anyString());
+ doThrow(RemoteException.class).when(mNetd).tetherAddForward(anyString(), anyString());
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
- InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback);
- usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
- usbTeardownOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
+ InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
+ usbTeardownOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE);
+
+ usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
+ argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
usbTeardownOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR);
usbTeardownOrder.verify(mCallback).updateLinkProperties(
@@ -413,11 +435,11 @@ public class IpServerTest {
public void ignoresDuplicateUpstreamNotifications() throws Exception {
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
for (int i = 0; i < 5; i++) {
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mStatsService, mCallback);
}
}
@@ -525,4 +547,12 @@ public class IpServerTest {
// never see an empty interface name in any LinkProperties update.
assertFalse(TextUtils.isEmpty(lp.getInterfaceName()));
}
+
+ private boolean assertContainsFlag(String[] flags, String match) {
+ for (String flag : flags) {
+ if (flag.equals(match)) return true;
+ }
+ fail("Missing flag: " + match);
+ return false;
+ }
}
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
index 99cf9e90d912..66eba9ae3b7a 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
@@ -16,12 +16,12 @@
package com.android.server.connectivity.tethering;
-import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
-import static android.net.ConnectivityManager.TETHERING_USB;
-import static android.net.ConnectivityManager.TETHERING_WIFI;
-import static android.net.ConnectivityManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
-import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
+import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_PROVISION_FAILED;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index 04b2eb411c9d..7af48a89d87c 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -19,16 +19,15 @@ package com.android.server.connectivity.tethering;
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
-import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
-import static android.net.ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY;
-import static android.net.ConnectivityManager.EXTRA_ACTIVE_TETHER;
-import static android.net.ConnectivityManager.EXTRA_AVAILABLE_TETHER;
-import static android.net.ConnectivityManager.TETHERING_USB;
-import static android.net.ConnectivityManager.TETHERING_WIFI;
-import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
-import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
import static android.net.RouteInfo.RTN_UNICAST;
+import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
+import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY;
+import static android.net.TetheringManager.EXTRA_ACTIVE_TETHER;
+import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
@@ -50,7 +49,6 @@ import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -74,14 +72,13 @@ import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
import android.net.ITetheringEventCallback;
import android.net.InetAddresses;
-import android.net.InterfaceConfiguration;
+import android.net.InterfaceConfigurationParcel;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.MacAddress;
import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.RouteInfo;
import android.net.TetherStatesParcel;
@@ -147,6 +144,7 @@ public class TetheringTest {
private static final String TEST_USB_IFNAME = "test_rndis0";
private static final String TEST_WLAN_IFNAME = "test_wlan0";
private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0";
+ private static final String TETHERING_NAME = "Tethering";
private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
@@ -185,6 +183,7 @@ public class TetheringTest {
private BroadcastReceiver mBroadcastReceiver;
private Tethering mTethering;
private PhoneStateListener mPhoneStateListener;
+ private InterfaceConfigurationParcel mInterfaceConfiguration;
private class TestContext extends BroadcastInterceptingContext {
TestContext(Context base) {
@@ -248,11 +247,6 @@ public class TetheringTest {
}
@Override
- public INetd getNetdService() {
- return mNetd;
- }
-
- @Override
public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
DhcpServerCallbacks cb) {
new Thread(() -> {
@@ -429,11 +423,11 @@ public class TetheringTest {
.thenReturn(new int[0]);
when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
.thenReturn(false);
- when(mNMService.listInterfaces())
+ when(mNetd.interfaceGetList())
.thenReturn(new String[] {
TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME});
- when(mNMService.getInterfaceConfig(anyString()))
- .thenReturn(new InterfaceConfiguration());
+ mInterfaceConfiguration = new InterfaceConfigurationParcel();
+ mInterfaceConfiguration.flags = new String[0];
when(mRouterAdvertisementDaemon.start())
.thenReturn(true);
@@ -495,15 +489,12 @@ public class TetheringTest {
p2pInfo.groupFormed = isGroupFormed;
p2pInfo.isGroupOwner = isGroupOwner;
- NetworkInfo networkInfo = new NetworkInfo(TYPE_WIFI_P2P, 0, null, null);
-
WifiP2pGroup group = new WifiP2pGroup();
group.setIsGroupOwner(isGroupOwner);
group.setInterface(ifname);
final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, p2pInfo);
- intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, networkInfo);
intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, group);
mServiceContext.sendBroadcastAsUserMultiplePermissions(intent, UserHandle.ALL,
P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST);
@@ -523,10 +514,11 @@ public class TetheringTest {
}
private void verifyInterfaceServingModeStarted(String ifname) throws Exception {
- verify(mNMService, times(1)).getInterfaceConfig(ifname);
- verify(mNMService, times(1))
- .setInterfaceConfig(eq(ifname), any(InterfaceConfiguration.class));
- verify(mNMService, times(1)).tetherInterface(ifname);
+ verify(mNetd, times(1)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
+ verify(mNetd, times(1)).tetherInterfaceAdd(ifname);
+ verify(mNetd, times(1)).networkAddInterface(INetd.LOCAL_NET_ID, ifname);
+ verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(ifname),
+ anyString(), anyString());
}
private void verifyTetheringBroadcast(String ifname, String whichExtra) {
@@ -558,7 +550,7 @@ public class TetheringTest {
verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
}
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
verifyNoMoreInteractions(mWifiManager);
}
@@ -581,14 +573,14 @@ public class TetheringTest {
prepareUsbTethering(upstreamState);
// This should produce no activity of any kind.
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
// Pretend we then receive USB configured broadcast.
sendUsbBroadcast(true, true, true);
mLooper.dispatchAll();
// Now we should see the start of tethering mechanics (in this case:
// tetherMatchingInterfaces() which starts by fetching all interfaces).
- verify(mNMService, times(1)).listInterfaces();
+ verify(mNetd, times(1)).interfaceGetList();
// UpstreamNetworkMonitor should receive selected upstream
verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
@@ -618,9 +610,9 @@ public class TetheringTest {
verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
- verify(mNMService, times(1)).setIpForwardingEnabled(true);
- verify(mNMService, times(1)).startTethering(any(String[].class));
- verifyNoMoreInteractions(mNMService);
+ verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
+ verify(mNetd, times(1)).tetherStartWithConfiguration(any());
+ verifyNoMoreInteractions(mNetd);
verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
verify(mWifiManager).updateInterfaceIpState(
@@ -638,16 +630,16 @@ public class TetheringTest {
mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
mLooper.dispatchAll();
- verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
- // {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
- verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
- verify(mNMService, times(2))
- .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
- verify(mNMService, times(1)).stopTethering();
- verify(mNMService, times(1)).setIpForwardingEnabled(false);
+ verify(mNetd, times(1)).tetherApplyDnsInterfaces();
+ verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME);
+ verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
+ // interfaceSetCfg() called once for enabling and twice disabling IPv4.
+ verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
+ verify(mNetd, times(1)).tetherStop();
+ verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME);
verify(mWifiManager, times(3)).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
verifyNoMoreInteractions(mWifiManager);
// Asking for the last error after the per-interface state machine
// has been reaped yields an unknown interface error.
@@ -684,8 +676,8 @@ public class TetheringTest {
UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
runUsbTethering(upstreamState);
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
sendIPv6TetherUpdates(upstreamState);
verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
@@ -708,8 +700,8 @@ public class TetheringTest {
UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
runUsbTethering(upstreamState);
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
sendIPv6TetherUpdates(upstreamState);
verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
@@ -721,8 +713,8 @@ public class TetheringTest {
UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
runUsbTethering(upstreamState);
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mRouterAdvertisementDaemon, times(1)).start();
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
@@ -736,12 +728,11 @@ public class TetheringTest {
UpstreamNetworkState upstreamState = buildMobile464xlatUpstreamState();
runUsbTethering(upstreamState);
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
- TEST_XLAT_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
sendIPv6TetherUpdates(upstreamState);
verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
@@ -754,9 +745,9 @@ public class TetheringTest {
UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
runUsbTethering(upstreamState);
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
// Then 464xlat comes up
upstreamState = buildMobile464xlatUpstreamState();
@@ -772,12 +763,11 @@ public class TetheringTest {
mLooper.dispatchAll();
// Forwarding is added for 464xlat
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
- TEST_XLAT_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
// Forwarding was not re-added for v6 (still times(1))
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
// DHCP not restarted on downstream (still times(1))
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
}
@@ -820,7 +810,7 @@ public class TetheringTest {
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
// Emulate externally-visible WifiManager effects, causing the
// per-interface state machine to start up, and telling us that
@@ -833,7 +823,7 @@ public class TetheringTest {
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
verifyNoMoreInteractions(mWifiManager);
}
@@ -847,7 +837,7 @@ public class TetheringTest {
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
// Emulate externally-visible WifiManager effects, causing the
// per-interface state machine to start up, and telling us that
@@ -858,9 +848,11 @@ public class TetheringTest {
verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
- verify(mNMService, times(1)).setIpForwardingEnabled(true);
- verify(mNMService, times(1)).startTethering(any(String[].class));
- verifyNoMoreInteractions(mNMService);
+ verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
+ verify(mNetd, times(1)).tetherStartWithConfiguration(any());
+ verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(TEST_WLAN_IFNAME),
+ anyString(), anyString());
+ verifyNoMoreInteractions(mNetd);
verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
verify(mWifiManager).updateInterfaceIpState(
@@ -878,8 +870,8 @@ public class TetheringTest {
/////
// We do not currently emulate any upstream being found.
//
- // This is why there are no calls to verify mNMService.enableNat() or
- // mNMService.startInterfaceForwarding().
+ // This is why there are no calls to verify mNetd.tetherAddForward() or
+ // mNetd.ipfwdAddInterfaceForward().
/////
// Emulate pressing the WiFi tethering button.
@@ -887,7 +879,7 @@ public class TetheringTest {
mLooper.dispatchAll();
verify(mWifiManager, times(1)).stopSoftAp();
verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
// Emulate externally-visible WifiManager effects, when tethering mode
// is being torn down.
@@ -895,16 +887,16 @@ public class TetheringTest {
mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
mLooper.dispatchAll();
- verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
- // {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
- verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
- verify(mNMService, atLeastOnce())
- .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
- verify(mNMService, times(1)).stopTethering();
- verify(mNMService, times(1)).setIpForwardingEnabled(false);
+ verify(mNetd, times(1)).tetherApplyDnsInterfaces();
+ verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME);
+ verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
+ // interfaceSetCfg() called once for enabling and twice for disabling IPv4.
+ verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
+ verify(mNetd, times(1)).tetherStop();
+ verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME);
verify(mWifiManager, times(3)).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
verifyNoMoreInteractions(mWifiManager);
// Asking for the last error after the per-interface state machine
// has been reaped yields an unknown interface error.
@@ -915,14 +907,14 @@ public class TetheringTest {
@Test
public void failureEnablingIpForwarding() throws Exception {
when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
- doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
+ doThrow(new RemoteException()).when(mNetd).ipfwdEnableForwarding(TETHERING_NAME);
// Emulate pressing the WiFi tethering button.
mTethering.startTethering(TETHERING_WIFI, null, false);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
// Emulate externally-visible WifiManager effects, causing the
// per-interface state machine to start up, and telling us that
@@ -931,15 +923,15 @@ public class TetheringTest {
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
mLooper.dispatchAll();
- // We verify get/set called thrice here: twice for setup (on NMService) and once during
- // teardown (on Netd) because all events happen over the course of the single
+ // We verify get/set called three times here: twice for setup and once during
+ // teardown because all events happen over the course of the single
// dispatchAll() above. Note that once the IpServer IPv4 address config
// code is refactored the two calls during shutdown will revert to one.
- verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
- verify(mNMService, times(2))
- .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
- verify(mNetd, times(1)).interfaceSetCfg(argThat(p -> TEST_WLAN_IFNAME.equals(p.ifName)));
- verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
+ verify(mNetd, times(3)).interfaceSetCfg(argThat(p -> TEST_WLAN_IFNAME.equals(p.ifName)));
+ verify(mNetd, times(1)).tetherInterfaceAdd(TEST_WLAN_IFNAME);
+ verify(mNetd, times(1)).networkAddInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
+ verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(TEST_WLAN_IFNAME),
+ anyString(), anyString());
verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
verify(mWifiManager).updateInterfaceIpState(
@@ -949,18 +941,20 @@ public class TetheringTest {
assertEquals(3, mTetheringDependencies.mIsTetheringSupportedCalls);
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
// This is called, but will throw.
- verify(mNMService, times(1)).setIpForwardingEnabled(true);
+ verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
// This never gets called because of the exception thrown above.
- verify(mNMService, times(0)).startTethering(any(String[].class));
+ verify(mNetd, times(0)).tetherStartWithConfiguration(any());
// When the master state machine transitions to an error state it tells
// downstream interfaces, which causes us to tell Wi-Fi about the error
// so it can take down AP mode.
- verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
+ verify(mNetd, times(1)).tetherApplyDnsInterfaces();
+ verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME);
+ verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
}
private void runUserRestrictionsChange(
@@ -1232,9 +1226,9 @@ public class TetheringTest {
verifyInterfaceServingModeStarted(TEST_P2P_IFNAME);
verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_AVAILABLE_TETHER);
- verify(mNMService, times(1)).setIpForwardingEnabled(true);
- verify(mNMService, times(1)).startTethering(any(String[].class));
- verifyNoMoreInteractions(mNMService);
+ verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
+ verify(mNetd, times(1)).tetherStartWithConfiguration(any());
+ verifyNoMoreInteractions(mNetd);
verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
// This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
@@ -1249,16 +1243,16 @@ public class TetheringTest {
mTethering.interfaceRemoved(TEST_P2P_IFNAME);
mLooper.dispatchAll();
- verify(mNMService, times(1)).untetherInterface(TEST_P2P_IFNAME);
- // {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
- verify(mNMService, times(2)).getInterfaceConfig(TEST_P2P_IFNAME);
- verify(mNMService, times(2))
- .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
- verify(mNMService, times(1)).stopTethering();
- verify(mNMService, times(1)).setIpForwardingEnabled(false);
+ verify(mNetd, times(1)).tetherApplyDnsInterfaces();
+ verify(mNetd, times(1)).tetherInterfaceRemove(TEST_P2P_IFNAME);
+ verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
+ // interfaceSetCfg() called once for enabling and twice for disabling IPv4.
+ verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
+ verify(mNetd, times(1)).tetherStop();
+ verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME);
verify(mUpstreamNetworkMonitor, never()).getCurrentPreferredUpstream();
verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
// Asking for the last error after the per-interface state machine
// has been reaped yields an unknown interface error.
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
@@ -1272,12 +1266,11 @@ public class TetheringTest {
sendWifiP2pConnectionChanged(true, false, TEST_P2P_IFNAME);
mLooper.dispatchAll();
- verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
- verify(mNMService, never())
- .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
- verify(mNMService, never()).tetherInterface(TEST_P2P_IFNAME);
- verify(mNMService, never()).setIpForwardingEnabled(true);
- verify(mNMService, never()).startTethering(any(String[].class));
+ verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
+ verify(mNetd, never()).tetherInterfaceAdd(TEST_P2P_IFNAME);
+ verify(mNetd, never()).networkAddInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
+ verify(mNetd, never()).ipfwdEnableForwarding(TETHERING_NAME);
+ verify(mNetd, never()).tetherStartWithConfiguration(any());
// Emulate externally-visible WifiP2pManager effects, when wifi p2p group
// is being removed.
@@ -1285,13 +1278,13 @@ public class TetheringTest {
mTethering.interfaceRemoved(TEST_P2P_IFNAME);
mLooper.dispatchAll();
- verify(mNMService, never()).untetherInterface(TEST_P2P_IFNAME);
- verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
- verify(mNMService, never())
- .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
- verify(mNMService, never()).stopTethering();
- verify(mNMService, never()).setIpForwardingEnabled(false);
- verifyNoMoreInteractions(mNMService);
+ verify(mNetd, never()).tetherApplyDnsInterfaces();
+ verify(mNetd, never()).tetherInterfaceRemove(TEST_P2P_IFNAME);
+ verify(mNetd, never()).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
+ verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
+ verify(mNetd, never()).tetherStop();
+ verify(mNetd, never()).ipfwdDisableForwarding(TETHERING_NAME);
+ verifyNoMoreInteractions(mNetd);
// Asking for the last error after the per-interface state machine
// has been reaped yields an unknown interface error.
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
@@ -1321,12 +1314,11 @@ public class TetheringTest {
sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
mLooper.dispatchAll();
- verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
- verify(mNMService, never())
- .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
- verify(mNMService, never()).tetherInterface(TEST_P2P_IFNAME);
- verify(mNMService, never()).setIpForwardingEnabled(true);
- verify(mNMService, never()).startTethering(any(String[].class));
+ verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
+ verify(mNetd, never()).tetherInterfaceAdd(TEST_P2P_IFNAME);
+ verify(mNetd, never()).networkAddInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
+ verify(mNetd, never()).ipfwdEnableForwarding(TETHERING_NAME);
+ verify(mNetd, never()).tetherStartWithConfiguration(any());
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
}
@Test
diff --git a/rs/java/android/renderscript/BaseObj.java b/rs/java/android/renderscript/BaseObj.java
index b7e05d9c984c..7b5514b8a0d1 100644
--- a/rs/java/android/renderscript/BaseObj.java
+++ b/rs/java/android/renderscript/BaseObj.java
@@ -16,8 +16,10 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import dalvik.system.CloseGuard;
+
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
diff --git a/rs/java/android/renderscript/Element.java b/rs/java/android/renderscript/Element.java
index b8eb3a1d7a40..0941907d35f8 100644
--- a/rs/java/android/renderscript/Element.java
+++ b/rs/java/android/renderscript/Element.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* <p>An Element represents one item within an {@link
diff --git a/rs/java/android/renderscript/FileA3D.java b/rs/java/android/renderscript/FileA3D.java
index 9a6b0bcd4544..7cc2825ae565 100644
--- a/rs/java/android/renderscript/FileA3D.java
+++ b/rs/java/android/renderscript/FileA3D.java
@@ -16,13 +16,13 @@
package android.renderscript;
-import java.io.File;
-import java.io.InputStream;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.content.res.Resources;
+import java.io.File;
+import java.io.InputStream;
+
/**
* @hide
* @deprecated in API 16
diff --git a/rs/java/android/renderscript/Font.java b/rs/java/android/renderscript/Font.java
index 583350e91795..df9d8019f28d 100644
--- a/rs/java/android/renderscript/Font.java
+++ b/rs/java/android/renderscript/Font.java
@@ -16,17 +16,16 @@
package android.renderscript;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.res.AssetManager;
+import android.content.res.Resources;
+import android.os.Environment;
+
import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
-import android.os.Environment;
-
-import android.annotation.UnsupportedAppUsage;
-import android.content.res.AssetManager;
-import android.content.res.Resources;
-
/**
* @hide
* @deprecated in API 16
diff --git a/rs/java/android/renderscript/Matrix4f.java b/rs/java/android/renderscript/Matrix4f.java
index 026c9fbd7d5e..a9469c979494 100644
--- a/rs/java/android/renderscript/Matrix4f.java
+++ b/rs/java/android/renderscript/Matrix4f.java
@@ -16,8 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
-import java.lang.Math;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/rs/java/android/renderscript/Mesh.java b/rs/java/android/renderscript/Mesh.java
index 5321dcb957dc..826225a70d86 100644
--- a/rs/java/android/renderscript/Mesh.java
+++ b/rs/java/android/renderscript/Mesh.java
@@ -16,7 +16,8 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.util.Vector;
/**
diff --git a/rs/java/android/renderscript/Program.java b/rs/java/android/renderscript/Program.java
index e28d646f5f1c..ff072183e927 100644
--- a/rs/java/android/renderscript/Program.java
+++ b/rs/java/android/renderscript/Program.java
@@ -17,14 +17,14 @@
package android.renderscript;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.res.Resources;
+import android.util.Log;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
-import android.annotation.UnsupportedAppUsage;
-import android.content.res.Resources;
-import android.util.Log;
-
/**
* @hide
diff --git a/rs/java/android/renderscript/ProgramFragment.java b/rs/java/android/renderscript/ProgramFragment.java
index 3dde9b6d6400..880531207b4d 100644
--- a/rs/java/android/renderscript/ProgramFragment.java
+++ b/rs/java/android/renderscript/ProgramFragment.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/rs/java/android/renderscript/ProgramFragmentFixedFunction.java b/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
index d05d41da8b6f..c741ce6e77ed 100644
--- a/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
+++ b/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/rs/java/android/renderscript/ProgramRaster.java b/rs/java/android/renderscript/ProgramRaster.java
index 33000acb4eb0..a21696c82161 100644
--- a/rs/java/android/renderscript/ProgramRaster.java
+++ b/rs/java/android/renderscript/ProgramRaster.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/rs/java/android/renderscript/ProgramStore.java b/rs/java/android/renderscript/ProgramStore.java
index 622fe21be47a..7e61347ee218 100644
--- a/rs/java/android/renderscript/ProgramStore.java
+++ b/rs/java/android/renderscript/ProgramStore.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/rs/java/android/renderscript/ProgramVertex.java b/rs/java/android/renderscript/ProgramVertex.java
index 83d9ea7be645..9257234de42c 100644
--- a/rs/java/android/renderscript/ProgramVertex.java
+++ b/rs/java/android/renderscript/ProgramVertex.java
@@ -38,7 +38,7 @@
**/
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/rs/java/android/renderscript/ProgramVertexFixedFunction.java b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
index 579d3bb507e8..03c2eaf91242 100644
--- a/rs/java/android/renderscript/ProgramVertexFixedFunction.java
+++ b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/rs/java/android/renderscript/RSSurfaceView.java b/rs/java/android/renderscript/RSSurfaceView.java
index 561373cef625..6bdde387b334 100644
--- a/rs/java/android/renderscript/RSSurfaceView.java
+++ b/rs/java/android/renderscript/RSSurfaceView.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 5b79d514fcc6..39efe731ce8a 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
diff --git a/rs/java/android/renderscript/RenderScriptCacheDir.java b/rs/java/android/renderscript/RenderScriptCacheDir.java
index 1797bef4be8d..862d032d6987 100644
--- a/rs/java/android/renderscript/RenderScriptCacheDir.java
+++ b/rs/java/android/renderscript/RenderScriptCacheDir.java
@@ -16,7 +16,8 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.File;
/**
diff --git a/rs/java/android/renderscript/RenderScriptGL.java b/rs/java/android/renderscript/RenderScriptGL.java
index 6fac83e8c4a8..dafaf367364d 100644
--- a/rs/java/android/renderscript/RenderScriptGL.java
+++ b/rs/java/android/renderscript/RenderScriptGL.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.view.Surface;
diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
index 9ad9aea9d7aa..d1d3a7642382 100644
--- a/rs/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.SparseArray;
/**
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 4515be8f4a9f..c2e32d332f50 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -92,6 +92,7 @@ import android.net.NetworkInfo.DetailedState;
import android.net.NetworkMisc;
import android.net.NetworkMonitorManager;
import android.net.NetworkPolicyManager;
+import android.net.NetworkProvider;
import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkScore;
@@ -219,6 +220,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* @hide
@@ -595,6 +597,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
// sequence number of NetworkRequests
private int mNextNetworkRequestId = 1;
+ // Sequence number for NetworkProvider IDs.
+ private final AtomicInteger mNextNetworkProviderId = new AtomicInteger(
+ NetworkProvider.FIRST_PROVIDER_ID);
+
// NetworkRequest activity String log entries.
private static final int MAX_NETWORK_REQUEST_LOGS = 20;
private final LocalLog mNetworkRequestInfoLogs = new LocalLog(MAX_NETWORK_REQUEST_LOGS);
@@ -4911,31 +4917,69 @@ public class ConnectivityService extends IConnectivityManager.Stub
public final String name;
public final Messenger messenger;
private final AsyncChannel mAsyncChannel;
+ private final IBinder.DeathRecipient mDeathRecipient;
public final int factorySerialNumber;
NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel,
- int factorySerialNumber) {
+ int factorySerialNumber, IBinder.DeathRecipient deathRecipient) {
this.name = name;
this.messenger = messenger;
- this.mAsyncChannel = asyncChannel;
this.factorySerialNumber = factorySerialNumber;
+ mAsyncChannel = asyncChannel;
+ mDeathRecipient = deathRecipient;
+
+ if ((mAsyncChannel == null) == (mDeathRecipient == null)) {
+ throw new AssertionError("Must pass exactly one of asyncChannel or deathRecipient");
+ }
+ }
+
+ boolean isLegacyNetworkFactory() {
+ return mAsyncChannel != null;
+ }
+
+ void sendMessageToNetworkProvider(int what, int arg1, int arg2, Object obj) {
+ try {
+ messenger.send(Message.obtain(null /* handler */, what, arg1, arg2, obj));
+ } catch (RemoteException e) {
+ // Remote process died. Ignore; the death recipient will remove this
+ // NetworkFactoryInfo from mNetworkFactoryInfos.
+ }
}
void requestNetwork(NetworkRequest request, int score, int servingSerialNumber) {
- mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
- servingSerialNumber, request);
+ if (isLegacyNetworkFactory()) {
+ mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
+ servingSerialNumber, request);
+ } else {
+ sendMessageToNetworkProvider(NetworkProvider.CMD_REQUEST_NETWORK, score,
+ servingSerialNumber, request);
+ }
}
void cancelRequest(NetworkRequest request) {
- mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST, request);
+ if (isLegacyNetworkFactory()) {
+ mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST, request);
+ } else {
+ sendMessageToNetworkProvider(NetworkProvider.CMD_CANCEL_REQUEST, 0, 0, request);
+ }
}
void connect(Context context, Handler handler) {
- mAsyncChannel.connect(context, handler, messenger);
+ if (isLegacyNetworkFactory()) {
+ mAsyncChannel.connect(context, handler, messenger);
+ } else {
+ try {
+ messenger.getBinder().linkToDeath(mDeathRecipient, 0);
+ } catch (RemoteException e) {
+ mDeathRecipient.binderDied();
+ }
+ }
}
void completeConnection() {
- mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+ if (isLegacyNetworkFactory()) {
+ mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+ }
}
}
@@ -5306,6 +5350,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
}
+ /** Returns the next Network provider ID. */
+ public final int nextNetworkProviderId() {
+ return mNextNetworkProviderId.getAndIncrement();
+ }
+
@Override
public void releaseNetworkRequest(NetworkRequest networkRequest) {
ensureNetworkRequestHasType(networkRequest);
@@ -5317,23 +5366,51 @@ public class ConnectivityService extends IConnectivityManager.Stub
public int registerNetworkFactory(Messenger messenger, String name) {
enforceNetworkFactoryPermission();
NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel(),
- NetworkFactory.SerialNumber.nextSerialNumber());
+ nextNetworkProviderId(), null /* deathRecipient */);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
return nfi.factorySerialNumber;
}
private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
+ if (mNetworkFactoryInfos.containsKey(nfi.messenger)) {
+ // Avoid creating duplicates. even if an app makes a direct AIDL call.
+ // This will never happen if an app calls ConnectivityManager#registerNetworkProvider,
+ // as that will throw if a duplicate provider is registered.
+ Slog.e(TAG, "Attempt to register existing NetworkFactoryInfo "
+ + mNetworkFactoryInfos.get(nfi.messenger).name);
+ return;
+ }
+
if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
mNetworkFactoryInfos.put(nfi.messenger, nfi);
nfi.connect(mContext, mTrackerHandler);
+ if (!nfi.isLegacyNetworkFactory()) {
+ // Legacy NetworkFactories get their requests when their AsyncChannel connects.
+ sendAllRequestsToFactory(nfi);
+ }
}
@Override
- public void unregisterNetworkFactory(Messenger messenger) {
+ public int registerNetworkProvider(Messenger messenger, String name) {
+ enforceNetworkFactoryPermission();
+ NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger,
+ null /* asyncChannel */, nextNetworkProviderId(),
+ () -> unregisterNetworkProvider(messenger));
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
+ return nfi.factorySerialNumber;
+ }
+
+ @Override
+ public void unregisterNetworkProvider(Messenger messenger) {
enforceNetworkFactoryPermission();
mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger));
}
+ @Override
+ public void unregisterNetworkFactory(Messenger messenger) {
+ unregisterNetworkProvider(messenger);
+ }
+
private void handleUnregisterNetworkFactory(Messenger messenger) {
NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger);
if (nfi == null) {
@@ -5343,6 +5420,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (DBG) log("unregisterNetworkFactory for " + nfi.name);
}
+ @Override
+ public void declareNetworkRequestUnfulfillable(NetworkRequest request) {
+ enforceNetworkFactoryPermission();
+ mHandler.post(() -> handleReleaseNetworkRequest(request, Binder.getCallingUid(), true));
+ }
+
// NOTE: Accessed on multiple threads, must be synchronized on itself.
@GuardedBy("mNetworkForNetId")
private final SparseArray<NetworkAgentInfo> mNetworkForNetId = new SparseArray<>();
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 1f736502ae42..05d83606b2d0 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -58,10 +58,12 @@ import android.net.NetworkStack;
import android.net.NetworkStats;
import android.net.NetworkUtils;
import android.net.RouteInfo;
-import android.net.TetherConfigParcel;
import android.net.TetherStatsParcel;
import android.net.UidRange;
import android.net.UidRangeParcel;
+import android.net.shared.NetdUtils;
+import android.net.shared.RouteUtils;
+import android.net.shared.RouteUtils.ModifyOperation;
import android.net.util.NetdService;
import android.os.BatteryStats;
import android.os.Binder;
@@ -898,48 +900,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
@Override
public void addRoute(int netId, RouteInfo route) {
- modifyRoute(MODIFY_OPERATION_ADD, netId, route);
+ NetworkStack.checkNetworkStackPermission(mContext);
+ RouteUtils.modifyRoute(mNetdService, ModifyOperation.ADD, netId, route);
}
@Override
public void removeRoute(int netId, RouteInfo route) {
- modifyRoute(MODIFY_OPERATION_REMOVE, netId, route);
- }
-
- private void modifyRoute(boolean add, int netId, RouteInfo route) {
NetworkStack.checkNetworkStackPermission(mContext);
-
- final String ifName = route.getInterface();
- final String dst = route.getDestination().toString();
- final String nextHop;
-
- switch (route.getType()) {
- case RouteInfo.RTN_UNICAST:
- if (route.hasGateway()) {
- nextHop = route.getGateway().getHostAddress();
- } else {
- nextHop = INetd.NEXTHOP_NONE;
- }
- break;
- case RouteInfo.RTN_UNREACHABLE:
- nextHop = INetd.NEXTHOP_UNREACHABLE;
- break;
- case RouteInfo.RTN_THROW:
- nextHop = INetd.NEXTHOP_THROW;
- break;
- default:
- nextHop = INetd.NEXTHOP_NONE;
- break;
- }
- try {
- if (add) {
- mNetdService.networkAddRoute(netId, ifName, dst, nextHop);
- } else {
- mNetdService.networkRemoveRoute(netId, ifName, dst, nextHop);
- }
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
+ RouteUtils.modifyRoute(mNetdService, ModifyOperation.REMOVE, netId, route);
}
private ArrayList<String> readRouteList(String filename) {
@@ -1023,12 +991,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
@Override
public void startTetheringWithConfiguration(boolean usingLegacyDnsProxy, String[] dhcpRange) {
NetworkStack.checkNetworkStackPermission(mContext);
- // an odd number of addrs will fail
try {
- final TetherConfigParcel config = new TetherConfigParcel();
- config.usingLegacyDnsProxy = usingLegacyDnsProxy;
- config.dhcpRanges = dhcpRange;
- mNetdService.tetherStartWithConfiguration(config);
+ NetdUtils.tetherStart(mNetdService, usingLegacyDnsProxy, dhcpRange);
} catch (RemoteException | ServiceSpecificException e) {
throw new IllegalStateException(e);
}
@@ -1060,26 +1024,21 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
public void tetherInterface(String iface) {
NetworkStack.checkNetworkStackPermission(mContext);
try {
- mNetdService.tetherInterfaceAdd(iface);
+ final LinkAddress addr = getInterfaceConfig(iface).getLinkAddress();
+ final IpPrefix dest = new IpPrefix(addr.getAddress(), addr.getPrefixLength());
+ NetdUtils.tetherInterface(mNetdService, iface, dest);
} catch (RemoteException | ServiceSpecificException e) {
throw new IllegalStateException(e);
}
- List<RouteInfo> routes = new ArrayList<>();
- // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
- // suitable to use as a route destination.
- routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface));
- addInterfaceToLocalNetwork(iface, routes);
}
@Override
public void untetherInterface(String iface) {
NetworkStack.checkNetworkStackPermission(mContext);
try {
- mNetdService.tetherInterfaceRemove(iface);
+ NetdUtils.untetherInterface(mNetdService, iface);
} catch (RemoteException | ServiceSpecificException e) {
throw new IllegalStateException(e);
- } finally {
- removeInterfaceFromLocalNetwork(iface);
}
}
@@ -2122,16 +2081,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
@Override
public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, iface);
-
- for (RouteInfo route : routes) {
- if (!route.isDefaultRoute()) {
- modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, route);
- }
- }
-
- // IPv6 link local should be activated always.
- modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID,
- new RouteInfo(new IpPrefix("fe80::/64"), null, iface));
+ // modifyInterfaceInNetwork already check calling permission.
+ RouteUtils.addRoutesToLocalNetwork(mNetdService, iface, routes);
}
@Override
@@ -2141,17 +2092,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
@Override
public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
- int failures = 0;
-
- for (RouteInfo route : routes) {
- try {
- modifyRoute(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, route);
- } catch (IllegalStateException e) {
- failures++;
- }
- }
-
- return failures;
+ NetworkStack.checkNetworkStackPermission(mContext);
+ return RouteUtils.removeRoutesFromLocalNetwork(mNetdService, routes);
}
@Override
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 3d455ee1cf19..db542145a750 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import static android.Manifest.permission.ACCESS_MTP;
import static android.Manifest.permission.INSTALL_PACKAGES;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
@@ -111,6 +112,7 @@ import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
import android.provider.DeviceConfig;
+import android.provider.Downloads;
import android.provider.MediaStore;
import android.provider.Settings;
import android.sysprop.VoldProperties;
@@ -367,6 +369,8 @@ class StorageManagerService extends IStorageManager.Stub
private volatile int mMediaStoreAuthorityAppId = -1;
+ private volatile int mDownloadsAuthorityAppId = -1;
+
private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
private final Installer mInstaller;
@@ -1788,6 +1792,15 @@ class StorageManagerService extends IStorageManager.Stub
mMediaStoreAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
}
+ provider = mPmInternal.resolveContentProvider(
+ Downloads.Impl.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+ UserHandle.getUserId(UserHandle.USER_SYSTEM));
+
+ if (provider != null) {
+ mDownloadsAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
+ }
+
try {
mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback);
@@ -3881,6 +3894,19 @@ class StorageManagerService extends IStorageManager.Stub
return Zygote.MOUNT_EXTERNAL_PASS_THROUGH;
}
+ if (mIsFuseEnabled && mDownloadsAuthorityAppId == UserHandle.getAppId(uid)) {
+ // DownloadManager can write in app-private directories on behalf of apps;
+ // give it write access to Android/
+ return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
+ }
+
+ final boolean hasMtp = mIPackageManager.checkUidPermission(ACCESS_MTP, uid) ==
+ PERMISSION_GRANTED;
+ if (mIsFuseEnabled && hasMtp) {
+ // The process hosting the MTP server should be able to write in Android/
+ return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
+ }
+
// Determine if caller is holding runtime permission
final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE);
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 2091c2a0c694..9ffe89c61a44 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -1059,8 +1059,8 @@ final class UiModeManagerService extends SystemService {
if (Sandman.shouldStartDockApp(getContext(), homeIntent)) {
try {
int result = ActivityTaskManager.getService().startActivityWithConfig(
- null, null, homeIntent, null, null, null, 0, 0,
- mConfiguration, null, UserHandle.USER_CURRENT);
+ null, getContext().getBasePackageName(), homeIntent, null, null, null,
+ 0, 0, mConfiguration, null, UserHandle.USER_CURRENT);
if (ActivityManager.isStartResultSuccessful(result)) {
dockAppStarted = true;
} else if (result != ActivityManager.START_INTENT_NOT_RESOLVED) {
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 454941ccdb03..a60b09fda2e8 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -39,8 +39,10 @@ import android.system.StructRlimit;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.StatsLog;
+import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.ZygoteConnectionConstants;
import com.android.server.am.ActivityManagerService;
import com.android.server.wm.SurfaceAnimationThread;
@@ -606,13 +608,18 @@ public class Watchdog extends Thread {
pids.add(Process.myPid());
if (mPhonePid > 0) pids.add(mPhonePid);
+ long anrTime = SystemClock.uptimeMillis();
+ ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(false);
final File stack = ActivityManagerService.dumpStackTraces(
- pids, null, null, getInterestingNativePids());
+ pids, processCpuTracker, new SparseArray<>(), getInterestingNativePids());
// Give some extra time to make sure the stack traces get written.
// The system's been hanging for a minute, another second or two won't hurt much.
SystemClock.sleep(5000);
+ processCpuTracker.update();
+ String cpuInfo = processCpuTracker.printCurrentState(anrTime);
+
// Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log
doSysRq('w');
doSysRq('l');
@@ -627,7 +634,7 @@ public class Watchdog extends Thread {
if (mActivity != null) {
mActivity.addErrorToDropBox(
"watchdog", null, "system_server", null, null, null,
- subject, null, stack, null);
+ subject, cpuInfo, stack, null);
}
StatsLog.write(StatsLog.SYSTEM_SERVER_WATCHDOG_OCCURRED, subject);
}
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index 4b48ef917744..143474bd5c94 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -413,6 +413,11 @@ public class AdbDebuggingManager {
case MESSAGE_ADB_CLEAR: {
Slog.d(TAG, "Received a request to clear the adb authorizations");
mConnectedKeys.clear();
+ // If the key store has not yet been instantiated then do so now; this avoids
+ // the unnecessary creation of the key store when adb is not enabled.
+ if (mAdbKeyStore == null) {
+ mAdbKeyStore = new AdbKeyStore();
+ }
mAdbKeyStore.deleteKeyStore();
cancelJobToUpdateAdbKeyStore();
break;
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index a1e1f29016c2..b9f2e76c6ecb 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -103,6 +103,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.MemInfoReader;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
+import com.android.server.SystemConfig;
import com.android.server.Watchdog;
import com.android.server.compat.PlatformCompat;
import com.android.server.pm.dex.DexManager;
@@ -357,6 +358,8 @@ public final class ProcessList {
private boolean mAppDataIsolationEnabled = false;
+ private ArrayList<String> mAppDataIsolationWhitelistedApps;
+
/**
* Temporary to avoid allocations. Protected by main lock.
*/
@@ -645,6 +648,9 @@ public final class ProcessList {
// want some apps enabled while some apps disabled
mAppDataIsolationEnabled =
SystemProperties.getBoolean(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);
+ mAppDataIsolationWhitelistedApps = new ArrayList<>(
+ SystemConfig.getInstance().getAppDataIsolationWhitelistedApps());
+
if (sKillHandler == null) {
sKillThread = new ServiceThread(TAG + ":kill",
@@ -1555,20 +1561,27 @@ public final class ProcessList {
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
-
+ int numGids = 3;
+ if (mountExternal == Zygote.MOUNT_EXTERNAL_INSTALLER
+ || mountExternal == Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE) {
+ numGids++;
+ }
/*
* Add shared application and profile GIDs so applications can share some
* resources like shared libraries and access user-wide resources
*/
if (ArrayUtils.isEmpty(permGids)) {
- gids = new int[3];
+ gids = new int[numGids];
} else {
- gids = new int[permGids.length + 3];
- System.arraycopy(permGids, 0, gids, 3, permGids.length);
+ gids = new int[permGids.length + numGids];
+ System.arraycopy(permGids, 0, gids, numGids, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
+ if (numGids > 3) {
+ gids[3] = Process.SDCARD_RW_GID;
+ }
// Replace any invalid GIDs
if (gids[0] == UserHandle.ERR_GID) gids[0] = gids[2];
@@ -1905,6 +1918,16 @@ public final class ProcessList {
result.put(packageName, Pair.create(volumeUuid, inode));
}
}
+ if (mAppDataIsolationWhitelistedApps != null) {
+ for (String packageName : mAppDataIsolationWhitelistedApps) {
+ String volumeUuid = pmInt.getPackage(packageName).getVolumeUuid();
+ long inode = pmInt.getCeDataInode(packageName, userId);
+ if (inode != 0) {
+ result.put(packageName, Pair.create(volumeUuid, inode));
+ }
+ }
+ }
+
return result;
}
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index ad728c18dd59..8498dcb32eb1 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -237,15 +237,15 @@ public class DisplayModeDirector {
lowestConsideredPriority++;
}
- int defaultModeId = defaultMode.getModeId();
+ int baseModeId = defaultMode.getModeId();
if (availableModes.length > 0) {
- defaultModeId = availableModes[0];
+ baseModeId = availableModes[0];
}
// filterModes function is going to filter the modes based on the voting system. If
// the application requests a given mode with preferredModeId function, it will be
- // stored as defaultModeId.
+ // stored as baseModeId.
return new DesiredDisplayModeSpecs(
- defaultModeId, new RefreshRateRange(minRefreshRate, maxRefreshRate));
+ baseModeId, new RefreshRateRange(minRefreshRate, maxRefreshRate));
}
}
@@ -526,7 +526,7 @@ public class DisplayModeDirector {
}
/**
- * Information about the desired display mode to be set by the system. Includes the default
+ * Information about the desired display mode to be set by the system. Includes the base
* mode ID and refresh rate range.
*
* We have this class in addition to SurfaceControl.DesiredDisplayConfigSpecs to make clear the
@@ -535,10 +535,10 @@ public class DisplayModeDirector {
*/
public static final class DesiredDisplayModeSpecs {
/**
- * Default mode ID. This is what system defaults to for all other settings, or
+ * Base mode ID. This is what system defaults to for all other settings, or
* if the refresh rate range is not available.
*/
- public int defaultModeId;
+ public int baseModeId;
/**
* The refresh rate range.
*/
@@ -548,9 +548,8 @@ public class DisplayModeDirector {
refreshRateRange = new RefreshRateRange();
}
- public DesiredDisplayModeSpecs(
- int defaultModeId, @NonNull RefreshRateRange refreshRateRange) {
- this.defaultModeId = defaultModeId;
+ public DesiredDisplayModeSpecs(int baseModeId, @NonNull RefreshRateRange refreshRateRange) {
+ this.baseModeId = baseModeId;
this.refreshRateRange = refreshRateRange;
}
@@ -559,7 +558,7 @@ public class DisplayModeDirector {
*/
@Override
public String toString() {
- return String.format("defaultModeId=%d min=%.0f max=%.0f", defaultModeId,
+ return String.format("baseModeId=%d min=%.0f max=%.0f", baseModeId,
refreshRateRange.min, refreshRateRange.max);
}
/**
@@ -577,7 +576,7 @@ public class DisplayModeDirector {
DesiredDisplayModeSpecs desiredDisplayModeSpecs = (DesiredDisplayModeSpecs) other;
- if (defaultModeId != desiredDisplayModeSpecs.defaultModeId) {
+ if (baseModeId != desiredDisplayModeSpecs.baseModeId) {
return false;
}
if (!refreshRateRange.equals(desiredDisplayModeSpecs.refreshRateRange)) {
@@ -588,14 +587,14 @@ public class DisplayModeDirector {
@Override
public int hashCode() {
- return Objects.hash(defaultModeId, refreshRateRange);
+ return Objects.hash(baseModeId, refreshRateRange);
}
/**
* Copy values from the other object.
*/
public void copyFrom(DesiredDisplayModeSpecs other) {
- defaultModeId = other.defaultModeId;
+ baseModeId = other.baseModeId;
refreshRateRange.min = other.refreshRateRange.min;
refreshRateRange.max = other.refreshRateRange.max;
}
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index cf94d4695497..fb8a4193286b 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -272,14 +272,14 @@ final class LocalDisplayAdapter extends DisplayAdapter {
// Check whether surface flinger spontaneously changed display config specs out from
// under us. If so, schedule a traversal to reapply our display config specs.
- if (mDisplayModeSpecs.defaultModeId != 0) {
- int activeDefaultMode =
+ if (mDisplayModeSpecs.baseModeId != 0) {
+ int activeBaseMode =
findMatchingModeIdLocked(physicalDisplayConfigSpecs.defaultConfig);
// If we can't map the defaultConfig index to a mode, then the physical display
// configs must have changed, and the code below for handling changes to the
// list of available modes will take care of updating display config specs.
- if (activeDefaultMode != 0) {
- if (mDisplayModeSpecs.defaultModeId != activeDefaultMode
+ if (activeBaseMode != 0) {
+ if (mDisplayModeSpecs.baseModeId != activeBaseMode
|| mDisplayModeSpecs.refreshRateRange.min
!= physicalDisplayConfigSpecs.minRefreshRate
|| mDisplayModeSpecs.refreshRateRange.max
@@ -312,14 +312,14 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mDefaultModeId = activeRecord.mMode.getModeId();
}
- // Determine whether the display mode specs' default mode is still there.
- if (mSupportedModes.indexOfKey(mDisplayModeSpecs.defaultModeId) < 0) {
- if (mDisplayModeSpecs.defaultModeId != 0) {
+ // Determine whether the display mode specs' base mode is still there.
+ if (mSupportedModes.indexOfKey(mDisplayModeSpecs.baseModeId) < 0) {
+ if (mDisplayModeSpecs.baseModeId != 0) {
Slog.w(TAG,
- "DisplayModeSpecs default mode no longer available, using currently"
- + " active mode as default.");
+ "DisplayModeSpecs base mode no longer available, using currently"
+ + " active mode.");
}
- mDisplayModeSpecs.defaultModeId = activeRecord.mMode.getModeId();
+ mDisplayModeSpecs.baseModeId = activeRecord.mMode.getModeId();
mDisplayModeSpecsInvalid = true;
}
@@ -648,13 +648,13 @@ final class LocalDisplayAdapter extends DisplayAdapter {
@Override
public void setDesiredDisplayModeSpecsLocked(
DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {
- if (displayModeSpecs.defaultModeId == 0) {
+ if (displayModeSpecs.baseModeId == 0) {
// Bail if the caller is requesting a null mode. We'll get called again shortly with
// a valid mode.
return;
}
- int defaultPhysIndex = findDisplayInfoIndexLocked(displayModeSpecs.defaultModeId);
- if (defaultPhysIndex < 0) {
+ int basePhysIndex = findDisplayInfoIndexLocked(displayModeSpecs.baseModeId);
+ if (basePhysIndex < 0) {
// When a display is hotplugged, it's possible for a mode to be removed that was
// previously valid. Because of the way display changes are propagated through the
// framework, and the caching of the display mode specs in LogicalDisplay, it's
@@ -662,8 +662,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
// mode. This should only happen in extremely rare cases. A followup call will
// contain a valid mode id.
Slog.w(TAG,
- "Ignoring request for invalid default mode id "
- + displayModeSpecs.defaultModeId);
+ "Ignoring request for invalid base mode id " + displayModeSpecs.baseModeId);
updateDeviceInfoLocked();
return;
}
@@ -673,7 +672,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
getHandler().sendMessage(PooledLambda.obtainMessage(
LocalDisplayDevice::setDesiredDisplayModeSpecsAsync, this,
getDisplayTokenLocked(),
- new SurfaceControl.DesiredDisplayConfigSpecs(defaultPhysIndex,
+ new SurfaceControl.DesiredDisplayConfigSpecs(basePhysIndex,
mDisplayModeSpecs.refreshRateRange.min,
mDisplayModeSpecs.refreshRateRange.max)));
}
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index b6255d15795e..c8e5f6c8f53b 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -317,7 +317,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
@Override
public void setDesiredDisplayModeSpecsLocked(
DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {
- final int id = displayModeSpecs.defaultModeId;
+ final int id = displayModeSpecs.baseModeId;
int index = -1;
if (id == 0) {
// Use the default.
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index ae6d63adc7e7..90358ca1f133 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -83,11 +83,11 @@ import android.view.ViewConfiguration;
import android.widget.Toast;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.DumpUtils;
-import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.DisplayThread;
import com.android.server.LocalServices;
@@ -186,6 +186,9 @@ public class InputManagerService extends IInputManager.Stub
// The associations of input devices to displays by port. Maps from input device port (String)
// to display id (int). Currently only accessed by InputReader.
private final Map<String, Integer> mStaticAssociations;
+ private final Object mAssociationsLock = new Object();
+ @GuardedBy("mAssociationLock")
+ private final Map<String, Integer> mRuntimeAssociations = new HashMap<String, Integer>();
private static native long nativeInit(InputManagerService service,
Context context, MessageQueue messageQueue);
@@ -240,6 +243,7 @@ public class InputManagerService extends IInputManager.Stub
private static native void nativeSetCustomPointerIcon(long ptr, PointerIcon icon);
private static native void nativeSetPointerCapture(long ptr, boolean detached);
private static native boolean nativeCanDispatchToDisplay(long ptr, int deviceId, int displayId);
+ private static native void nativeNotifyPortAssociationsChanged(long ptr);
// Input event injection constants defined in InputDispatcher.h.
private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
@@ -1723,6 +1727,49 @@ public class InputManagerService extends IInputManager.Stub
nativeSetCustomPointerIcon(mPtr, icon);
}
+ /**
+ * Add a runtime association between the input port and the display port. This overrides any
+ * static associations.
+ * @param inputPort The port of the input device.
+ * @param displayPort The physical port of the associated display.
+ */
+ @Override // Binder call
+ public void addPortAssociation(@NonNull String inputPort, int displayPort) {
+ if (!checkCallingPermission(
+ android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT,
+ "addPortAssociation()")) {
+ throw new SecurityException(
+ "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT permission");
+ }
+
+ Objects.requireNonNull(inputPort);
+ synchronized (mAssociationsLock) {
+ mRuntimeAssociations.put(inputPort, displayPort);
+ }
+ nativeNotifyPortAssociationsChanged(mPtr);
+ }
+
+ /**
+ * Remove the runtime association between the input port and the display port. Any existing
+ * static association for the cleared input port will be restored.
+ * @param inputPort The port of the input device to be cleared.
+ */
+ @Override // Binder call
+ public void removePortAssociation(@NonNull String inputPort) {
+ if (!checkCallingPermission(
+ android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT,
+ "clearPortAssociations()")) {
+ throw new SecurityException(
+ "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT permission");
+ }
+
+ Objects.requireNonNull(inputPort);
+ synchronized (mAssociationsLock) {
+ mRuntimeAssociations.remove(inputPort);
+ }
+ nativeNotifyPortAssociationsChanged(mPtr);
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
@@ -1743,6 +1790,16 @@ public class InputManagerService extends IInputManager.Stub
pw.println(" display: " + v);
});
}
+
+ synchronized (mAssociationsLock) {
+ if (!mRuntimeAssociations.isEmpty()) {
+ pw.println("Runtime Associations:");
+ mRuntimeAssociations.forEach((k, v) -> {
+ pw.print(" port: " + k);
+ pw.println(" display: " + v);
+ });
+ }
+ }
}
private boolean checkCallingPermission(String permission, String func) {
@@ -1766,6 +1823,7 @@ public class InputManagerService extends IInputManager.Stub
@Override
public void monitor() {
synchronized (mInputFilterLock) { }
+ synchronized (mAssociationsLock) { /* Test if blocked by associations lock. */}
nativeMonitor(mPtr);
}
@@ -1930,7 +1988,7 @@ public class InputManagerService extends IInputManager.Stub
* @return Flattened list
*/
private static List<String> flatten(@NonNull Map<String, Integer> map) {
- List<String> list = new ArrayList<>(map.size() * 2);
+ final List<String> list = new ArrayList<>(map.size() * 2);
map.forEach((k, v)-> {
list.add(k);
list.add(v.toString());
@@ -1943,11 +2001,11 @@ public class InputManagerService extends IInputManager.Stub
* directory.
*/
private static Map<String, Integer> loadStaticInputPortAssociations() {
- File baseDir = Environment.getVendorDirectory();
- File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH);
+ final File baseDir = Environment.getVendorDirectory();
+ final File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH);
try {
- InputStream stream = new FileInputStream(confFile);
+ final InputStream stream = new FileInputStream(confFile);
return ConfigurationProcessor.processInputPortAssociations(stream);
} catch (FileNotFoundException e) {
// Most of the time, file will not exist, which is expected.
@@ -1960,7 +2018,14 @@ public class InputManagerService extends IInputManager.Stub
// Native callback
private String[] getInputPortAssociations() {
- List<String> associationList = flatten(mStaticAssociations);
+ final Map<String, Integer> associations = new HashMap<>(mStaticAssociations);
+
+ // merge the runtime associations.
+ synchronized (mAssociationsLock) {
+ associations.putAll(mRuntimeAssociations);
+ }
+
+ final List<String> associationList = flatten(associations);
return associationList.toArray(new String[0]);
}
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index 55c4e21dd830..9ca302edd204 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -46,7 +46,7 @@ abstract class MediaRoute2Provider {
}
public abstract void requestCreateSession(String packageName, String routeId,
- String controlCategory, long requestId);
+ String routeType, long requestId);
public abstract void releaseSession(int sessionId);
public abstract void selectRoute(int sessionId, String routeId);
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
index 28bb034b33f7..5cc2b16e073a 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -76,10 +76,10 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
}
@Override
- public void requestCreateSession(String packageName, String routeId, String controlCategory,
+ public void requestCreateSession(String packageName, String routeId, String routeType,
long requestId) {
if (mConnectionReady) {
- mActiveConnection.requestCreateSession(packageName, routeId, controlCategory,
+ mActiveConnection.requestCreateSession(packageName, routeId, routeType,
requestId);
updateBinding();
}
@@ -345,11 +345,11 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
mClient.dispose();
}
- public void requestCreateSession(String packageName, String routeId, String controlCategory,
+ public void requestCreateSession(String packageName, String routeId, String routeType,
long requestId) {
try {
mProvider.requestCreateSession(packageName, routeId,
- controlCategory, requestId);
+ routeType, requestId);
} catch (RemoteException ex) {
Slog.e(TAG, "Failed to deliver request to create a session.", ex);
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index a5ffbb8f60e4..b48243279d9e 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -28,6 +28,7 @@ import android.media.IMediaRouter2Client;
import android.media.IMediaRouter2Manager;
import android.media.MediaRoute2Info;
import android.media.MediaRoute2ProviderInfo;
+import android.media.RouteDiscoveryRequest;
import android.media.RouteSessionInfo;
import android.os.Binder;
import android.os.Bundle;
@@ -174,18 +175,18 @@ class MediaRouter2ServiceImpl {
}
public void requestCreateSession(IMediaRouter2Client client, MediaRoute2Info route,
- String controlCategory, int requestId) {
+ String routeType, int requestId) {
Objects.requireNonNull(client, "client must not be null");
Objects.requireNonNull(route, "route must not be null");
- if (TextUtils.isEmpty(controlCategory)) {
- throw new IllegalArgumentException("controlCategory must not be empty");
+ if (TextUtils.isEmpty(routeType)) {
+ throw new IllegalArgumentException("routeType must not be empty");
}
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- requestCreateSessionLocked(client, route, controlCategory, requestId);
+ requestCreateSessionLocked(client, route, routeType, requestId);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -267,16 +268,16 @@ class MediaRouter2ServiceImpl {
}
}
- public void setControlCategories(@NonNull IMediaRouter2Client client,
- @NonNull List<String> categories) {
+ public void setDiscoveryRequest2(@NonNull IMediaRouter2Client client,
+ @NonNull RouteDiscoveryRequest request) {
Objects.requireNonNull(client, "client must not be null");
- Objects.requireNonNull(categories, "categories must not be null");
+ Objects.requireNonNull(request, "request must not be null");
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
Client2Record clientRecord = mAllClientRecords.get(client.asBinder());
- setControlCategoriesLocked(clientRecord, categories);
+ setDiscoveryRequestLocked(clientRecord, request);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -434,7 +435,7 @@ class MediaRouter2ServiceImpl {
}
private void requestCreateSessionLocked(@NonNull IMediaRouter2Client client,
- @NonNull MediaRoute2Info route, @NonNull String controlCategory, long requestId) {
+ @NonNull MediaRoute2Info route, @NonNull String routeType, long requestId) {
final IBinder binder = client.asBinder();
final Client2Record clientRecord = mAllClientRecords.get(binder);
@@ -447,7 +448,7 @@ class MediaRouter2ServiceImpl {
clientRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::requestCreateSessionOnHandler,
clientRecord.mUserRecord.mHandler,
- clientRecord, route, controlCategory, requestId));
+ clientRecord, route, routeType, requestId));
}
}
@@ -502,13 +503,14 @@ class MediaRouter2ServiceImpl {
}
}
- private void setControlCategoriesLocked(Client2Record clientRecord, List<String> categories) {
+ private void setDiscoveryRequestLocked(Client2Record clientRecord,
+ RouteDiscoveryRequest discoveryRequest) {
if (clientRecord != null) {
- if (clientRecord.mControlCategories.equals(categories)) {
+ if (clientRecord.mDiscoveryRequest.equals(discoveryRequest)) {
return;
}
- clientRecord.mControlCategories = categories;
+ clientRecord.mDiscoveryRequest = discoveryRequest;
clientRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::updateClientUsage,
clientRecord.mUserRecord.mHandler, clientRecord));
@@ -607,7 +609,7 @@ class MediaRouter2ServiceImpl {
if (clientRecord != null && managerRecord.mTrusted) {
//TODO: select category properly
requestCreateSessionLocked(clientRecord.mClient, route,
- route.getSupportedCategories().get(0), uniqueRequestId);
+ route.getRouteTypes().get(0), uniqueRequestId);
}
}
}
@@ -725,7 +727,7 @@ class MediaRouter2ServiceImpl {
public final boolean mTrusted;
public final int mClientId;
- public List<String> mControlCategories;
+ public RouteDiscoveryRequest mDiscoveryRequest;
public boolean mIsManagerSelecting;
public MediaRoute2Info mSelectingRoute;
public MediaRoute2Info mSelectedRoute;
@@ -735,7 +737,7 @@ class MediaRouter2ServiceImpl {
mUserRecord = userRecord;
mPackageName = packageName;
mSelectRouteSequenceNumbers = new ArrayList<>();
- mControlCategories = Collections.emptyList();
+ mDiscoveryRequest = RouteDiscoveryRequest.EMPTY;
mClient = client;
mUid = uid;
mPid = pid;
@@ -961,7 +963,7 @@ class MediaRouter2ServiceImpl {
}
private void requestCreateSessionOnHandler(Client2Record clientRecord,
- MediaRoute2Info route, String controlCategory, long requestId) {
+ MediaRoute2Info route, String routeType, long requestId) {
final MediaRoute2Provider provider = findProvider(route.getProviderId());
if (provider == null) {
@@ -971,20 +973,20 @@ class MediaRouter2ServiceImpl {
return;
}
- if (!route.getSupportedCategories().contains(controlCategory)) {
+ if (!route.getRouteTypes().contains(routeType)) {
Slog.w(TAG, "Ignoring session creation request since the given route=" + route
- + " doesn't support the given category=" + controlCategory);
+ + " doesn't support the given type=" + routeType);
notifySessionCreationFailed(clientRecord, toClientRequestId(requestId));
return;
}
// TODO: Apply timeout for each request (How many seconds should we wait?)
SessionCreationRequest request = new SessionCreationRequest(
- clientRecord, route, controlCategory, requestId);
+ clientRecord, route, routeType, requestId);
mSessionCreationRequests.add(request);
provider.requestCreateSession(clientRecord.mPackageName, route.getOriginalId(),
- controlCategory, requestId);
+ routeType, requestId);
}
private void selectRouteOnHandler(@NonNull Client2Record clientRecord,
@@ -1144,12 +1146,12 @@ class MediaRouter2ServiceImpl {
}
String originalRouteId = matchingRequest.mRoute.getId();
- String originalCategory = matchingRequest.mControlCategory;
+ String originalCategory = matchingRequest.mRouteType;
Client2Record client2Record = matchingRequest.mClientRecord;
if (!sessionInfo.getSelectedRoutes().contains(originalRouteId)
|| !TextUtils.equals(originalCategory,
- sessionInfo.getControlCategory())) {
+ sessionInfo.getRouteType())) {
Slog.w(TAG, "Created session doesn't match the original request."
+ " originalRouteId=" + originalRouteId
+ ", originalCategory=" + originalCategory + ", requestId=" + requestId
@@ -1404,8 +1406,8 @@ class MediaRouter2ServiceImpl {
try {
manager.notifyRouteSelected(clientRecord.mPackageName,
clientRecord.mSelectedRoute);
- manager.notifyControlCategoriesChanged(clientRecord.mPackageName,
- clientRecord.mControlCategories);
+ manager.notifyRouteTypesChanged(clientRecord.mPackageName,
+ clientRecord.mDiscoveryRequest.getRouteTypes());
} catch (RemoteException ex) {
Slog.w(TAG, "Failed to update client usage. Manager probably died.", ex);
}
@@ -1424,15 +1426,15 @@ class MediaRouter2ServiceImpl {
final class SessionCreationRequest {
public final Client2Record mClientRecord;
public final MediaRoute2Info mRoute;
- public final String mControlCategory;
+ public final String mRouteType;
public final long mRequestId;
SessionCreationRequest(@NonNull Client2Record clientRecord,
@NonNull MediaRoute2Info route,
- @NonNull String controlCategory, long requestId) {
+ @NonNull String routeType, long requestId) {
mClientRecord = clientRecord;
mRoute = route;
- mControlCategory = controlCategory;
+ mRouteType = routeType;
mRequestId = requestId;
}
}
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index d77f43b4435d..c76555cf15cf 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -39,6 +39,7 @@ import android.media.MediaRouter;
import android.media.MediaRouterClientState;
import android.media.RemoteDisplayState;
import android.media.RemoteDisplayState.RemoteDisplayInfo;
+import android.media.RouteDiscoveryRequest;
import android.media.RouteSessionInfo;
import android.os.Binder;
import android.os.Handler;
@@ -459,8 +460,8 @@ public final class MediaRouterService extends IMediaRouterService.Stub
// Binder call
@Override
public void requestCreateSession(IMediaRouter2Client client, MediaRoute2Info route,
- String controlCategory, int requestId) {
- mService2.requestCreateSession(client, route, controlCategory, requestId);
+ String routeType, int requestId) {
+ mService2.requestCreateSession(client, route, routeType, requestId);
}
// Binder call
@@ -519,8 +520,8 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
// Binder call
@Override
- public void setControlCategories(IMediaRouter2Client client, List<String> categories) {
- mService2.setControlCategories(client, categories);
+ public void setDiscoveryRequest2(IMediaRouter2Client client, RouteDiscoveryRequest request) {
+ mService2.setDiscoveryRequest2(client, request);
}
// Binder call
diff --git a/services/core/java/com/android/server/media/MediaSession2Record.java b/services/core/java/com/android/server/media/MediaSession2Record.java
new file mode 100644
index 000000000000..f3241ee44569
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaSession2Record.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media;
+
+import android.media.MediaController2;
+import android.media.Session2CommandGroup;
+import android.media.Session2Token;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Looper;
+import android.os.ResultReceiver;
+import android.os.UserHandle;
+import android.util.Log;
+import android.view.KeyEvent;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.PrintWriter;
+
+/**
+ * Keeps the record of {@link Session2Token} helps to send command to the corresponding session.
+ */
+// TODO(jaewan): Do not call service method directly -- introduce listener instead.
+public class MediaSession2Record implements MediaSessionRecordImpl {
+ private static final String TAG = "MediaSession2Record";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ private final Session2Token mSessionToken;
+ @GuardedBy("mLock")
+ private final HandlerExecutor mHandlerExecutor;
+ @GuardedBy("mLock")
+ private final MediaController2 mController;
+ @GuardedBy("mLock")
+ private final MediaSessionService mService;
+ @GuardedBy("mLock")
+ private boolean mIsConnected;
+
+ public MediaSession2Record(Session2Token sessionToken, MediaSessionService service,
+ Looper handlerLooper) {
+ mSessionToken = sessionToken;
+ mService = service;
+ mHandlerExecutor = new HandlerExecutor(new Handler(handlerLooper));
+ mController = new MediaController2.Builder(service.getContext(), sessionToken)
+ .setControllerCallback(mHandlerExecutor, new Controller2Callback())
+ .build();
+ }
+
+ @Override
+ public String getPackageName() {
+ return mSessionToken.getPackageName();
+ }
+
+ public Session2Token getSession2Token() {
+ return mSessionToken;
+ }
+
+ @Override
+ public int getUid() {
+ return mSessionToken.getUid();
+ }
+
+ @Override
+ public int getUserId() {
+ return UserHandle.getUserId(mSessionToken.getUid());
+ }
+
+ @Override
+ public boolean isSystemPriority() {
+ // System priority session is currently only allowed for telephony, and it's OK to stick to
+ // the media1 API at this moment.
+ return false;
+ }
+
+ @Override
+ public void adjustVolume(String packageName, String opPackageName, int pid, int uid,
+ boolean asSystemService, int direction, int flags, boolean useSuggested) {
+ // TODO(jaewan): Add API to adjust volume.
+ }
+
+ @Override
+ public boolean isActive() {
+ synchronized (mLock) {
+ return mIsConnected;
+ }
+ }
+
+ @Override
+ public boolean checkPlaybackActiveState(boolean expected) {
+ synchronized (mLock) {
+ return mIsConnected && mController.isPlaybackActive() == expected;
+ }
+ }
+
+ @Override
+ public boolean isPlaybackTypeLocal() {
+ // TODO(jaewan): Implement -- need API to know whether the playback is remote or local.
+ return true;
+ }
+
+ @Override
+ public void close() {
+ synchronized (mLock) {
+ // Call close regardless of the mIsAvailable. This may be called when it's not yet
+ // connected.
+ mController.close();
+ }
+ }
+
+ @Override
+ public boolean sendMediaButton(String packageName, int pid, int uid, boolean asSystemService,
+ KeyEvent ke, int sequenceId, ResultReceiver cb) {
+ // TODO(jaewan): Implement.
+ return false;
+ }
+
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ pw.println(prefix + "token=" + mSessionToken);
+ pw.println(prefix + "controller=" + mController);
+
+ final String indent = prefix + " ";
+ pw.println(indent + "playbackActive=" + mController.isPlaybackActive());
+ }
+
+ @Override
+ public String toString() {
+ // TODO(jaewan): Also add getId().
+ return getPackageName() + " (userId=" + getUserId() + ")";
+ }
+
+ private class Controller2Callback extends MediaController2.ControllerCallback {
+ @Override
+ public void onConnected(MediaController2 controller, Session2CommandGroup allowedCommands) {
+ if (DEBUG) {
+ Log.d(TAG, "connected to " + mSessionToken + ", allowed=" + allowedCommands);
+ }
+ synchronized (mLock) {
+ mIsConnected = true;
+ }
+ mService.onSessionActiveStateChanged(MediaSession2Record.this);
+ }
+
+ @Override
+ public void onDisconnected(MediaController2 controller) {
+ if (DEBUG) {
+ Log.d(TAG, "disconnected from " + mSessionToken);
+ }
+ synchronized (mLock) {
+ mIsConnected = false;
+ }
+ mService.onSessionDied(MediaSession2Record.this);
+ }
+
+ @Override
+ public void onPlaybackActiveChanged(MediaController2 controller, boolean playbackActive) {
+ if (DEBUG) {
+ Log.d(TAG, "playback active changed, " + mSessionToken + ", active="
+ + playbackActive);
+ }
+ mService.onSessionPlaybackStateChanged(MediaSession2Record.this, playbackActive);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index aa24ed26023a..df115d0f2773 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -56,13 +56,15 @@ import com.android.server.LocalServices;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
* This is the system implementation of a Session. Apps will interact with the
* MediaSession wrapper class instead.
*/
-public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable {
+// TODO(jaewan): Do not call service method directly -- introduce listener instead.
+public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionRecordImpl {
private static final String TAG = "MediaSessionRecord";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -72,6 +74,24 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable
*/
private static final int OPTIMISTIC_VOLUME_TIMEOUT = 1000;
+ /**
+ * These are states that usually indicate the user took an action and should
+ * bump priority regardless of the old state.
+ */
+ private static final List<Integer> ALWAYS_PRIORITY_STATES = Arrays.asList(
+ PlaybackState.STATE_FAST_FORWARDING,
+ PlaybackState.STATE_REWINDING,
+ PlaybackState.STATE_SKIPPING_TO_PREVIOUS,
+ PlaybackState.STATE_SKIPPING_TO_NEXT);
+ /**
+ * These are states that usually indicate the user took an action if they
+ * were entered from a non-priority state.
+ */
+ private static final List<Integer> TRANSITION_PRIORITY_STATES = Arrays.asList(
+ PlaybackState.STATE_BUFFERING,
+ PlaybackState.STATE_CONNECTING,
+ PlaybackState.STATE_PLAYING);
+
private final MessageHandler mHandler;
private final int mOwnerPid;
@@ -170,6 +190,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable
*
* @return Info that identifies this session.
*/
+ @Override
public String getPackageName() {
return mPackageName;
}
@@ -188,6 +209,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable
*
* @return The UID for this session.
*/
+ @Override
public int getUid() {
return mOwnerUid;
}
@@ -197,6 +219,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable
*
* @return The user id for this session.
*/
+ @Override
public int getUserId() {
return mUserId;
}
@@ -207,6 +230,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable
*
* @return True if this is a system priority session, false otherwise
*/
+ @Override
public boolean isSystemPriority() {
return (mFlags & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0;
}
@@ -220,7 +244,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable
* @param opPackageName The op package that made the original volume request.
* @param pid The pid that made the original volume request.
* @param uid The uid that made the original volume request.
- * @param caller caller binder. can be {@code null} if it's from the volume key.
* @param asSystemService {@code true} if the event sent to the session as if it was come from
* the system service instead of the app process. This helps sessions to distinguish
* between the key injection by the app and key events from the hardware devices.
@@ -318,9 +341,13 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable
/**
* Check if this session has been set to active by the app.
+ * <p>
+ * It's not used to prioritize sessions for dispatching media keys since API 26, but still used
+ * to filter session list in MediaSessionManager#getActiveSessions().
*
* @return True if the session is active, false otherwise.
*/
+ @Override
public boolean isActive() {
return mIsActive && !mDestroyed;
}
@@ -333,6 +360,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable
* @param expected True if playback is expected to be active. false otherwise.
* @return True if the session's playback matches with the expectation. false otherwise.
*/
+ @Override
public boolean checkPlaybackActiveState(boolean expected) {
if (mPlaybackState == null) {
return false;
@@ -345,13 +373,14 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable
*
* @return {@code true} if the playback is local.
*/
- public boolean isPlaybackLocal() {
+ @Override
+ public boolean isPlaybackTypeLocal() {
return mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL;
}
@Override
public void binderDied() {
- mService.sessionDied(this);
+ mService.onSessionDied(this);
}
/**
@@ -383,7 +412,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable
* @param sequenceId (optional) sequence id. Use this only when a wake lock is needed.
* @param cb (optional) result receiver to receive callback. Use this only when a wake lock is
* needed.
- * @return {@code true} if the attempt to send media button was successfuly.
+ * @return {@code true} if the attempt to send media button was successfully.
* {@code false} otherwise.
*/
public boolean sendMediaButton(String packageName, int pid, int uid, boolean asSystemService,
@@ -392,6 +421,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable
cb);
}
+ @Override
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + mTag + " " + this);
@@ -712,7 +742,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable
public void destroySession() throws RemoteException {
final long token = Binder.clearCallingIdentity();
try {
- mService.destroySession(MediaSessionRecord.this);
+ mService.onSessionDied(MediaSessionRecord.this);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -734,7 +764,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable
mIsActive = active;
final long token = Binder.clearCallingIdentity();
try {
- mService.updateSession(MediaSessionRecord.this);
+ mService.onSessionActiveStateChanged(MediaSessionRecord.this);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -801,12 +831,16 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable
? PlaybackState.STATE_NONE : mPlaybackState.getState();
int newState = state == null
? PlaybackState.STATE_NONE : state.getState();
+ boolean shouldUpdatePriority = ALWAYS_PRIORITY_STATES.contains(newState)
+ || (!TRANSITION_PRIORITY_STATES.contains(oldState)
+ && TRANSITION_PRIORITY_STATES.contains(newState));
synchronized (mLock) {
mPlaybackState = state;
}
final long token = Binder.clearCallingIdentity();
try {
- mService.onSessionPlaystateChanged(MediaSessionRecord.this, oldState, newState);
+ mService.onSessionPlaybackStateChanged(
+ MediaSessionRecord.this, shouldUpdatePriority);
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
new file mode 100644
index 000000000000..2cde89a7a6f6
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media;
+
+import android.media.AudioManager;
+import android.os.ResultReceiver;
+import android.view.KeyEvent;
+
+import java.io.PrintWriter;
+
+/**
+ * Common interfaces between {@link MediaSessionRecord} and {@link MediaSession2Record}.
+ */
+public interface MediaSessionRecordImpl extends AutoCloseable {
+
+ /**
+ * Get the info for this session.
+ *
+ * @return Info that identifies this session.
+ */
+ String getPackageName();
+
+ /**
+ * Get the UID this session was created for.
+ *
+ * @return The UID for this session.
+ */
+ int getUid();
+
+ /**
+ * Get the user id this session was created for.
+ *
+ * @return The user id for this session.
+ */
+ int getUserId();
+
+ /**
+ * Check if this session has system priorty and should receive media buttons
+ * before any other sessions.
+ *
+ * @return True if this is a system priority session, false otherwise
+ */
+ boolean isSystemPriority();
+
+ /**
+ * Send a volume adjustment to the session owner. Direction must be one of
+ * {@link AudioManager#ADJUST_LOWER}, {@link AudioManager#ADJUST_RAISE},
+ * {@link AudioManager#ADJUST_SAME}.
+ *
+ * @param packageName The package that made the original volume request.
+ * @param opPackageName The op package that made the original volume request.
+ * @param pid The pid that made the original volume request.
+ * @param uid The uid that made the original volume request.
+ * @param asSystemService {@code true} if the event sent to the session as if it was come from
+ * the system service instead of the app process. This helps sessions to distinguish
+ * between the key injection by the app and key events from the hardware devices.
+ * Should be used only when the volume key events aren't handled by foreground
+ * activity. {@code false} otherwise to tell session about the real caller.
+ * @param direction The direction to adjust volume in.
+ * @param flags Any of the flags from {@link AudioManager}.
+ * @param useSuggested True to use adjustSuggestedStreamVolume instead of
+ */
+ void adjustVolume(String packageName, String opPackageName, int pid, int uid,
+ boolean asSystemService, int direction, int flags, boolean useSuggested);
+
+ /**
+ * Check if this session has been set to active by the app. (i.e. ready to receive command and
+ * getters are available).
+ *
+ * @return True if the session is active, false otherwise.
+ */
+ // TODO(jaewan): Find better naming, or remove this from the MediaSessionRecordImpl.
+ boolean isActive();
+
+ /**
+ * Check if the session's playback active state matches with the expectation. This always return
+ * {@code false} if the playback state is unknown (e.g. {@code null}), where we cannot know the
+ * actual playback state associated with the session.
+ *
+ * @param expected True if playback is expected to be active. false otherwise.
+ * @return True if the session's playback matches with the expectation. false otherwise.
+ */
+ boolean checkPlaybackActiveState(boolean expected);
+
+ /**
+ * Check whether the playback type is local or remote.
+ * <p>
+ * <ul>
+ * <li>Local: volume changes the stream volume because playback happens on this device.</li>
+ * <li>Remote: volume is sent to the apps callback because playback happens on the remote
+ * device and we cannot know how to control the volume of it.</li>
+ * </ul>
+ *
+ * @return {@code true} if the playback is local. {@code false} if the playback is remote.
+ */
+ boolean isPlaybackTypeLocal();
+
+ /**
+ * Sends media button.
+ *
+ * @param packageName caller package name
+ * @param pid caller pid
+ * @param uid caller uid
+ * @param asSystemService {@code true} if the event sent to the session as if it was come from
+ * the system service instead of the app process.
+ * @param ke key events
+ * @param sequenceId (optional) sequence id. Use this only when a wake lock is needed.
+ * @param cb (optional) result receiver to receive callback. Use this only when a wake lock is
+ * needed.
+ * @return {@code true} if the attempt to send media button was successfully.
+ * {@code false} otherwise.
+ */
+ boolean sendMediaButton(String packageName, int pid, int uid, boolean asSystemService,
+ KeyEvent ke, int sequenceId, ResultReceiver cb);
+
+ /**
+ * Dumps internal state
+ *
+ * @param pw print writer
+ * @param prefix prefix
+ */
+ void dump(PrintWriter pw, String prefix);
+
+ /**
+ * Override {@link AutoCloseable#close} to tell not to throw exception.
+ */
+ @Override
+ void close();
+}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 0f059dba5274..f71fb582e3ed 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -40,10 +40,7 @@ import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.AudioPlaybackConfiguration;
import android.media.AudioSystem;
-import android.media.IAudioService;
import android.media.IRemoteVolumeController;
-import android.media.MediaController2;
-import android.media.Session2CommandGroup;
import android.media.Session2Token;
import android.media.session.IActiveSessionsListener;
import android.media.session.IOnMediaKeyEventDispatchedListener;
@@ -61,7 +58,6 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
@@ -123,11 +119,6 @@ public class MediaSessionService extends SystemService implements Monitor {
@GuardedBy("mLock")
private final ArrayList<SessionsListenerRecord> mSessionsListeners =
new ArrayList<SessionsListenerRecord>();
- // Map user id as index to list of Session2Tokens
- // TODO: Keep session2 info in MediaSessionStack for prioritizing both session1 and session2 in
- // one place.
- @GuardedBy("mLock")
- private final SparseArray<List<Session2Token>> mSession2TokensPerUser = new SparseArray<>();
@GuardedBy("mLock")
private final List<Session2TokensListenerRecord> mSession2TokensListenerRecords =
new ArrayList<>();
@@ -189,16 +180,11 @@ public class MediaSessionService extends SystemService implements Monitor {
updateUser();
}
- private IAudioService getAudioService() {
- IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
- return IAudioService.Stub.asInterface(b);
- }
-
private boolean isGlobalPriorityActiveLocked() {
return mGlobalPrioritySession != null && mGlobalPrioritySession.isActive();
}
- void updateSession(MediaSessionRecord record) {
+ void onSessionActiveStateChanged(MediaSessionRecordImpl record) {
synchronized (mLock) {
FullUserRecord user = getFullUserRecordLocked(record.getUserId());
if (user == null) {
@@ -215,12 +201,14 @@ public class MediaSessionService extends SystemService implements Monitor {
Log.w(TAG, "Unknown session updated. Ignoring.");
return;
}
- user.mPriorityStack.onSessionStateChange(record);
+ user.mPriorityStack.onSessionActiveStateChanged(record);
}
- mHandler.postSessionsChanged(record.getUserId());
+
+ mHandler.postSessionsChanged(record);
}
}
+ // Currently only media1 can become global priority session.
void setGlobalPrioritySession(MediaSessionRecord record) {
synchronized (mLock) {
FullUserRecord user = getFullUserRecordLocked(record.getUserId());
@@ -266,11 +254,13 @@ public class MediaSessionService extends SystemService implements Monitor {
List<Session2Token> getSession2TokensLocked(int userId) {
List<Session2Token> list = new ArrayList<>();
if (userId == USER_ALL) {
- for (int i = 0; i < mSession2TokensPerUser.size(); i++) {
- list.addAll(mSession2TokensPerUser.valueAt(i));
+ int size = mUserRecords.size();
+ for (int i = 0; i < size; i++) {
+ list.addAll(mUserRecords.valueAt(i).mPriorityStack.getSession2Tokens(userId));
}
} else {
- list.addAll(mSession2TokensPerUser.get(userId));
+ FullUserRecord user = getFullUserRecordLocked(userId);
+ list.addAll(user.mPriorityStack.getSession2Tokens(userId));
}
return list;
}
@@ -297,14 +287,15 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
- void onSessionPlaystateChanged(MediaSessionRecord record, int oldState, int newState) {
+ void onSessionPlaybackStateChanged(MediaSessionRecordImpl record,
+ boolean shouldUpdatePriority) {
synchronized (mLock) {
FullUserRecord user = getFullUserRecordLocked(record.getUserId());
if (user == null || !user.mPriorityStack.contains(record)) {
Log.d(TAG, "Unknown session changed playback state. Ignoring.");
return;
}
- user.mPriorityStack.onPlaystateChanged(record, oldState, newState);
+ user.mPriorityStack.onPlaybackStateChanged(record, shouldUpdatePriority);
}
}
@@ -347,7 +338,6 @@ public class MediaSessionService extends SystemService implements Monitor {
user.destroySessionsForUserLocked(userId);
}
}
- mSession2TokensPerUser.remove(userId);
updateUser();
}
}
@@ -366,13 +356,7 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
- void sessionDied(MediaSessionRecord session) {
- synchronized (mLock) {
- destroySessionLocked(session);
- }
- }
-
- void destroySession(MediaSessionRecord session) {
+ void onSessionDied(MediaSessionRecordImpl session) {
synchronized (mLock) {
destroySessionLocked(session);
}
@@ -393,9 +377,6 @@ public class MediaSessionService extends SystemService implements Monitor {
mUserRecords.put(userInfo.id, new FullUserRecord(userInfo.id));
}
}
- if (mSession2TokensPerUser.get(userInfo.id) == null) {
- mSession2TokensPerUser.put(userInfo.id, new ArrayList<>());
- }
}
}
// Ensure that the current full user exists.
@@ -405,9 +386,6 @@ public class MediaSessionService extends SystemService implements Monitor {
Log.w(TAG, "Cannot find FullUserInfo for the current user " + currentFullUserId);
mCurrentFullUserRecord = new FullUserRecord(currentFullUserId);
mUserRecords.put(currentFullUserId, mCurrentFullUserRecord);
- if (mSession2TokensPerUser.get(currentFullUserId) == null) {
- mSession2TokensPerUser.put(currentFullUserId, new ArrayList<>());
- }
}
mFullUserIds.put(currentFullUserId, currentFullUserId);
}
@@ -444,7 +422,7 @@ public class MediaSessionService extends SystemService implements Monitor {
* 5. We need to unlink to death from the cb binder
* 6. We need to tell the session to do any final cleanup (onDestroy)
*/
- private void destroySessionLocked(MediaSessionRecord session) {
+ private void destroySessionLocked(MediaSessionRecordImpl session) {
if (DEBUG) {
Log.d(TAG, "Destroying " + session);
}
@@ -461,7 +439,7 @@ public class MediaSessionService extends SystemService implements Monitor {
}
session.close();
- mHandler.postSessionsChanged(session.getUserId());
+ mHandler.postSessionsChanged(session);
}
private void enforcePackageName(String packageName, int uid) {
@@ -541,15 +519,6 @@ public class MediaSessionService extends SystemService implements Monitor {
return false;
}
- private MediaSessionRecord createSessionInternal(int callerPid, int callerUid, int userId,
- String callerPackageName, ISessionCallback cb, String tag, Bundle sessionInfo)
- throws RemoteException {
- synchronized (mLock) {
- return createSessionLocked(callerPid, callerUid, userId, callerPackageName, cb,
- tag, sessionInfo);
- }
- }
-
/*
* When a session is created the following things need to happen.
* 1. Its callback binder needs a link to death
@@ -557,29 +526,31 @@ public class MediaSessionService extends SystemService implements Monitor {
* 3. It needs to be added to the priority stack.
* 4. It needs to be added to the relevant user record.
*/
- private MediaSessionRecord createSessionLocked(int callerPid, int callerUid, int userId,
+ private MediaSessionRecord createSessionInternal(int callerPid, int callerUid, int userId,
String callerPackageName, ISessionCallback cb, String tag, Bundle sessionInfo) {
- FullUserRecord user = getFullUserRecordLocked(userId);
- if (user == null) {
- Log.w(TAG, "Request from invalid user: " + userId + ", pkg=" + callerPackageName);
- throw new RuntimeException("Session request from invalid user.");
- }
+ synchronized (mLock) {
+ FullUserRecord user = getFullUserRecordLocked(userId);
+ if (user == null) {
+ Log.w(TAG, "Request from invalid user: " + userId + ", pkg=" + callerPackageName);
+ throw new RuntimeException("Session request from invalid user.");
+ }
- final MediaSessionRecord session;
- try {
- session = new MediaSessionRecord(callerPid, callerUid, userId,
- callerPackageName, cb, tag, sessionInfo, this, mHandler.getLooper());
- } catch (RemoteException e) {
- throw new RuntimeException("Media Session owner died prematurely.", e);
- }
+ final MediaSessionRecord session;
+ try {
+ session = new MediaSessionRecord(callerPid, callerUid, userId,
+ callerPackageName, cb, tag, sessionInfo, this, mHandler.getLooper());
+ } catch (RemoteException e) {
+ throw new RuntimeException("Media Session owner died prematurely.", e);
+ }
- user.mPriorityStack.addSession(session);
- mHandler.postSessionsChanged(userId);
+ user.mPriorityStack.addSession(session);
+ mHandler.postSessionsChanged(session);
- if (DEBUG) {
- Log.d(TAG, "Created session for " + callerPackageName + " with tag " + tag);
+ if (DEBUG) {
+ Log.d(TAG, "Created session for " + callerPackageName + " with tag " + tag);
+ }
+ return session;
}
- return session;
}
private int findIndexOfSessionsListenerLocked(IActiveSessionsListener listener) {
@@ -600,16 +571,16 @@ public class MediaSessionService extends SystemService implements Monitor {
return -1;
}
- private void pushSessionsChanged(int userId) {
+ private void pushSession1Changed(int userId) {
synchronized (mLock) {
FullUserRecord user = getFullUserRecordLocked(userId);
if (user == null) {
- Log.w(TAG, "pushSessionsChanged failed. No user with id=" + userId);
+ Log.w(TAG, "pushSession1ChangedOnHandler failed. No user with id=" + userId);
return;
}
List<MediaSessionRecord> records = getActiveSessionsLocked(userId);
int size = records.size();
- ArrayList<MediaSession.Token> tokens = new ArrayList<MediaSession.Token>();
+ ArrayList<MediaSession.Token> tokens = new ArrayList<>();
for (int i = 0; i < size; i++) {
tokens.add(records.get(i).getSessionToken());
}
@@ -629,6 +600,27 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
+ void pushSession2Changed(int userId) {
+ synchronized (mLock) {
+ List<Session2Token> allSession2Tokens = getSession2TokensLocked(USER_ALL);
+ List<Session2Token> session2Tokens = getSession2TokensLocked(userId);
+
+ for (int i = mSession2TokensListenerRecords.size() - 1; i >= 0; i--) {
+ Session2TokensListenerRecord listenerRecord = mSession2TokensListenerRecords.get(i);
+ try {
+ if (listenerRecord.userId == USER_ALL) {
+ listenerRecord.listener.onSession2TokensChanged(allSession2Tokens);
+ } else if (listenerRecord.userId == userId) {
+ listenerRecord.listener.onSession2TokensChanged(session2Tokens);
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to notify Session2Token change. Removing listener.", e);
+ mSession2TokensListenerRecords.remove(i);
+ }
+ }
+ }
+ }
+
private void pushRemoteVolumeUpdateLocked(int userId) {
FullUserRecord user = getFullUserRecordLocked(userId);
if (user == null) {
@@ -638,8 +630,13 @@ public class MediaSessionService extends SystemService implements Monitor {
synchronized (mLock) {
int size = mRemoteVolumeControllers.beginBroadcast();
- MediaSessionRecord record = user.mPriorityStack.getDefaultRemoteSession(userId);
- MediaSession.Token token = record == null ? null : record.getSessionToken();
+ MediaSessionRecordImpl record = user.mPriorityStack.getDefaultRemoteSession(userId);
+ if (record instanceof MediaSession2Record) {
+ // TODO(jaewan): Implement
+ return;
+ }
+ MediaSession.Token token = record == null
+ ? null : ((MediaSessionRecord) record).getSessionToken();
for (int i = size - 1; i >= 0; i--) {
try {
@@ -653,34 +650,15 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
- void pushSession2TokensChangedLocked(int userId) {
- List<Session2Token> allSession2Tokens = getSession2TokensLocked(USER_ALL);
- List<Session2Token> session2Tokens = getSession2TokensLocked(userId);
-
- for (int i = mSession2TokensListenerRecords.size() - 1; i >= 0; i--) {
- Session2TokensListenerRecord listenerRecord = mSession2TokensListenerRecords.get(i);
- try {
- if (listenerRecord.userId == USER_ALL) {
- listenerRecord.listener.onSession2TokensChanged(allSession2Tokens);
- } else if (listenerRecord.userId == userId) {
- listenerRecord.listener.onSession2TokensChanged(session2Tokens);
- }
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to notify Session2Token change. Removing listener.", e);
- mSession2TokensListenerRecords.remove(i);
- }
- }
- }
-
/**
* Called when the media button receiver for the {@code record} is changed.
*
* @param record the media session whose media button receiver is updated.
*/
- public void onMediaButtonReceiverChanged(MediaSessionRecord record) {
+ public void onMediaButtonReceiverChanged(MediaSessionRecordImpl record) {
synchronized (mLock) {
FullUserRecord user = getFullUserRecordLocked(record.getUserId());
- MediaSessionRecord mediaButtonSession =
+ MediaSessionRecordImpl mediaButtonSession =
user.mPriorityStack.getMediaButtonSession();
if (record == mediaButtonSession) {
user.rememberMediaButtonReceiverLocked(mediaButtonSession);
@@ -868,39 +846,34 @@ public class MediaSessionService extends SystemService implements Monitor {
pw.println(indent + "Restored MediaButtonReceiverComponentType: "
+ mRestoredMediaButtonReceiverComponentType);
mPriorityStack.dump(pw, indent);
- pw.println(indent + "Session2Tokens:");
- for (int i = 0; i < mSession2TokensPerUser.size(); i++) {
- List<Session2Token> list = mSession2TokensPerUser.valueAt(i);
- if (list == null || list.size() == 0) {
- continue;
- }
- for (Session2Token token : list) {
- pw.println(indent + " " + token);
- }
- }
}
@Override
- public void onMediaButtonSessionChanged(MediaSessionRecord oldMediaButtonSession,
- MediaSessionRecord newMediaButtonSession) {
+ public void onMediaButtonSessionChanged(MediaSessionRecordImpl oldMediaButtonSession,
+ MediaSessionRecordImpl newMediaButtonSession) {
if (DEBUG_KEY_EVENT) {
Log.d(TAG, "Media button session is changed to " + newMediaButtonSession);
}
synchronized (mLock) {
if (oldMediaButtonSession != null) {
- mHandler.postSessionsChanged(oldMediaButtonSession.getUserId());
+ mHandler.postSessionsChanged(oldMediaButtonSession);
}
if (newMediaButtonSession != null) {
rememberMediaButtonReceiverLocked(newMediaButtonSession);
- mHandler.postSessionsChanged(newMediaButtonSession.getUserId());
+ mHandler.postSessionsChanged(newMediaButtonSession);
}
pushAddressedPlayerChangedLocked();
}
}
// Remember media button receiver and keep it in the persistent storage.
- public void rememberMediaButtonReceiverLocked(MediaSessionRecord record) {
- PendingIntent receiver = record.getMediaButtonReceiver();
+ public void rememberMediaButtonReceiverLocked(MediaSessionRecordImpl record) {
+ if (record instanceof MediaSession2Record) {
+ // TODO(jaewan): Implement
+ return;
+ }
+ MediaSessionRecord sessionRecord = (MediaSessionRecord) record;
+ PendingIntent receiver = sessionRecord.getMediaButtonReceiver();
mLastMediaButtonReceiver = receiver;
mRestoredMediaButtonReceiver = null;
mRestoredMediaButtonReceiverComponentType = COMPONENT_TYPE_INVALID;
@@ -925,10 +898,15 @@ public class MediaSessionService extends SystemService implements Monitor {
private void pushAddressedPlayerChangedLocked(
IOnMediaKeyEventSessionChangedListener callback) {
try {
- MediaSessionRecord mediaButtonSession = getMediaButtonSessionLocked();
+ MediaSessionRecordImpl mediaButtonSession = getMediaButtonSessionLocked();
if (mediaButtonSession != null) {
- callback.onMediaKeyEventSessionChanged(mediaButtonSession.getPackageName(),
- mediaButtonSession.getSessionToken());
+ if (mediaButtonSession instanceof MediaSessionRecord) {
+ MediaSessionRecord session1 = (MediaSessionRecord) mediaButtonSession;
+ callback.onMediaKeyEventSessionChanged(session1.getPackageName(),
+ session1.getSessionToken());
+ } else {
+ // TODO(jaewan): Implement
+ }
} else if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null) {
callback.onMediaKeyEventSessionChanged(
mCurrentFullUserRecord.mLastMediaButtonReceiver
@@ -951,7 +929,7 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
- private MediaSessionRecord getMediaButtonSessionLocked() {
+ private MediaSessionRecordImpl getMediaButtonSessionLocked() {
return isGlobalPriorityActiveLocked()
? mGlobalPrioritySession : mPriorityStack.getMediaButtonSession();
}
@@ -1132,14 +1110,13 @@ public class MediaSessionService extends SystemService implements Monitor {
throw new SecurityException("Unexpected Session2Token's UID, expected=" + uid
+ " but actually=" + sessionToken.getUid());
}
- Controller2Callback callback = new Controller2Callback(sessionToken);
- // Note: It's safe not to keep controller here because it wouldn't be GC'ed until
- // it's closed.
- // TODO: Keep controller as well for better readability
- // because the GC behavior isn't straightforward.
- MediaController2 controller = new MediaController2.Builder(mContext, sessionToken)
- .setControllerCallback(new HandlerExecutor(mHandler), callback)
- .build();
+ MediaSession2Record record = new MediaSession2Record(
+ sessionToken, MediaSessionService.this, mHandler.getLooper());
+ synchronized (mLock) {
+ FullUserRecord user = getFullUserRecordLocked(record.getUserId());
+ user.mPriorityStack.addSession(record);
+ }
+ // Do not immediately notify changes -- do so when framework can dispatch command
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1180,7 +1157,8 @@ public class MediaSessionService extends SystemService implements Monitor {
null /* optional packageName */);
List<Session2Token> result;
synchronized (mLock) {
- result = getSession2TokensLocked(resolvedUserId);
+ FullUserRecord user = getFullUserRecordLocked(userId);
+ result = user.mPriorityStack.getSession2Tokens(resolvedUserId);
}
return new ParceledListSlice(result);
} finally {
@@ -2018,7 +1996,7 @@ public class MediaSessionService extends SystemService implements Monitor {
private void dispatchAdjustVolumeLocked(String packageName, String opPackageName, int pid,
int uid, boolean asSystemService, int suggestedStream, int direction, int flags) {
- MediaSessionRecord session = isGlobalPriorityActiveLocked() ? mGlobalPrioritySession
+ MediaSessionRecordImpl session = isGlobalPriorityActiveLocked() ? mGlobalPrioritySession
: mCurrentFullUserRecord.mPriorityStack.getDefaultVolumeSession();
boolean preferSuggestedStream = false;
@@ -2109,7 +2087,13 @@ public class MediaSessionService extends SystemService implements Monitor {
private void dispatchMediaKeyEventLocked(String packageName, int pid, int uid,
boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
- MediaSessionRecord session = mCurrentFullUserRecord.getMediaButtonSessionLocked();
+ if (mCurrentFullUserRecord.getMediaButtonSessionLocked()
+ instanceof MediaSession2Record) {
+ // TODO(jaewan): Implement
+ return;
+ }
+ MediaSessionRecord session =
+ (MediaSessionRecord) mCurrentFullUserRecord.getMediaButtonSessionLocked();
if (session != null) {
if (DEBUG_KEY_EVENT) {
Log.d(TAG, "Sending " + keyEvent + " to " + session);
@@ -2389,15 +2373,19 @@ public class MediaSessionService extends SystemService implements Monitor {
}
final class MessageHandler extends Handler {
- private static final int MSG_SESSIONS_CHANGED = 1;
- private static final int MSG_VOLUME_INITIAL_DOWN = 2;
+ private static final int MSG_SESSIONS_1_CHANGED = 1;
+ private static final int MSG_SESSIONS_2_CHANGED = 2;
+ private static final int MSG_VOLUME_INITIAL_DOWN = 3;
private final SparseArray<Integer> mIntegerCache = new SparseArray<>();
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MSG_SESSIONS_CHANGED:
- pushSessionsChanged((int) msg.obj);
+ case MSG_SESSIONS_1_CHANGED:
+ pushSession1Changed((int) msg.obj);
+ break;
+ case MSG_SESSIONS_2_CHANGED:
+ pushSession2Changed((int) msg.obj);
break;
case MSG_VOLUME_INITIAL_DOWN:
synchronized (mLock) {
@@ -2412,41 +2400,19 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
- public void postSessionsChanged(int userId) {
+ public void postSessionsChanged(MediaSessionRecordImpl record) {
// Use object instead of the arguments when posting message to remove pending requests.
- Integer userIdInteger = mIntegerCache.get(userId);
+ Integer userIdInteger = mIntegerCache.get(record.getUserId());
if (userIdInteger == null) {
- userIdInteger = Integer.valueOf(userId);
- mIntegerCache.put(userId, userIdInteger);
+ userIdInteger = Integer.valueOf(record.getUserId());
+ mIntegerCache.put(record.getUserId(), userIdInteger);
}
- removeMessages(MSG_SESSIONS_CHANGED, userIdInteger);
- obtainMessage(MSG_SESSIONS_CHANGED, userIdInteger).sendToTarget();
- }
- }
- private class Controller2Callback extends MediaController2.ControllerCallback {
- private final Session2Token mToken;
-
- Controller2Callback(Session2Token token) {
- mToken = token;
- }
-
- @Override
- public void onConnected(MediaController2 controller, Session2CommandGroup allowedCommands) {
- synchronized (mLock) {
- int userId = UserHandle.getUserId(mToken.getUid());
- mSession2TokensPerUser.get(userId).add(mToken);
- pushSession2TokensChangedLocked(userId);
- }
- }
-
- @Override
- public void onDisconnected(MediaController2 controller) {
- synchronized (mLock) {
- int userId = UserHandle.getUserId(mToken.getUid());
- mSession2TokensPerUser.get(userId).remove(mToken);
- pushSession2TokensChangedLocked(userId);
- }
+ int msg = (record instanceof MediaSessionRecord)
+ ? MSG_SESSIONS_1_CHANGED : MSG_SESSIONS_2_CHANGED;
+ removeMessages(msg, userIdInteger);
+ obtainMessage(msg, userIdInteger).sendToTarget();
}
}
+
}
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index 732563f6e05e..7bb7cf4b74ad 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -16,8 +16,8 @@
package com.android.server.media;
+import android.media.Session2Token;
import android.media.session.MediaSession;
-import android.media.session.PlaybackState;
import android.os.Debug;
import android.os.UserHandle;
import android.util.IntArray;
@@ -45,51 +45,30 @@ class MediaSessionStack {
/**
* Called when the media button session is changed.
*/
- void onMediaButtonSessionChanged(MediaSessionRecord oldMediaButtonSession,
- MediaSessionRecord newMediaButtonSession);
+ void onMediaButtonSessionChanged(MediaSessionRecordImpl oldMediaButtonSession,
+ MediaSessionRecordImpl newMediaButtonSession);
}
/**
- * These are states that usually indicate the user took an action and should
- * bump priority regardless of the old state.
+ * Sorted list of the media sessions
*/
- private static final int[] ALWAYS_PRIORITY_STATES = {
- PlaybackState.STATE_FAST_FORWARDING,
- PlaybackState.STATE_REWINDING,
- PlaybackState.STATE_SKIPPING_TO_PREVIOUS,
- PlaybackState.STATE_SKIPPING_TO_NEXT };
- /**
- * These are states that usually indicate the user took an action if they
- * were entered from a non-priority state.
- */
- private static final int[] TRANSITION_PRIORITY_STATES = {
- PlaybackState.STATE_BUFFERING,
- PlaybackState.STATE_CONNECTING,
- PlaybackState.STATE_PLAYING };
-
- /**
- * Sorted list of the media sessions.
- * The session of which PlaybackState is changed to ALWAYS_PRIORITY_STATES or
- * TRANSITION_PRIORITY_STATES comes first.
- * @see #shouldUpdatePriority
- */
- private final List<MediaSessionRecord> mSessions = new ArrayList<MediaSessionRecord>();
+ private final List<MediaSessionRecordImpl> mSessions = new ArrayList<>();
private final AudioPlayerStateMonitor mAudioPlayerStateMonitor;
private final OnMediaButtonSessionChangedListener mOnMediaButtonSessionChangedListener;
/**
* The media button session which receives media key events.
- * It could be null if the previous media buttion session is released.
+ * It could be null if the previous media button session is released.
*/
- private MediaSessionRecord mMediaButtonSession;
+ private MediaSessionRecordImpl mMediaButtonSession;
- private MediaSessionRecord mCachedVolumeDefault;
+ private MediaSessionRecordImpl mCachedVolumeDefault;
/**
* Cache the result of the {@link #getActiveSessions} per user.
*/
- private final SparseArray<ArrayList<MediaSessionRecord>> mCachedActiveLists =
+ private final SparseArray<List<MediaSessionRecord>> mCachedActiveLists =
new SparseArray<>();
MediaSessionStack(AudioPlayerStateMonitor monitor, OnMediaButtonSessionChangedListener listener) {
@@ -102,7 +81,7 @@ class MediaSessionStack {
*
* @param record The record to add.
*/
- public void addSession(MediaSessionRecord record) {
+ public void addSession(MediaSessionRecordImpl record) {
mSessions.add(record);
clearCache(record.getUserId());
@@ -117,7 +96,7 @@ class MediaSessionStack {
*
* @param record The record to remove.
*/
- public void removeSession(MediaSessionRecord record) {
+ public void removeSession(MediaSessionRecordImpl record) {
mSessions.remove(record);
if (mMediaButtonSession == record) {
// When the media button session is removed, nullify the media button session and do not
@@ -131,7 +110,7 @@ class MediaSessionStack {
/**
* Return if the record exists in the priority tracker.
*/
- public boolean contains(MediaSessionRecord record) {
+ public boolean contains(MediaSessionRecordImpl record) {
return mSessions.contains(record);
}
@@ -142,9 +121,12 @@ class MediaSessionStack {
* @return the MediaSessionRecord. Can be {@code null} if the session is gone meanwhile.
*/
public MediaSessionRecord getMediaSessionRecord(MediaSession.Token sessionToken) {
- for (MediaSessionRecord record : mSessions) {
- if (Objects.equals(record.getSessionToken(), sessionToken)) {
- return record;
+ for (MediaSessionRecordImpl record : mSessions) {
+ if (record instanceof MediaSessionRecord) {
+ MediaSessionRecord session1 = (MediaSessionRecord) record;
+ if (Objects.equals(session1.getSessionToken(), sessionToken)) {
+ return session1;
+ }
}
}
return null;
@@ -154,15 +136,15 @@ class MediaSessionStack {
* Notify the priority tracker that a session's playback state changed.
*
* @param record The record that changed.
- * @param oldState Its old playback state.
- * @param newState Its new playback state.
+ * @param shouldUpdatePriority {@code true} if the record needs to prioritized
*/
- public void onPlaystateChanged(MediaSessionRecord record, int oldState, int newState) {
- if (shouldUpdatePriority(oldState, newState)) {
+ public void onPlaybackStateChanged(
+ MediaSessionRecordImpl record, boolean shouldUpdatePriority) {
+ if (shouldUpdatePriority) {
mSessions.remove(record);
mSessions.add(0, record);
clearCache(record.getUserId());
- } else if (!MediaSession.isActiveState(newState)) {
+ } else if (record.checkPlaybackActiveState(false)) {
// Just clear the volume cache when a state goes inactive
mCachedVolumeDefault = null;
}
@@ -172,7 +154,7 @@ class MediaSessionStack {
// In that case, we pick the media session whose PlaybackState matches
// the audio playback configuration.
if (mMediaButtonSession != null && mMediaButtonSession.getUid() == record.getUid()) {
- MediaSessionRecord newMediaButtonSession =
+ MediaSessionRecordImpl newMediaButtonSession =
findMediaButtonSession(mMediaButtonSession.getUid());
if (newMediaButtonSession != mMediaButtonSession) {
updateMediaButtonSession(newMediaButtonSession);
@@ -185,7 +167,7 @@ class MediaSessionStack {
*
* @param record The record that changed.
*/
- public void onSessionStateChange(MediaSessionRecord record) {
+ public void onSessionActiveStateChanged(MediaSessionRecordImpl record) {
// For now just clear the cache. Eventually we'll selectively clear
// depending on what changed.
clearCache(record.getUserId());
@@ -203,7 +185,7 @@ class MediaSessionStack {
}
IntArray audioPlaybackUids = mAudioPlayerStateMonitor.getSortedAudioPlaybackClientUids();
for (int i = 0; i < audioPlaybackUids.size(); i++) {
- MediaSessionRecord mediaButtonSession =
+ MediaSessionRecordImpl mediaButtonSession =
findMediaButtonSession(audioPlaybackUids.get(i));
if (mediaButtonSession != null) {
// Found the media button session.
@@ -225,9 +207,9 @@ class MediaSessionStack {
* @return The media button session. Returns {@code null} if the app doesn't have a media
* session.
*/
- private MediaSessionRecord findMediaButtonSession(int uid) {
- MediaSessionRecord mediaButtonSession = null;
- for (MediaSessionRecord session : mSessions) {
+ private MediaSessionRecordImpl findMediaButtonSession(int uid) {
+ MediaSessionRecordImpl mediaButtonSession = null;
+ for (MediaSessionRecordImpl session : mSessions) {
if (uid == session.getUid()) {
if (session.checkPlaybackActiveState(
mAudioPlayerStateMonitor.isPlaybackActive(session.getUid()))) {
@@ -253,8 +235,8 @@ class MediaSessionStack {
* for all users in this {@link MediaSessionStack}.
* @return All the active sessions in priority order.
*/
- public ArrayList<MediaSessionRecord> getActiveSessions(int userId) {
- ArrayList<MediaSessionRecord> cachedActiveList = mCachedActiveLists.get(userId);
+ public List<MediaSessionRecord> getActiveSessions(int userId) {
+ List<MediaSessionRecord> cachedActiveList = mCachedActiveLists.get(userId);
if (cachedActiveList == null) {
cachedActiveList = getPriorityList(true, userId);
mCachedActiveLists.put(userId, cachedActiveList);
@@ -263,26 +245,46 @@ class MediaSessionStack {
}
/**
+ * Gets the session2 tokens.
+ *
+ * @param userId The user to check. It can be {@link UserHandle#USER_ALL} to get all session2
+ * tokens for all users in this {@link MediaSessionStack}.
+ * @return All session2 tokens.
+ */
+ public List<Session2Token> getSession2Tokens(int userId) {
+ ArrayList<Session2Token> session2Records = new ArrayList<>();
+ for (MediaSessionRecordImpl record : mSessions) {
+ if ((userId == UserHandle.USER_ALL || record.getUserId() == userId)
+ && record.isActive()
+ && record instanceof MediaSession2Record) {
+ MediaSession2Record session2 = (MediaSession2Record) record;
+ session2Records.add(session2.getSession2Token());
+ }
+ }
+ return session2Records;
+ }
+
+ /**
* Get the media button session which receives the media button events.
*
* @return The media button session or null.
*/
- public MediaSessionRecord getMediaButtonSession() {
+ public MediaSessionRecordImpl getMediaButtonSession() {
return mMediaButtonSession;
}
- private void updateMediaButtonSession(MediaSessionRecord newMediaButtonSession) {
- MediaSessionRecord oldMediaButtonSession = mMediaButtonSession;
+ private void updateMediaButtonSession(MediaSessionRecordImpl newMediaButtonSession) {
+ MediaSessionRecordImpl oldMediaButtonSession = mMediaButtonSession;
mMediaButtonSession = newMediaButtonSession;
mOnMediaButtonSessionChangedListener.onMediaButtonSessionChanged(
oldMediaButtonSession, newMediaButtonSession);
}
- public MediaSessionRecord getDefaultVolumeSession() {
+ public MediaSessionRecordImpl getDefaultVolumeSession() {
if (mCachedVolumeDefault != null) {
return mCachedVolumeDefault;
}
- ArrayList<MediaSessionRecord> records = getPriorityList(true, UserHandle.USER_ALL);
+ List<MediaSessionRecord> records = getPriorityList(true, UserHandle.USER_ALL);
int size = records.size();
for (int i = 0; i < size; i++) {
MediaSessionRecord record = records.get(i);
@@ -294,13 +296,13 @@ class MediaSessionStack {
return null;
}
- public MediaSessionRecord getDefaultRemoteSession(int userId) {
- ArrayList<MediaSessionRecord> records = getPriorityList(true, userId);
+ public MediaSessionRecordImpl getDefaultRemoteSession(int userId) {
+ List<MediaSessionRecord> records = getPriorityList(true, userId);
int size = records.size();
for (int i = 0; i < size; i++) {
MediaSessionRecord record = records.get(i);
- if (!record.isPlaybackLocal()) {
+ if (!record.isPlaybackTypeLocal()) {
return record;
}
}
@@ -308,16 +310,11 @@ class MediaSessionStack {
}
public void dump(PrintWriter pw, String prefix) {
- ArrayList<MediaSessionRecord> sortedSessions = getPriorityList(false,
- UserHandle.USER_ALL);
- int count = sortedSessions.size();
pw.println(prefix + "Media button session is " + mMediaButtonSession);
- pw.println(prefix + "Sessions Stack - have " + count + " sessions:");
+ pw.println(prefix + "Sessions Stack - have " + mSessions.size() + " sessions:");
String indent = prefix + " ";
- for (int i = 0; i < count; i++) {
- MediaSessionRecord record = sortedSessions.get(i);
+ for (MediaSessionRecordImpl record : mSessions) {
record.dump(pw, indent);
- pw.println();
}
}
@@ -335,17 +332,19 @@ class MediaSessionStack {
* will return sessions for all users.
* @return The priority sorted list of sessions.
*/
- public ArrayList<MediaSessionRecord> getPriorityList(boolean activeOnly, int userId) {
- ArrayList<MediaSessionRecord> result = new ArrayList<MediaSessionRecord>();
+ public List<MediaSessionRecord> getPriorityList(boolean activeOnly, int userId) {
+ List<MediaSessionRecord> result = new ArrayList<MediaSessionRecord>();
int lastPlaybackActiveIndex = 0;
int lastActiveIndex = 0;
- int size = mSessions.size();
- for (int i = 0; i < size; i++) {
- final MediaSessionRecord session = mSessions.get(i);
+ for (MediaSessionRecordImpl record : mSessions) {
+ if (!(record instanceof MediaSessionRecord)) {
+ continue;
+ }
+ final MediaSessionRecord session = (MediaSessionRecord) record;
- if (userId != UserHandle.USER_ALL && userId != session.getUserId()) {
- // Filter out sessions for the wrong user
+ if ((userId != UserHandle.USER_ALL && userId != session.getUserId())) {
+ // Filter out sessions for the wrong user or session2.
continue;
}
@@ -369,26 +368,6 @@ class MediaSessionStack {
return result;
}
- private boolean shouldUpdatePriority(int oldState, int newState) {
- if (containsState(newState, ALWAYS_PRIORITY_STATES)) {
- return true;
- }
- if (!containsState(oldState, TRANSITION_PRIORITY_STATES)
- && containsState(newState, TRANSITION_PRIORITY_STATES)) {
- return true;
- }
- return false;
- }
-
- private boolean containsState(int state, int[] states) {
- for (int i = 0; i < states.length; i++) {
- if (states[i] == state) {
- return true;
- }
- }
- return false;
- }
-
private void clearCache(int userId) {
mCachedVolumeDefault = null;
mCachedActiveLists.remove(userId);
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 53027655390b..daf603012391 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -91,7 +91,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
}
@Override
- public void requestCreateSession(String packageName, String routeId, String controlCategory,
+ public void requestCreateSession(String packageName, String routeId, String routeType,
long requestId) {
// Do nothing
}
@@ -141,8 +141,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
: MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
.setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
.setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC))
- .addSupportedCategory(CATEGORY_LIVE_AUDIO)
- .addSupportedCategory(CATEGORY_LIVE_VIDEO)
+ .addRouteType(CATEGORY_LIVE_AUDIO)
+ .addRouteType(CATEGORY_LIVE_VIDEO)
.build();
AudioRoutesInfo newAudioRoutes = null;
@@ -181,8 +181,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
: MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
.setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
.setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC))
- .addSupportedCategory(CATEGORY_LIVE_AUDIO)
- .addSupportedCategory(CATEGORY_LIVE_VIDEO)
+ .addRouteType(CATEGORY_LIVE_AUDIO)
+ .addRouteType(CATEGORY_LIVE_VIDEO)
.build();
if (!TextUtils.equals(newRoutes.bluetoothName, mCurAudioRoutesInfo.bluetoothName)) {
@@ -193,7 +193,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
mCurAudioRoutesInfo.bluetoothName)
.setDescription(mContext.getResources().getText(
R.string.bluetooth_a2dp_audio_route_name).toString())
- .addSupportedCategory(CATEGORY_LIVE_AUDIO)
+ .addRouteType(CATEGORY_LIVE_AUDIO)
.build();
} else {
mBluetoothA2dpRoute = null;
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index 3ca1803262e7..22b01bee6c6a 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -229,7 +229,7 @@ public class NetworkStatsFactory {
entry.txPackets += reader.nextLong();
}
- stats.addValues(entry);
+ stats.addEntry(entry);
reader.finishLine();
}
} catch (NullPointerException|NumberFormatException e) {
@@ -279,7 +279,7 @@ public class NetworkStatsFactory {
entry.txBytes = reader.nextLong();
entry.txPackets = reader.nextLong();
- stats.addValues(entry);
+ stats.addEntry(entry);
reader.finishLine();
}
} catch (NullPointerException|NumberFormatException e) {
@@ -439,7 +439,7 @@ public class NetworkStatsFactory {
if ((limitIfaces == null || ArrayUtils.contains(limitIfaces, entry.iface))
&& (limitUid == UID_ALL || limitUid == entry.uid)
&& (limitTag == TAG_ALL || limitTag == entry.tag)) {
- stats.addValues(entry);
+ stats.addEntry(entry);
}
reader.finishLine();
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index ec8a8e7c4c1a..7a6f29764f09 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -27,6 +27,7 @@ import static android.net.ConnectivityManager.isNetworkTypeMobile;
import static android.net.NetworkStack.checkNetworkStackPermission;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.IFACE_VT;
import static android.net.NetworkStats.INTERFACES_ALL;
import static android.net.NetworkStats.METERED_ALL;
import static android.net.NetworkStats.ROAMING_ALL;
@@ -211,7 +212,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
/**
* Virtual network interface for video telephony. This is for VT data usage counting purpose.
*/
- public static final String VT_INTERFACE = "vt_data0";
+ // TODO: Remove this after no one is using it.
+ public static final String VT_INTERFACE = NetworkStats.IFACE_VT;
/**
* Settings that can be changed externally.
@@ -712,7 +714,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
final NetworkStats stats = new NetworkStats(end - start, 1);
- stats.addValues(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE,
+ stats.addEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE,
METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets,
entry.txBytes, entry.txPackets, entry.operations));
return stats;
@@ -1179,8 +1181,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(),
ident.getRoaming(), true /* metered */,
true /* onDefaultNetwork */);
- findOrCreateNetworkIdentitySet(mActiveIfaces, VT_INTERFACE).add(vtIdent);
- findOrCreateNetworkIdentitySet(mActiveUidIfaces, VT_INTERFACE).add(vtIdent);
+ findOrCreateNetworkIdentitySet(mActiveIfaces, IFACE_VT).add(vtIdent);
+ findOrCreateNetworkIdentitySet(mActiveUidIfaces, IFACE_VT).add(vtIdent);
}
if (isMobile) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 426cd01d3d0b..4dcdf7ea0ecc 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -140,6 +140,7 @@ import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@@ -209,6 +210,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill";
private static final int[] EMPTY_CHILD_SESSION_ARRAY = {};
+ private static final String SYSTEM_DATA_LOADER_PACKAGE = "android";
+
// TODO: enforce INSTALL_ALLOW_TEST
// TODO: enforce INSTALL_ALLOW_DOWNGRADE
@@ -555,6 +558,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
params.dataLoaderParams);
}
}
+
+ if (isStreamingInstallation()
+ && this.params.dataLoaderParams.getComponentName().getPackageName()
+ == SYSTEM_DATA_LOADER_PACKAGE) {
+ assertShellOrSystemCalling("System data loaders");
+ }
}
public SessionInfo generateInfo() {
@@ -770,6 +779,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
+ private void assertShellOrSystemCalling(String operation) {
+ switch (Binder.getCallingUid()) {
+ case android.os.Process.SHELL_UID:
+ case android.os.Process.ROOT_UID:
+ case android.os.Process.SYSTEM_UID:
+ break;
+ default:
+ throw new SecurityException(operation + " only supported from shell or system");
+ }
+ }
+
private void assertCanWrite(boolean reverseMode) {
if (isDataLoaderInstallation()) {
throw new IllegalStateException(
@@ -780,15 +800,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
assertPreparedAndNotSealedLocked("assertCanWrite");
}
if (reverseMode) {
- switch (Binder.getCallingUid()) {
- case android.os.Process.SHELL_UID:
- case android.os.Process.ROOT_UID:
- case android.os.Process.SYSTEM_UID:
- break;
- default:
- throw new SecurityException(
- "Reverse mode only supported from shell or system");
- }
+ assertShellOrSystemCalling("Reverse mode");
}
}
@@ -1025,13 +1037,24 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
}
- private class FileSystemConnector extends IPackageInstallerSessionFileSystemConnector.Stub {
+ private final class FileSystemConnector extends
+ IPackageInstallerSessionFileSystemConnector.Stub {
+ final Set<String> mAddedFiles;
+
+ FileSystemConnector(List<InstallationFile> addedFiles) {
+ mAddedFiles = addedFiles.stream().map(file -> file.getName()).collect(
+ Collectors.toSet());
+ }
+
@Override
public void writeData(String name, long offsetBytes, long lengthBytes,
ParcelFileDescriptor incomingFd) {
if (incomingFd == null) {
throw new IllegalArgumentException("incomingFd can't be null");
}
+ if (!mAddedFiles.contains(name)) {
+ throw new SecurityException("File name is not in the list of added files.");
+ }
try {
doWriteInternal(name, offsetBytes, lengthBytes, incomingFd);
} catch (IOException e) {
@@ -2467,8 +2490,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return;
}
- FileSystemConnector connector = new FileSystemConnector();
-
List<InstallationFile> addedFiles = mFiles.stream().filter(
file -> sAddedFilter.accept(new File(file.name))).map(
file -> new InstallationFile(
@@ -2480,6 +2501,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
0, file.name.length() - REMOVE_MARKER_EXTENSION.length())).collect(
Collectors.toList());
+ final FileSystemConnector connector = new FileSystemConnector(addedFiles);
+
DataLoaderManager dataLoaderManager = mContext.getSystemService(DataLoaderManager.class);
if (dataLoaderManager == null) {
throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
@@ -2515,11 +2538,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
};
- final DataLoaderParams params = this.params.dataLoaderParams;
-
final FileSystemControlParcel control = new FileSystemControlParcel();
control.callback = connector;
+ final DataLoaderParams params = this.params.dataLoaderParams;
+
Bundle dataLoaderParams = new Bundle();
dataLoaderParams.putParcelable("componentName", params.getComponentName());
dataLoaderParams.putParcelable("control", control);
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 10e2780863d8..5adab378bb73 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -34,7 +34,6 @@ import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
-import android.content.pm.DataLoaderParams;
import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageInstaller;
@@ -137,10 +136,6 @@ class PackageManagerShellCommand extends ShellCommand {
private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
private static final int DEFAULT_WAIT_MS = 60 * 1000;
- private static final String DATA_LOADER_PACKAGE = "android";
- private static final String DATA_LOADER_CLASS =
- "com.android.server.pm.PackageManagerShellCommandDataLoader";
-
final IPackageManager mInterface;
final IPermissionManager mPermissionManager;
final private WeakHashMap<String, Resources> mResourceCache =
@@ -164,7 +159,7 @@ class PackageManagerShellCommand extends ShellCommand {
final PrintWriter pw = getOutPrintWriter();
try {
- switch(cmd) {
+ switch (cmd) {
case "path":
return runPath();
case "dump":
@@ -1163,9 +1158,8 @@ class PackageManagerShellCommand extends ShellCommand {
private int runStreamingInstall() throws RemoteException {
final InstallParams params = makeInstallParams();
if (params.sessionParams.dataLoaderParams == null) {
- final DataLoaderParams dataLoaderParams = DataLoaderParams.forStreaming(
- new ComponentName(DATA_LOADER_PACKAGE, DATA_LOADER_CLASS), "");
- params.sessionParams.setDataLoaderParams(dataLoaderParams);
+ params.sessionParams.setDataLoaderParams(
+ PackageManagerShellCommandDataLoader.getDataLoaderParams(this));
}
return doRunInstall(params);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
index 1ee9ab8927bb..a814cb8942e2 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
@@ -17,18 +17,22 @@
package com.android.server.pm;
import android.annotation.NonNull;
+import android.content.ComponentName;
import android.content.pm.DataLoaderParams;
import android.content.pm.InstallationFile;
import android.os.ParcelFileDescriptor;
+import android.os.ShellCommand;
import android.service.dataloader.DataLoaderService;
import android.text.TextUtils;
import android.util.Slog;
+import android.util.SparseArray;
import libcore.io.IoUtils;
-import java.io.File;
import java.io.IOException;
+import java.lang.ref.WeakReference;
import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
import java.util.Collection;
/**
@@ -37,41 +41,109 @@ import java.util.Collection;
public class PackageManagerShellCommandDataLoader extends DataLoaderService {
public static final String TAG = "PackageManagerShellCommandDataLoader";
+ private static final String PACKAGE = "android";
+ private static final String CLASS = PackageManagerShellCommandDataLoader.class.getName();
+
+ static final SecureRandom sRandom = new SecureRandom();
+ static final SparseArray<WeakReference<ShellCommand>> sShellCommands = new SparseArray<>();
+
+ private static final char ARGS_DELIM = '&';
+ private static final String SHELL_COMMAND_ID_PREFIX = "shellCommandId=";
+ private static final int INVALID_SHELL_COMMAND_ID = -1;
+ private static final int TOO_MANY_PENDING_SHELL_COMMANDS = 10;
+
+ private static final String STDIN_PATH = "-";
+
+ static DataLoaderParams getDataLoaderParams(ShellCommand shellCommand) {
+ int commandId;
+ synchronized (sShellCommands) {
+ // Clean up old references.
+ for (int i = sShellCommands.size() - 1; i >= 0; i--) {
+ WeakReference<ShellCommand> oldRef = sShellCommands.valueAt(i);
+ if (oldRef.get() == null) {
+ sShellCommands.removeAt(i);
+ }
+ }
+
+ // Sanity check.
+ if (sShellCommands.size() > TOO_MANY_PENDING_SHELL_COMMANDS) {
+ Slog.e(TAG, "Too many pending shell commands: " + sShellCommands.size());
+ }
+
+ // Generate new id and put ref to the array.
+ do {
+ commandId = sRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
+ } while (sShellCommands.contains(commandId));
+
+ sShellCommands.put(commandId, new WeakReference<>(shellCommand));
+ }
+
+ final String args = SHELL_COMMAND_ID_PREFIX + commandId;
+ return DataLoaderParams.forStreaming(new ComponentName(PACKAGE, CLASS), args);
+ }
+
+ private static int extractShellCommandId(String args) {
+ int sessionIdIdx = args.indexOf(SHELL_COMMAND_ID_PREFIX);
+ if (sessionIdIdx < 0) {
+ Slog.e(TAG, "Missing shell command id param.");
+ return INVALID_SHELL_COMMAND_ID;
+ }
+ sessionIdIdx += SHELL_COMMAND_ID_PREFIX.length();
+ int delimIdx = args.indexOf(ARGS_DELIM, sessionIdIdx);
+ try {
+ if (delimIdx < 0) {
+ return Integer.parseInt(args.substring(sessionIdIdx));
+ } else {
+ return Integer.parseInt(args.substring(sessionIdIdx, delimIdx));
+ }
+ } catch (NumberFormatException e) {
+ Slog.e(TAG, "Incorrect shell command id format.", e);
+ return INVALID_SHELL_COMMAND_ID;
+ }
+ }
+
static class DataLoader implements DataLoaderService.DataLoader {
- private ParcelFileDescriptor mInFd = null;
+ private DataLoaderParams mParams = null;
private FileSystemConnector mConnector = null;
- private static final String STDIN_PATH = "-";
-
@Override
public boolean onCreate(@NonNull DataLoaderParams dataLoaderParams,
@NonNull FileSystemConnector connector) {
+ mParams = dataLoaderParams;
mConnector = connector;
return true;
}
+
@Override
public boolean onPrepareImage(Collection<InstallationFile> addedFiles,
Collection<String> removedFiles) {
+ final int commandId = extractShellCommandId(mParams.getArguments());
+ if (commandId == INVALID_SHELL_COMMAND_ID) {
+ return false;
+ }
+
+ final WeakReference<ShellCommand> shellCommandRef;
+ synchronized (sShellCommands) {
+ shellCommandRef = sShellCommands.get(commandId, null);
+ }
+ final ShellCommand shellCommand =
+ shellCommandRef != null ? shellCommandRef.get() : null;
+ if (shellCommand == null) {
+ Slog.e(TAG, "Missing shell command.");
+ return false;
+ }
try {
for (InstallationFile fileInfo : addedFiles) {
String filePath = new String(fileInfo.getMetadata(), StandardCharsets.UTF_8);
if (STDIN_PATH.equals(filePath) || TextUtils.isEmpty(filePath)) {
- // TODO(b/146080380): add support for STDIN installations.
- if (mInFd == null) {
- Slog.e(TAG, "Invalid stdin file descriptor.");
- return false;
- }
- ParcelFileDescriptor inFd = ParcelFileDescriptor.dup(
- mInFd.getFileDescriptor());
+ final ParcelFileDescriptor inFd = ParcelFileDescriptor.dup(
+ shellCommand.getInFileDescriptor());
mConnector.writeData(fileInfo.getName(), 0, fileInfo.getSize(), inFd);
} else {
- File localFile = new File(filePath);
ParcelFileDescriptor incomingFd = null;
try {
- // TODO(b/146080380): open files via callback into shell command.
- incomingFd = ParcelFileDescriptor.open(localFile,
- ParcelFileDescriptor.MODE_READ_ONLY);
- mConnector.writeData(fileInfo.getName(), 0, localFile.length(),
+ incomingFd = shellCommand.openFileForSystem(filePath, "r");
+ mConnector.writeData(fileInfo.getName(), 0, incomingFd.getStatSize(),
incomingFd);
} finally {
IoUtils.closeQuietly(incomingFd);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 956962ef9f29..ea83adba4d8a 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5192,7 +5192,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final Intent dock = createHomeDockIntent();
if (dock != null) {
int result = ActivityTaskManager.getService()
- .startActivityAsUser(null, null, dock,
+ .startActivityAsUser(null, mContext.getBasePackageName(), dock,
dock.resolveTypeIfNeeded(mContext.getContentResolver()),
null, null, 0,
ActivityManager.START_FLAG_ONLY_IF_NEEDED,
@@ -5203,7 +5203,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
int result = ActivityTaskManager.getService()
- .startActivityAsUser(null, null, mHomeIntent,
+ .startActivityAsUser(null, mContext.getBasePackageName(), mHomeIntent,
mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
null, null, 0,
ActivityManager.START_FLAG_ONLY_IF_NEEDED,
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index e281712f743a..26d76a8d6e28 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -243,9 +243,9 @@ import android.app.servertransaction.NewIntentItem;
import android.app.servertransaction.PauseActivityItem;
import android.app.servertransaction.PipModeChangeItem;
import android.app.servertransaction.ResumeActivityItem;
+import android.app.servertransaction.StartActivityItem;
import android.app.servertransaction.StopActivityItem;
import android.app.servertransaction.TopResumedActivityChangeItem;
-import android.app.servertransaction.WindowVisibilityItem;
import android.app.usage.UsageEvents.Event;
import android.content.ComponentName;
import android.content.Intent;
@@ -4497,7 +4497,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
sleeping = false;
app.postPendingUiCleanMsg(true);
if (reportToClient) {
- makeClientVisible();
+ mClientVisibilityDeferred = false;
+ makeActiveIfNeeded(starting);
} else {
mClientVisibilityDeferred = true;
}
@@ -4511,23 +4512,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
handleAlreadyVisible();
}
- /** Send visibility change message to the client and pause if needed. */
- void makeClientVisible() {
- mClientVisibilityDeferred = false;
- try {
- mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
- WindowVisibilityItem.obtain(true /* showWindow */));
- makeActiveIfNeeded(null /* activeActivity*/);
- if (isState(STOPPING, STOPPED)) {
- // Set state to STARTED in order to have consistent state with client while
- // making an non-active activity visible from stopped.
- setState(STARTED, "makeClientVisible");
- }
- } catch (Exception e) {
- Slog.w(TAG, "Exception thrown sending visibility update: " + intent.getComponent(), e);
- }
- }
-
void makeInvisible() {
if (!mVisibleRequested) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + this);
@@ -4556,14 +4540,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
switch (getState()) {
case STOPPING:
case STOPPED:
- if (attachedToProcess()) {
- if (DEBUG_VISIBILITY) {
- Slog.v(TAG_VISIBILITY, "Scheduling invisibility: " + this);
- }
- mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(),
- appToken, WindowVisibilityItem.obtain(false /* showWindow */));
- }
-
// Reset the flag indicating that an app can enter picture-in-picture once the
// activity is hidden
supportsEnterPipOnTaskSwitch = false;
@@ -4595,17 +4571,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean makeActiveIfNeeded(ActivityRecord activeActivity) {
if (shouldResumeActivity(activeActivity)) {
if (DEBUG_VISIBILITY) {
- Slog.v("TAG_VISIBILITY", "Resume visible activity, " + this);
+ Slog.v(TAG_VISIBILITY, "Resume visible activity, " + this);
}
return getActivityStack().resumeTopActivityUncheckedLocked(activeActivity /* prev */,
null /* options */);
} else if (shouldPauseActivity(activeActivity)) {
if (DEBUG_VISIBILITY) {
- Slog.v("TAG_VISIBILITY", "Pause visible activity, " + this);
+ Slog.v(TAG_VISIBILITY, "Pause visible activity, " + this);
}
// An activity must be in the {@link PAUSING} state for the system to validate
// the move to {@link PAUSED}.
- setState(PAUSING, "makeVisibleIfNeeded");
+ setState(PAUSING, "makeActiveIfNeeded");
try {
mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
PauseActivityItem.obtain(finishing, false /* userLeaving */,
@@ -4613,6 +4589,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
} catch (Exception e) {
Slog.w(TAG, "Exception thrown sending pause: " + intent.getComponent(), e);
}
+ } else if (shouldStartActivity()) {
+ if (DEBUG_VISIBILITY) {
+ Slog.v(TAG_VISIBILITY, "Start visible activity, " + this);
+ }
+ setState(STARTED, "makeActiveIfNeeded");
+ try {
+ mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
+ StartActivityItem.obtain());
+ } catch (Exception e) {
+ Slog.w(TAG, "Exception thrown sending start: " + intent.getComponent(), e);
+ }
}
return false;
}
@@ -4656,6 +4643,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
/**
+ * Check if activity should be moved to STARTED state.
+ * NOTE: This will not check if activity should be made paused or resumed first, so it must only
+ * be called after checking with {@link #shouldResumeActivity(ActivityRecord)}
+ * and {@link #shouldPauseActivity(ActivityRecord)}.
+ */
+ private boolean shouldStartActivity() {
+ return mVisibleRequested && isState(STOPPED);
+ }
+
+ /**
* Check if activity is eligible to be made active (resumed of paused). The activity:
* - should be paused, stopped or stopping
* - should not be the currently active one or launching behind other tasks
@@ -4890,16 +4887,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
setState(STOPPING, "stopIfPossible");
if (DEBUG_VISIBILITY) {
- Slog.v(TAG_VISIBILITY, "Stopping visibleRequested="
- + mVisibleRequested + " for " + this);
- }
- if (!mVisibleRequested) {
- setVisibility(false);
+ Slog.v(TAG_VISIBILITY, "Stopping:" + this);
}
EventLogTags.writeWmStopActivity(
mUserId, System.identityHashCode(this), shortComponentName);
mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
- StopActivityItem.obtain(mVisibleRequested, configChangeFlags));
+ StopActivityItem.obtain(configChangeFlags));
+
if (stack.shouldSleepOrShutDownActivities()) {
setSleeping(true);
}
@@ -7201,7 +7195,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// {@link ActivityTaskManagerService.activityStopped}).
try {
mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
- StopActivityItem.obtain(false /* showWindow */, 0 /* configChanges */));
+ StopActivityItem.obtain(0 /* configChanges */));
} catch (RemoteException e) {
Slog.w(TAG, "Exception thrown during restart " + this, e);
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 76c0e4eeecae..474c5c960eb0 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -7203,7 +7203,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
ActivityManagerServiceDumpProcessesProto.VR_CONTROLLER);
if (mController != null) {
final long token = proto.start(CONTROLLER);
- proto.write(CONTROLLER, mController.toString());
+ proto.write(ActivityManagerServiceDumpProcessesProto.Controller.CONTROLLER,
+ mController.toString());
proto.write(IS_A_MONKEY, mControllerIsAMonkey);
proto.end(token);
}
diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
index 55f5e289377e..c09834f2b3c1 100644
--- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
+++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
@@ -79,12 +79,13 @@ class EnsureActivitiesVisibleHelper {
final PooledConsumer f = PooledLambda.obtainConsumer(
EnsureActivitiesVisibleHelper::setActivityVisibilityState, this,
- PooledLambda.__(ActivityRecord.class), resumeTopActivity);
+ PooledLambda.__(ActivityRecord.class), starting, resumeTopActivity);
mContiner.forAllActivities(f);
f.recycle();
}
- private void setActivityVisibilityState(ActivityRecord r, final boolean resumeTopActivity) {
+ private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting,
+ final boolean resumeTopActivity) {
final boolean isTop = r == mTop;
if (mAboveTop && !isTop) {
return;
@@ -129,7 +130,8 @@ class EnsureActivitiesVisibleHelper {
"Skipping: already visible at " + r);
if (r.mClientVisibilityDeferred && mNotifyClients) {
- r.makeClientVisible();
+ r.makeActiveIfNeeded(r.mClientVisibilityDeferred ? null : starting);
+ r.mClientVisibilityDeferred = false;
}
r.handleAlreadyVisible();
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 7b40f609aaf1..a13383d3991e 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -70,6 +70,9 @@ class InsetsSourceProvider {
*/
private boolean mServerVisible;
+ private boolean mSeamlessRotating;
+ private long mFinishSeamlessRotateFrameNumber = -1;
+
private final boolean mControllable;
InsetsSourceProvider(InsetsSource source, InsetsStateController stateController,
@@ -170,7 +173,9 @@ class InsetsSourceProvider {
updateSourceFrame();
if (mControl != null) {
final Rect frame = mWin.getWindowFrames().mFrame;
- if (mControl.setSurfacePosition(frame.left, frame.top)) {
+ if (mControl.setSurfacePosition(frame.left, frame.top) && mControlTarget != null) {
+ // The leash has been stale, we need to create a new one for the client.
+ updateControlForTarget(mControlTarget, true /* force */);
mStateController.notifyControlChanged(mControlTarget);
}
}
@@ -189,6 +194,11 @@ class InsetsSourceProvider {
}
void updateControlForTarget(@Nullable InsetsControlTarget target, boolean force) {
+ if (mSeamlessRotating) {
+ // We are un-rotating the window against the display rotation. We don't want the target
+ // to control the window for now.
+ return;
+ }
if (mWin == null) {
mControlTarget = target;
return;
@@ -203,13 +213,41 @@ class InsetsSourceProvider {
}
mAdapter = new ControlAdapter();
setClientVisible(InsetsState.getDefaultVisibility(mSource.getType()));
- mWin.startAnimation(mDisplayContent.getPendingTransaction(), mAdapter,
- !mClientVisible /* hidden */);
+ final Transaction t = mDisplayContent.getPendingTransaction();
+ mWin.startAnimation(t, mAdapter, !mClientVisible /* hidden */);
+ final SurfaceControl leash = mAdapter.mCapturedLeash;
+ final long frameNumber = mFinishSeamlessRotateFrameNumber;
+ mFinishSeamlessRotateFrameNumber = -1;
+ if (frameNumber >= 0 && mWin.mHasSurface && leash != null) {
+ // We just finished the seamless rotation. We don't want to change the position or the
+ // window crop of the surface controls (including the leash) until the client finishes
+ // drawing the new frame of the new orientation. Although we cannot defer the reparent
+ // operation, it is fine, because reparent won't cause any visual effect.
+ final SurfaceControl barrier = mWin.mWinAnimator.mSurfaceController.mSurfaceControl;
+ t.deferTransactionUntil(mWin.getSurfaceControl(), barrier, frameNumber);
+ t.deferTransactionUntil(leash, barrier, frameNumber);
+ }
mControlTarget = target;
- mControl = new InsetsSourceControl(mSource.getType(), mAdapter.mCapturedLeash,
+ mControl = new InsetsSourceControl(mSource.getType(), leash,
new Point(mWin.getWindowFrames().mFrame.left, mWin.getWindowFrames().mFrame.top));
}
+ void startSeamlessRotation() {
+ if (!mSeamlessRotating) {
+ mSeamlessRotating = true;
+
+ // This will revoke the leash and clear the control target.
+ mWin.cancelAnimation();
+ }
+ }
+
+ void finishSeamlessRotation(boolean timeout) {
+ if (mSeamlessRotating) {
+ mSeamlessRotating = false;
+ mFinishSeamlessRotateFrameNumber = timeout ? -1 : mWin.getFrameNumber();
+ }
+ }
+
boolean onInsetsModified(InsetsControlTarget caller, InsetsSource modifiedSource) {
if (mControlTarget != caller || modifiedSource.isVisible() == mClientVisible) {
return false;
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 720493f4a466..b2234d17984e 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -203,7 +203,7 @@ class InsetsStateController {
if (target == previous) {
return;
}
- final InsetsSourceProvider provider = getSourceProvider(type);
+ final InsetsSourceProvider provider = mProviders.get(type);
if (provider == null) {
return;
}
@@ -211,6 +211,7 @@ class InsetsStateController {
return;
}
provider.updateControlForTarget(target, false /* force */);
+ target = provider.getControlTarget();
if (previous != null) {
removeFromControlMaps(previous, type, false /* fake */);
mPendingControlChanged.add(previous);
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 976730ec4337..5286a6e32958 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -322,12 +322,16 @@ class SurfaceAnimator {
if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to leash");
final SurfaceControl.Builder builder = mAnimatable.makeAnimationLeash()
.setParent(mAnimatable.getAnimationLeashParent())
+ .setHidden(hidden)
.setName(surface + " - animation-leash");
final SurfaceControl leash = builder.build();
t.setWindowCrop(leash, width, height);
+
+ // TODO: rely on builder.setHidden(hidden) instead of show and setAlpha when b/138459974 is
+ // fixed.
t.show(leash);
- // TODO: change this back to use show instead of alpha when b/138459974 is fixed.
t.setAlpha(leash, hidden ? 0 : 1);
+
t.reparent(surface, leash);
return leash;
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 96bc8e963b38..ba40f623ea66 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -688,6 +688,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
if (mForceSeamlesslyRotate || requested) {
+ if (mControllableInsetProvider != null) {
+ mControllableInsetProvider.startSeamlessRotation();
+ }
mPendingSeamlessRotate = new SeamlessRotator(oldRotation, rotation, getDisplayInfo());
mPendingSeamlessRotate.unrotate(transaction, this);
getDisplayContent().getDisplayRotation().markForSeamlessRotation(this,
@@ -702,6 +705,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mPendingSeamlessRotate = null;
getDisplayContent().getDisplayRotation().markForSeamlessRotation(this,
false /* seamlesslyRotated */);
+ if (mControllableInsetProvider != null) {
+ mControllableInsetProvider.finishSeamlessRotation(timeout);
+ }
}
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 2e8e5e7b706a..c0891d739788 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -1757,6 +1757,12 @@ static jboolean nativeCanDispatchToDisplay(JNIEnv* env, jclass /* clazz */, jlon
return im->getInputManager()->getReader()->canDispatchToDisplay(deviceId, displayId);
}
+static void nativeNotifyPortAssociationsChanged(JNIEnv* env, jclass /* clazz */, jlong ptr) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+ im->getInputManager()->getReader()->requestRefreshConfiguration(
+ InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod gInputManagerMethods[] = {
@@ -1842,6 +1848,8 @@ static const JNINativeMethod gInputManagerMethods[] = {
(void*) nativeSetCustomPointerIcon },
{ "nativeCanDispatchToDisplay", "(JII)Z",
(void*) nativeCanDispatchToDisplay },
+ { "nativeNotifyPortAssociationsChanged", "(J)V",
+ (void*) nativeNotifyPortAssociationsChanged },
};
#define FIND_CLASS(var, className) \
diff --git a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
index d4182f3d31e2..5a1ad8655ab0 100644
--- a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
@@ -672,6 +672,30 @@ public final class AdbDebuggingManagerTest {
connectionTime2, mKeyStore.getLastConnectionTime(TEST_KEY_2));
}
+ @Test
+ public void testClearAuthorizationsBeforeAdbEnabled() throws Exception {
+ // The adb key store is not instantiated until adb is enabled; however if the user attempts
+ // to clear the adb authorizations when adb is disabled after a boot a NullPointerException
+ // was thrown as deleteKeyStore is invoked against the key store. This test ensures the
+ // key store can be successfully cleared when adb is disabled.
+ mHandler = mManager.new AdbDebuggingHandler(FgThread.get().getLooper());
+
+ clearKeyStore();
+ }
+
+ @Test
+ public void testClearAuthorizationsDeletesKeyFiles() throws Exception {
+ mAdbKeyFile.createNewFile();
+ mAdbKeyXmlFile.createNewFile();
+
+ clearKeyStore();
+
+ assertFalse("The adb key file should have been deleted after revocation of the grants",
+ mAdbKeyFile.exists());
+ assertFalse("The adb xml key file should have been deleted after revocation of the grants",
+ mAdbKeyXmlFile.exists());
+ }
+
/**
* Runs an adb test with the provided configuration.
*
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index ebca240819e8..25d077823a3f 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -78,7 +78,7 @@ public class DisplayModeDirectorTest {
int displayId = 0;
// With no votes present, DisplayModeDirector should allow any refresh rate.
- assertEquals(new DisplayModeDirector.DesiredDisplayModeSpecs(/*defaultModeId=*/60,
+ assertEquals(new DisplayModeDirector.DesiredDisplayModeSpecs(/*baseModeId=*/60,
new DisplayModeDirector.RefreshRateRange(0f, Float.POSITIVE_INFINITY)),
createDisplayModeDirectorWithDisplayFpsRange(60, 90).getDesiredDisplayModeSpecs(
displayId));
@@ -105,7 +105,7 @@ public class DisplayModeDirectorTest {
director.injectVotesByDisplay(votesByDisplay);
assertEquals(
new DisplayModeDirector.DesiredDisplayModeSpecs(
- /*defaultModeId=*/minFps + i,
+ /*baseModeId=*/minFps + i,
new DisplayModeDirector.RefreshRateRange(minFps + i, maxFps - i)),
director.getDesiredDisplayModeSpecs(displayId));
}
@@ -126,7 +126,7 @@ public class DisplayModeDirectorTest {
votes.put(DisplayModeDirector.Vote.MIN_PRIORITY,
DisplayModeDirector.Vote.forRefreshRates(70, 80));
director.injectVotesByDisplay(votesByDisplay);
- assertEquals(new DisplayModeDirector.DesiredDisplayModeSpecs(/*defaultModeId=*/70,
+ assertEquals(new DisplayModeDirector.DesiredDisplayModeSpecs(/*baseModeId=*/70,
new DisplayModeDirector.RefreshRateRange(70, 80)),
director.getDesiredDisplayModeSpecs(displayId));
}
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 28e6830515f0..c7dbad83e384 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -1273,11 +1273,11 @@ public class NetworkPolicyManagerServiceTest {
history.recordData(start, end,
new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1440), 0L, 0L, 0L, 0));
stats.clear();
- stats.addValues(IFACE_ALL, UID_A, SET_ALL, TAG_ALL,
+ stats.addEntry(IFACE_ALL, UID_A, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
- stats.addValues(IFACE_ALL, UID_B, SET_ALL, TAG_ALL,
+ stats.addEntry(IFACE_ALL, UID_B, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
- stats.addValues(IFACE_ALL, UID_C, SET_ALL, TAG_ALL,
+ stats.addEntry(IFACE_ALL, UID_C, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
reset(mNotifManager);
@@ -1301,9 +1301,9 @@ public class NetworkPolicyManagerServiceTest {
history.recordData(start, end,
new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1440), 0L, 0L, 0L, 0));
stats.clear();
- stats.addValues(IFACE_ALL, UID_A, SET_ALL, TAG_ALL,
+ stats.addEntry(IFACE_ALL, UID_A, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(960), 0, 0, 0, 0);
- stats.addValues(IFACE_ALL, UID_B, SET_ALL, TAG_ALL,
+ stats.addEntry(IFACE_ALL, UID_B, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
reset(mNotifManager);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 73b2f6b2dc37..a3e94599cad3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -521,11 +521,12 @@ public class ActivityRecordTests extends ActivityTestsBase {
}
@Test
- public void testShouldPauseWhenMakeClientVisible() {
+ public void testShouldStartWhenMakeClientActive() {
ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
topActivity.setOccludesParent(false);
mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
- mActivity.makeClientVisible();
+ mActivity.setVisibility(true);
+ mActivity.makeActiveIfNeeded(null /* activeActivity */);
assertEquals(STARTED, mActivity.getState());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
index 574517a00f6f..71390dbbe4a3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
@@ -40,7 +40,7 @@ import org.mockito.MockitoAnnotations;
* Tests for the {@link ActivityStack} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:AnimatingActivityRegistryTest
+ * atest WmTests:AnimatingActivityRegistryTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 1311889d5605..f6213bd94ddd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -42,7 +42,7 @@ import org.junit.runner.RunWith;
/**
* Build/Install/Run:
- * atest FrameworksServicesTests:AppTransitionControllerTest
+ * atest WmTests:AppTransitionControllerTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
index 0ad0f95f64c1..1dda535cfb95 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
@@ -60,7 +60,7 @@ import org.junit.runner.RunWith;
* appropriately.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:BoundsAnimationControllerTests
+ * atest WmTests:BoundsAnimationControllerTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
index 0aa6961d20b3..e8f7849ef96a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
@@ -40,7 +40,7 @@ import org.junit.runner.RunWith;
/**
* Build/Install/Run:
- * atest FrameworksServicesTests:DimmerTests
+ * atest WmTests:DimmerTests
*/
@Presubmit
@RunWith(WindowTestRunner.class)
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 112479b3b9a0..1a575962b961 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -61,7 +61,7 @@ import org.mockito.MockitoAnnotations;
/**
* Build/Install/Run:
- * atest FrameworksServicesTests:RemoteAnimationControllerTest
+ * atest WmTests:RemoteAnimationControllerTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
index e0112809b22b..bac2bcae30de 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -60,7 +60,7 @@ import java.util.concurrent.CountDownLatch;
* Test class for {@link SurfaceAnimationRunner}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:SurfaceAnimationRunnerTest
+ * atest WmTests:SurfaceAnimationRunnerTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index 0274b7d788ff..e71247173930 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
@@ -38,7 +38,7 @@ import org.mockito.MockitoAnnotations;
* Test class for {@link TaskSnapshotCache}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:TaskSnapshotCacheTest
+ * atest WmTests:TaskSnapshotCacheTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 8fe0cdbbd872..2e485dd1bec3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -53,7 +53,7 @@ import org.mockito.Mockito;
* Test class for {@link TaskSnapshotController}.
*
* Build/Install/Run:
- * * atest FrameworksServicesTests:TaskSnapshotControllerTest
+ * * atest WmTests:TaskSnapshotControllerTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index b5a5790a3a8c..eb8eb98fd484 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -47,7 +47,7 @@ import java.util.function.Predicate;
* Test class for {@link TaskSnapshotPersister} and {@link TaskSnapshotLoader}
*
* Build/Install/Run:
- * atest FrameworksServicesTests:TaskSnapshotPersisterLoaderTest
+ * atest WmTests:TaskSnapshotPersisterLoaderTest
*/
@MediumTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index 2d418ffffcf6..ed87f3a0c604 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -53,7 +53,7 @@ import org.junit.runner.RunWith;
* Test class for {@link TaskSnapshotSurface}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:TaskSnapshotSurfaceTest
+ * atest WmTests:TaskSnapshotSurfaceTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
index 8936aadd5f92..3c0dd1e897f5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
@@ -39,7 +39,7 @@ import java.util.function.Consumer;
* Tests for {@link WindowContainer#forAllWindows} and various implementations.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:WindowContainerTraversalTests
+ * atest WmTests:WindowContainerTraversalTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index e081ca374808..7e248f854dcf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -92,7 +92,7 @@ import java.util.List;
* Tests for the {@link WindowState} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:WindowStateTests
+ * atest WmTests:WindowStateTests
*/
@SmallTest
@Presubmit
diff --git a/telecomm/java/android/telecom/AudioState.java b/telecomm/java/android/telecom/AudioState.java
index 8b8c86be7b0a..ea641f866b98 100644
--- a/telecomm/java/android/telecom/AudioState.java
+++ b/telecomm/java/android/telecom/AudioState.java
@@ -19,7 +19,7 @@ package android.telecom;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 86ad795b9ea2..a8852a849604 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -20,12 +20,11 @@ import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
-import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import com.android.internal.telecom.IVideoProvider;
diff --git a/telecomm/java/android/telecom/CallerInfo.java b/telecomm/java/android/telecom/CallerInfo.java
index a5d25e2ce4bb..fb6f99405759 100644
--- a/telecomm/java/android/telecom/CallerInfo.java
+++ b/telecomm/java/android/telecom/CallerInfo.java
@@ -17,7 +17,7 @@
package android.telecom;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -41,8 +41,8 @@ import com.android.i18n.phonenumbers.NumberParseException;
import com.android.i18n.phonenumbers.PhoneNumberUtil;
import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber;
import com.android.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
-
import com.android.internal.annotations.VisibleForTesting;
+
import java.util.Locale;
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 8808339b1664..f205ec64f49b 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -21,9 +21,9 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Notification;
import android.bluetooth.BluetoothDevice;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.hardware.camera2.CameraManager;
import android.net.Uri;
diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java
index 7d4ee7686512..4f6a9d6450f8 100644
--- a/telecomm/java/android/telecom/Log.java
+++ b/telecomm/java/android/telecom/Log.java
@@ -16,7 +16,7 @@
package android.telecom;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index a234bb0af8fa..be4e2f4c65e1 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -16,22 +16,21 @@
package android.telecom;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.telecom.Call.Details.CallDirection;
+import com.android.internal.telecom.IVideoProvider;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import com.android.internal.telecom.IVideoProvider;
-
/**
* Information about a call that is used between InCallService and Telecom.
* @hide
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 61a639a1a235..a427ed612b31 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -17,8 +17,8 @@
package android.telecom;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothDevice;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.util.ArrayMap;
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index eb568e04ebf3..e1bcb5fbdf00 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -18,7 +18,7 @@ package android.telecom;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.os.Build;
import android.os.Parcel;
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index af3c55abf00c..9cf4803966c6 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -26,7 +26,7 @@ import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java
index 4a1aa0a8ffa4..109e7f829f2e 100644
--- a/telecomm/java/android/telecom/VideoCallImpl.java
+++ b/telecomm/java/android/telecom/VideoCallImpl.java
@@ -16,7 +16,7 @@
package android.telecom;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index 64e6ca3416e3..4197f3cfc6c3 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -19,7 +19,6 @@ package android.telecom;
import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.IntRange;
-import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/common/com/android/internal/telephony/GsmAlphabet.java b/telephony/common/com/android/internal/telephony/GsmAlphabet.java
index 5fb4e90b9666..22cbdaa0f133 100644
--- a/telephony/common/com/android/internal/telephony/GsmAlphabet.java
+++ b/telephony/common/com/android/internal/telephony/GsmAlphabet.java
@@ -16,7 +16,7 @@
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.os.Build;
import android.telephony.Rlog;
diff --git a/telephony/common/com/android/internal/telephony/SmsConstants.java b/telephony/common/com/android/internal/telephony/SmsConstants.java
index 19f52b0ef429..3aa8bbf607d1 100644
--- a/telephony/common/com/android/internal/telephony/SmsConstants.java
+++ b/telephony/common/com/android/internal/telephony/SmsConstants.java
@@ -15,7 +15,7 @@
*/
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* SMS Constants and must be the same as the corresponding
diff --git a/telephony/java/android/service/euicc/EuiccProfileInfo.java b/telephony/java/android/service/euicc/EuiccProfileInfo.java
index 6c357ccdd03d..8450a9018634 100644
--- a/telephony/java/android/service/euicc/EuiccProfileInfo.java
+++ b/telephony/java/android/service/euicc/EuiccProfileInfo.java
@@ -19,7 +19,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.service.carrier.CarrierIdentifier;
diff --git a/telephony/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java b/telephony/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java
index c7a985160730..2382f657c9ee 100644
--- a/telephony/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java
+++ b/telephony/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java
@@ -17,7 +17,7 @@ package android.service.euicc;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.euicc.DownloadableSubscription;
diff --git a/telephony/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java b/telephony/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
index abd4065c754a..d0fb51180c1d 100644
--- a/telephony/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
+++ b/telephony/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
@@ -17,7 +17,7 @@ package android.service.euicc;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.euicc.DownloadableSubscription;
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 5baddef99efa..4d5713259a0f 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -24,7 +24,7 @@ import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.os.PersistableBundle;
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 2ecdfce92825..49f425acead6 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -18,7 +18,7 @@ package android.telephony;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 15c91752badf..bc4655069dba 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -18,7 +18,7 @@ package android.telephony;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.telephony.gsm.GsmCellLocation;
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 5b12aed3e51b..66feb7bac25d 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -2044,4 +2044,27 @@ public class ServiceState implements Parcelable {
public boolean isIwlanPreferred() {
return mIsIwlanPreferred;
}
+ /**
+ * @return {@code true}Returns True whenever the modem is searching for service.
+ * To check both CS and PS domain
+ */
+
+ public boolean isSearching() {
+ NetworkRegistrationInfo psRegState = getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+
+ if (psRegState != null && psRegState.getRegistrationState()
+ == NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING) {
+ return true;
+ }
+
+ NetworkRegistrationInfo csRegState = getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+
+ if (csRegState != null && csRegState.getRegistrationState()
+ == NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING) {
+ return true;
+ }
+ return false;
+ }
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 88501a726ee1..321753bc1776 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -983,6 +983,23 @@ public class SubscriptionManager {
*/
public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
if (listener == null) return;
+ addOnSubscriptionsChangedListener(listener.mExecutor, listener);
+ }
+
+ /**
+ * Register for changes to the list of active {@link SubscriptionInfo} records or to the
+ * individual records themselves. When a change occurs the onSubscriptionsChanged method of
+ * the listener will be invoked immediately if there has been a notification. The
+ * onSubscriptionChanged method will also be triggered once initially when calling this
+ * function.
+ *
+ * @param listener an instance of {@link OnSubscriptionsChangedListener} with
+ * onSubscriptionsChanged overridden.
+ * @param executor the executor that will execute callbacks.
+ */
+ public void addOnSubscriptionsChangedListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnSubscriptionsChangedListener listener) {
String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
if (DBG) {
logd("register OnSubscriptionsChangedListener pkgName=" + pkgName
@@ -994,7 +1011,7 @@ public class SubscriptionManager {
mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
if (telephonyRegistryManager != null) {
telephonyRegistryManager.addOnSubscriptionsChangedListener(listener,
- listener.mExecutor);
+ executor);
}
}
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index c16a0f446651..33d77d288e15 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -64,15 +64,15 @@ public class NetworkStatsTest {
@Test
public void testFindIndex() throws Exception {
final NetworkStats stats = new NetworkStats(TEST_START, 5)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1024L, 8L, 0L, 0L, 10)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 0L, 0L, 1024L, 8L, 11)
- .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1024L, 8L, 1024L, 8L, 12)
- .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+ .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12);
assertEquals(4, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES,
@@ -94,21 +94,21 @@ public class NetworkStatsTest {
@Test
public void testFindIndexHinted() {
final NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1024L, 8L, 0L, 0L, 10)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11)
- .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12)
- .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1024L, 8L, 0L, 0L, 10)
- .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 0L, 0L, 1024L, 8L, 11)
- .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11)
- .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12)
- .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+ .addEntry(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_NO, 1024L, 8L, 1024L, 8L, 12);
// verify that we correctly find across regardless of hinting
@@ -143,27 +143,27 @@ public class NetworkStatsTest {
assertEquals(0, stats.size());
assertEquals(4, stats.internalSize());
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1L, 1L, 2L, 2L, 3);
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 2L, 2L, 2L, 2L, 4);
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 3L, 3L, 2L, 2L, 5);
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_NO, 3L, 3L, 2L, 2L, 5);
assertEquals(4, stats.size());
assertEquals(4, stats.internalSize());
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 4L, 40L, 4L, 40L, 7);
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 5L, 50L, 4L, 40L, 8);
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 6L, 60L, 5L, 50L, 10);
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 7L, 70L, 5L, 50L, 11);
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_NO, 7L, 70L, 5L, 50L, 11);
assertEquals(9, stats.size());
@@ -193,8 +193,8 @@ public class NetworkStatsTest {
public void testCombineExisting() throws Exception {
final NetworkStats stats = new NetworkStats(TEST_START, 10);
- stats.addValues(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 10);
- stats.addValues(TEST_IFACE, 1001, SET_DEFAULT, 0xff, 128L, 1L, 128L, 1L, 2);
+ stats.addEntry(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 10);
+ stats.addEntry(TEST_IFACE, 1001, SET_DEFAULT, 0xff, 128L, 1L, 128L, 1L, 2);
stats.combineValues(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, -128L, -1L,
-128L, -1L, -1);
@@ -215,12 +215,12 @@ public class NetworkStatsTest {
@Test
public void testSubtractIdenticalData() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
final NetworkStats after = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
final NetworkStats result = after.subtract(before);
@@ -234,12 +234,12 @@ public class NetworkStatsTest {
@Test
public void testSubtractIdenticalRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
final NetworkStats after = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1025L, 9L, 2L, 1L, 15)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 3L, 1L, 1028L, 9L, 20);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1025L, 9L, 2L, 1L, 15)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 3L, 1L, 1028L, 9L, 20);
final NetworkStats result = after.subtract(before);
@@ -253,13 +253,13 @@ public class NetworkStatsTest {
@Test
public void testSubtractNewRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
final NetworkStats after = new NetworkStats(TEST_START, 3)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12)
- .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 20);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12)
+ .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 20);
final NetworkStats result = after.subtract(before);
@@ -275,11 +275,11 @@ public class NetworkStatsTest {
@Test
public void testSubtractMissingRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 0L, 0L, 0L, 0)
- .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2048L, 0L, 0L, 0L, 0);
+ .addEntry(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 0L, 0L, 0L, 0)
+ .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2048L, 0L, 0L, 0L, 0);
final NetworkStats after = new NetworkStats(TEST_START, 1)
- .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2049L, 2L, 3L, 4L, 0);
+ .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2049L, 2L, 3L, 4L, 0);
final NetworkStats result = after.subtract(before);
@@ -293,40 +293,40 @@ public class NetworkStatsTest {
@Test
public void testTotalBytes() throws Exception {
final NetworkStats iface = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 128L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 256L, 0L, 0L, 0L, 0L);
+ .addEntry(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 128L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 256L, 0L, 0L, 0L, 0L);
assertEquals(384L, iface.getTotalBytes());
final NetworkStats uidSet = new NetworkStats(TEST_START, 3)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE, 101, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
assertEquals(96L, uidSet.getTotalBytes());
final NetworkStats uidTag = new NetworkStats(TEST_START, 6)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L);
assertEquals(64L, uidTag.getTotalBytes());
final NetworkStats uidMetered = new NetworkStats(TEST_START, 3)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
assertEquals(96L, uidMetered.getTotalBytes());
final NetworkStats uidRoaming = new NetworkStats(TEST_START, 3)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
assertEquals(96L, uidRoaming.getTotalBytes());
}
@@ -343,11 +343,11 @@ public class NetworkStatsTest {
@Test
public void testGroupedByIfaceAll() throws Exception {
final NetworkStats uidStats = new NetworkStats(TEST_START, 3)
- .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L)
- .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 128L, 8L, 0L, 2L, 20L)
- .addValues(IFACE_ALL, 101, SET_ALL, TAG_NONE, METERED_NO, ROAMING_YES,
+ .addEntry(IFACE_ALL, 101, SET_ALL, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L);
final NetworkStats grouped = uidStats.groupedByIface();
@@ -361,19 +361,19 @@ public class NetworkStatsTest {
@Test
public void testGroupedByIface() throws Exception {
final NetworkStats uidStats = new NetworkStats(TEST_START, 7)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 64L, 4L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L);
final NetworkStats grouped = uidStats.groupedByIface();
@@ -390,19 +390,19 @@ public class NetworkStatsTest {
@Test
public void testAddAllValues() {
final NetworkStats first = new NetworkStats(TEST_START, 5)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
+ .addEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
final NetworkStats second = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
+ .addEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
first.combineAllValues(second);
@@ -421,19 +421,19 @@ public class NetworkStatsTest {
@Test
public void testGetTotal() {
final NetworkStats stats = new NetworkStats(TEST_START, 7)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 64L, 4L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 512L,32L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L);
assertValues(stats.getTotal(null), 1408L, 88L, 0L, 2L, 20L);
@@ -459,7 +459,7 @@ public class NetworkStatsTest {
assertEquals(0, after.size());
// Test 1 item stats.
- before.addValues(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, 1L, 128L, 0L, 2L, 20L);
+ before.addEntry(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, 1L, 128L, 0L, 2L, 20L);
after = before.clone();
after.removeUids(new int[0]);
assertEquals(1, after.size());
@@ -469,12 +469,12 @@ public class NetworkStatsTest {
assertEquals(0, after.size());
// Append remaining test items.
- before.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 2L, 64L, 0L, 2L, 20L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 4L, 32L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 16L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 8L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 4L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 64L, 2L, 0L, 0L, 0L);
+ before.addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 2L, 64L, 0L, 2L, 20L)
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 4L, 32L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 16L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 8L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 4L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 64L, 2L, 0L, 0L, 0L);
assertEquals(7, before.size());
// Test remove with empty uid list.
@@ -505,12 +505,12 @@ public class NetworkStatsTest {
@Test
public void testClone() throws Exception {
final NetworkStats original = new NetworkStats(TEST_START, 5)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L);
// make clone and mutate original
final NetworkStats clone = original.clone();
- original.addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L);
+ original.addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L);
assertEquals(3, original.size());
assertEquals(2, clone.size());
@@ -523,8 +523,8 @@ public class NetworkStatsTest {
public void testAddWhenEmpty() throws Exception {
final NetworkStats red = new NetworkStats(TEST_START, -1);
final NetworkStats blue = new NetworkStats(TEST_START, 5)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L);
// We're mostly checking that we don't crash
red.combineAllValues(blue);
@@ -537,39 +537,39 @@ public class NetworkStatsTest {
final String underlyingIface = "wlan0";
final int testTag1 = 8888;
NetworkStats delta = new NetworkStats(TEST_START, 17)
- .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 39605L, 46L, 12259L, 55L, 0L)
- .addValues(tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
- .addValues(tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 72667L, 197L, 43909L, 241L, 0L)
- .addValues(tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 9297L, 17L, 4128L, 21L, 0L)
- // VPN package also uses some traffic through unprotected network.
- .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 4983L, 10L, 1801L, 12L, 0L)
- .addValues(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
- // Tag entries
- .addValues(tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 21691L, 41L, 13820L, 51L, 0L)
- .addValues(tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 1281L, 2L, 665L, 2L, 0L)
- // Irrelevant entries
- .addValues(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 1685L, 5L, 2070L, 6L, 0L)
- // Underlying Iface entries
- .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 5178L, 8L, 2139L, 11L, 0L)
- .addValues(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
- .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 149873L, 287L, 59217L /* smaller than sum(tun0) */,
- 299L /* smaller than sum(tun0) */, 0L)
- .addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
-
- delta.migrateTun(tunUid, tunIface, new String[] {underlyingIface});
+ .addEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 39605L, 46L, 12259L, 55L, 0L)
+ .addEntry(tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
+ .addEntry(tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 72667L, 197L, 43909L, 241L, 0L)
+ .addEntry(tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 9297L, 17L, 4128L, 21L, 0L)
+ // VPN package also uses some traffic through unprotected network.
+ .addEntry(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 4983L, 10L, 1801L, 12L, 0L)
+ .addEntry(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
+ // Tag entries
+ .addEntry(tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 21691L, 41L, 13820L, 51L, 0L)
+ .addEntry(tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 1281L, 2L, 665L, 2L, 0L)
+ // Irrelevant entries
+ .addEntry(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 1685L, 5L, 2070L, 6L, 0L)
+ // Underlying Iface entries
+ .addEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 5178L, 8L, 2139L, 11L, 0L)
+ .addEntry(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
+ .addEntry(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 149873L, 287L, 59217L /* smaller than sum(tun0) */,
+ 299L /* smaller than sum(tun0) */, 0L)
+ .addEntry(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
+
+ delta.migrateTun(tunUid, tunIface, new String[]{underlyingIface});
assertEquals(20, delta.size());
// tunIface and TEST_IFACE entries are not changed.
@@ -634,21 +634,21 @@ public class NetworkStatsTest {
final String tunIface = "tun0";
final String underlyingIface = "wlan0";
NetworkStats delta = new NetworkStats(TEST_START, 9)
- // 2 different apps sent/receive data via tun0.
- .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L)
- .addValues(tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L)
- // VPN package resends data through the tunnel (with exaggerated overhead)
- .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 240000, 100L, 120000L, 60L, 0L)
- // 1 app already has some traffic on the underlying interface, the other doesn't yet
- .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 1000L, 10L, 2000L, 20L, 0L)
- // Traffic through the underlying interface via the vpn app.
- // This test should redistribute this data correctly.
- .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 75500L, 37L, 130000L, 70L, 0L);
+ // 2 different apps sent/receive data via tun0.
+ .addEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L)
+ .addEntry(tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L)
+ // VPN package resends data through the tunnel (with exaggerated overhead)
+ .addEntry(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 240000, 100L, 120000L, 60L, 0L)
+ // 1 app already has some traffic on the underlying interface, the other doesn't yet
+ .addEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 1000L, 10L, 2000L, 20L, 0L)
+ // Traffic through the underlying interface via the vpn app.
+ // This test should redistribute this data correctly.
+ .addEntry(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 75500L, 37L, 130000L, 70L, 0L);
delta.migrateTun(tunUid, tunIface, new String[]{underlyingIface});
assertEquals(9, delta.size());
@@ -697,9 +697,9 @@ public class NetworkStatsTest {
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addValues(entry1)
- .addValues(entry2)
- .addValues(entry3);
+ .addEntry(entry1)
+ .addEntry(entry2)
+ .addEntry(entry3);
stats.filter(UID_ALL, INTERFACES_ALL, TAG_ALL);
assertEquals(3, stats.size());
@@ -724,9 +724,9 @@ public class NetworkStatsTest {
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addValues(entry1)
- .addValues(entry2)
- .addValues(entry3);
+ .addEntry(entry1)
+ .addEntry(entry2)
+ .addEntry(entry3);
stats.filter(testUid, INTERFACES_ALL, TAG_ALL);
assertEquals(2, stats.size());
@@ -755,10 +755,10 @@ public class NetworkStatsTest {
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 4)
- .addValues(entry1)
- .addValues(entry2)
- .addValues(entry3)
- .addValues(entry4);
+ .addEntry(entry1)
+ .addEntry(entry2)
+ .addEntry(entry3)
+ .addEntry(entry4);
stats.filter(UID_ALL, new String[] { testIf1, testIf2 }, TAG_ALL);
assertEquals(3, stats.size());
@@ -778,8 +778,8 @@ public class NetworkStatsTest {
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addValues(entry1)
- .addValues(entry2);
+ .addEntry(entry1)
+ .addEntry(entry2);
stats.filter(UID_ALL, new String[] { }, TAG_ALL);
assertEquals(0, stats.size());
@@ -802,9 +802,9 @@ public class NetworkStatsTest {
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addValues(entry1)
- .addValues(entry2)
- .addValues(entry3);
+ .addEntry(entry1)
+ .addEntry(entry2)
+ .addEntry(entry3);
stats.filter(UID_ALL, INTERFACES_ALL, testTag);
assertEquals(2, stats.size());
@@ -831,10 +831,10 @@ public class NetworkStatsTest {
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 4)
- .addValues(entry1)
- .addValues(entry2)
- .addValues(entry3)
- .addValues(entry4);
+ .addEntry(entry1)
+ .addEntry(entry2)
+ .addEntry(entry3)
+ .addEntry(entry4);
stats.filterDebugEntries();
@@ -891,14 +891,14 @@ public class NetworkStatsTest {
0 /* operations */);
final NetworkStats statsXt = new NetworkStats(TEST_START, 3)
- .addValues(appEntry)
- .addValues(xtRootUidEntry)
- .addValues(otherEntry);
+ .addEntry(appEntry)
+ .addEntry(xtRootUidEntry)
+ .addEntry(otherEntry);
final NetworkStats statsEbpf = new NetworkStats(TEST_START, 3)
- .addValues(appEntry)
- .addValues(ebpfRootUidEntry)
- .addValues(otherEntry);
+ .addEntry(appEntry)
+ .addEntry(ebpfRootUidEntry)
+ .addEntry(otherEntry);
statsXt.apply464xlatAdjustments(stackedIface, false);
statsEbpf.apply464xlatAdjustments(stackedIface, true);
@@ -945,8 +945,8 @@ public class NetworkStatsTest {
0 /* operations */);
NetworkStats stats = new NetworkStats(TEST_START, 2)
- .addValues(firstEntry)
- .addValues(secondEntry);
+ .addEntry(firstEntry)
+ .addEntry(secondEntry);
// Empty map: no adjustment
stats.apply464xlatAdjustments(new ArrayMap<>(), false);
diff --git a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
index c0f9dc14869f..f0e5774a5dea 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -326,14 +326,14 @@ public class NetworkStatsObserversTest {
// Baseline
NetworkStats xtSnapshot = null;
NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
@@ -359,14 +359,14 @@ public class NetworkStatsObserversTest {
// Baseline
NetworkStats xtSnapshot = null;
NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
@@ -391,14 +391,14 @@ public class NetworkStatsObserversTest {
// Baseline
NetworkStats xtSnapshot = null;
NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
@@ -424,14 +424,14 @@ public class NetworkStatsObserversTest {
// Baseline
NetworkStats xtSnapshot = null;
NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
+ .addEntry(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
ROAMING_NO, DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
+ .addEntry(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
ROAMING_NO, DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 4d42a612030d..6de068e48a38 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -298,11 +298,11 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 1024L, 8L, 2048L, 16L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L));
mService.setUidForeground(UID_RED, false);
mService.incrementOperationCount(UID_RED, 0xFAAD, 4);
mService.setUidForeground(UID_RED, true);
@@ -407,9 +407,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 10);
forcePollAndWaitForIdle();
@@ -429,9 +429,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]);
forcePollAndWaitForIdle();
@@ -443,10 +443,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 2176L, 17L, 1536L, 12L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 640L, 5L, 1024L, 8L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 640L, 5L, 1024L, 8L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L));
mService.incrementOperationCount(UID_BLUE, 0xFAAD, 10);
forcePollAndWaitForIdle();
@@ -480,10 +480,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 4128L, 258L, 544L, 34L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L)
- .addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L)
+ .addEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
mService.incrementOperationCount(UID_RED, 0xFAAD, 10);
forcePollAndWaitForIdle();
@@ -501,10 +501,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 4128L, 258L, 544L, 34L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L)
- .addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L)
+ .addEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
final Intent intent = new Intent(ACTION_UID_REMOVED);
intent.putExtra(EXTRA_UID, UID_BLUE);
mServiceContext.sendBroadcast(intent);
@@ -536,8 +536,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 5);
forcePollAndWaitForIdle();
@@ -552,8 +552,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
states = new NetworkState[] {buildMobile4gState(TEST_IFACE2)};
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]);
forcePollAndWaitForIdle();
@@ -564,10 +564,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
- .addValues(TEST_IFACE2, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
- .addValues(TEST_IFACE2, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
+ .addEntry(TEST_IFACE2, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
+ .addEntry(TEST_IFACE2, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L));
mService.incrementOperationCount(UID_RED, 0xFAAD, 5);
forcePollAndWaitForIdle();
@@ -591,9 +591,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
forcePollAndWaitForIdle();
@@ -608,9 +608,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 2048L, 16L, 1024L, 8L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 2048L, 16L, 1024L, 8L, 0L));
forcePollAndWaitForIdle();
// first verify entire history present
@@ -654,9 +654,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addValues(entry1)
- .addValues(entry2)
- .addValues(entry3));
+ .addEntry(entry1)
+ .addEntry(entry2)
+ .addEntry(entry3));
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
NetworkStats stats = mService.getDetailedUidStats(INTERFACES_ALL);
@@ -704,11 +704,11 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
.thenReturn(augmentedIfaceFilter);
when(mStatsFactory.readNetworkStatsDetail(eq(UID_ALL), any(), eq(TAG_ALL)))
.thenReturn(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(uidStats));
+ .addEntry(uidStats));
when(mNetManager.getNetworkStatsTethering(STATS_PER_UID))
.thenReturn(new NetworkStats(getElapsedRealtime(), 2)
- .addValues(tetheredStats1)
- .addValues(tetheredStats2));
+ .addEntry(tetheredStats1)
+ .addEntry(tetheredStats2));
NetworkStats stats = mService.getDetailedUidStats(ifaceFilter);
@@ -745,8 +745,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
forcePollAndWaitForIdle();
@@ -760,10 +760,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L));
mService.setUidForeground(UID_RED, true);
mService.incrementOperationCount(UID_RED, 0xFAAD, 1);
@@ -804,9 +804,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
// and DEFAULT_NETWORK_YES, because these three properties aren't tracked at that layer.
// We layer them on top by inspecting the iface properties.
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
@@ -843,9 +843,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
// ROAMING_NO, because metered and roaming isn't tracked at that layer. We layer it
// on top by inspecting the iface properties.
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_NO,
DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 0L));
forcePollAndWaitForIdle();
@@ -885,10 +885,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
// Traffic for UID_RED.
final NetworkStats uidStats = new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L);
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L);
// All tethering traffic, both hardware and software.
final NetworkStats tetherStats = new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L,
+ .addEntry(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L,
0L);
expectNetworkStatsSummary(ifaceStats, tetherStatsHardware);