diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-04-12 02:06:19 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-04-12 02:06:19 +0000 |
commit | 84a3f0c1500e5a9e4c8f0208b740fb4d2fb7813f (patch) | |
tree | 3793dc74184cc1f27e3559c2c44e50188894598d | |
parent | ffcdceab605b409cdbb6faf2103f26ad89263ed9 (diff) | |
parent | 6ee8c911d804154ae89139325eb1ed0c0c627626 (diff) | |
download | base-84a3f0c1500e5a9e4c8f0208b740fb4d2fb7813f.tar.gz |
Snap for 9922117 from 6ee8c911d804154ae89139325eb1ed0c0c627626 to studio-giraffe-release
Change-Id: I8e17f639c9670dfcdf294d5a62e97ca269908a2f
943 files changed, 20039 insertions, 5733 deletions
diff --git a/BUILD.bazel b/BUILD.bazel index 7029f8458a..09d8bbdd69 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -59,6 +59,7 @@ maven_repository( "@maven//:org.jetbrains.kotlin.kotlin-gradle-plugin-api", "@maven//:org.jetbrains.kotlin.kotlin-stdlib-jdk8", "@maven//:org.jetbrains.kotlin.kotlin-test", + "@maven//:org.jetbrains.kotlin.kotlin-test-junit", "@maven//:org.jetbrains.kotlinx.kotlinx-coroutines-core_1.4.1", "@maven//:org.jetbrains.markdown", "@maven//:org.mockito.mockito-core", diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index a8dfad92e9..86e756d018 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -9,7 +9,7 @@ ktfmt = true [Builtin Hooks Options] google_java_format = --sort-imports clang_format = --style=google --extensions cc,h --commit HEAD --git-clang-format ${REPO_ROOT}/prebuilts/tools/common/clang-format/git-clang-format --clang-format ${REPO_ROOT}/prebuilts/tools/${BUILD_OS}/clang-format/clang-format${BUILD_OS_EXEC_EXTENSION} -ktfmt = --include-dirs=adb-proxy,device-provisioner,jdwp-packet,lint --google-style +ktfmt = --include-dirs=adb-proxy,debugger-tests,device-provisioner,jdwp-packet,lint,studio-grpc-testutils --google-style [Tool Paths] google-java-format = ${REPO_ROOT}/prebuilts/tools/common/google-java-format/google-java-format diff --git a/adb-proxy/src/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ForwardingDaemonImpl.kt b/adb-proxy/src/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ForwardingDaemonImpl.kt index a2636b3653..980216aac6 100644 --- a/adb-proxy/src/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ForwardingDaemonImpl.kt +++ b/adb-proxy/src/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ForwardingDaemonImpl.kt @@ -96,7 +96,12 @@ internal class ForwardingDaemonImpl( } } reverseService = - ReverseService("localhost:$devicePort", scope, localAdbChannel, adbSession) + ReverseService( + "localhost:$devicePort", + scope, + ResponseWriter(localAdbChannel), + adbSession + ) while (true) { ensureActive() diff --git a/adb-proxy/src/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ReverseService.kt b/adb-proxy/src/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ReverseService.kt index f91fff83fe..b1d860075c 100644 --- a/adb-proxy/src/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ReverseService.kt +++ b/adb-proxy/src/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ReverseService.kt @@ -16,7 +16,6 @@ package com.google.services.firebase.directaccess.client.device.remote.service.adb.forwardingdaemon -import com.android.adblib.AdbOutputChannel import com.android.adblib.AdbSession import java.util.concurrent.ConcurrentHashMap import java.util.logging.Logger @@ -41,12 +40,23 @@ import kotlinx.coroutines.sync.withLock internal class ReverseService( private val deviceId: String, private val scope: CoroutineScope, - outputChannel: AdbOutputChannel, - private val adbSession: AdbSession + private val responseWriter: ResponseWriter, + private val adbSession: AdbSession, + private val reverseForwardStreamFactory: (String, String, Int) -> ReverseForwardStream = + { devicePort, localPort, streamId -> + ReverseForwardStream( + devicePort, + localPort, + streamId, + deviceId, + adbSession, + responseWriter, + scope + ) + } ) { private val openReverses = ConcurrentHashMap<String, ReverseForwardStream>() private val openReversesLock = Mutex() - private val responseWriter = ResponseWriter(outputChannel) /** Handle a command to the "reverse:" service. */ suspend fun handleReverse(command: String, streamId: Int) { @@ -77,16 +87,7 @@ internal class ReverseService( responseWriter.writeOkayResponse(streamId) return null } - val stream = - ReverseForwardStream( - devicePort, - localPort, - streamId, - deviceId, - adbSession, - responseWriter, - scope, - ) + val stream = reverseForwardStreamFactory(devicePort, localPort, streamId) openReverses[devicePort] = stream scope.launch { // TODO(247652380): error handling diff --git a/adb-proxy/testSrc/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ForwardingDaemonTest.kt b/adb-proxy/testSrc/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ForwardingDaemonTest.kt index d4465adc23..844c5354e4 100644 --- a/adb-proxy/testSrc/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ForwardingDaemonTest.kt +++ b/adb-proxy/testSrc/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ForwardingDaemonTest.kt @@ -15,15 +15,12 @@ */ package com.google.services.firebase.directaccess.client.device.remote.service.adb.forwardingdaemon -import com.android.adblib.AdbChannel import com.android.adblib.AdbOutputChannel import com.android.adblib.AdbServerSocket import com.android.adblib.testing.FakeAdbSession import com.android.adblib.testingutils.CoroutineTestUtils.runBlockingWithTimeout import com.android.adblib.utils.createChildScope import com.google.common.truth.Truth.assertThat -import java.nio.ByteBuffer -import java.nio.ByteOrder import java.util.concurrent.atomic.AtomicReference import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.launch @@ -78,8 +75,8 @@ class ForwardingDaemonTest { @After fun tearDown() { - fakeAdbSession.close() forwardingDaemon.close() + fakeAdbSession.close() } @Test @@ -92,7 +89,7 @@ class ForwardingDaemonTest { assertThat(forwardingDaemon.devicePort).isEqualTo(testSocket.localAddress()?.port) fakeAdbSession.channelFactory.connectSocket(testSocket.localAddress()!!).use { channel -> inputList.forEach { channel.writeExactly(it) } - // CNXN respon + // CNXN response channel.assertCommand(CNXN) // OPEN response channel.assertCommand(OKAY, 1, 1) @@ -102,34 +99,3 @@ class ForwardingDaemonTest { assertThat(payloadAssertException.get()).isEqualTo(null) } } - -private suspend fun AdbChannel.assertCommand(vararg values: Int) { - val buffer = ByteBuffer.allocate(24).order(ByteOrder.LITTLE_ENDIAN) - readExactly(buffer) - // Read payload so that next assertCommand call will read the next command written to channel - val payloadBuffer = ByteBuffer.allocate(buffer.getInt(12)).order(ByteOrder.LITTLE_ENDIAN) - readExactly(payloadBuffer) - values.forEachIndexed { index, value -> assertThat(buffer.getInt(index * 4)).isEqualTo(value) } -} - -private fun createByteBuffer( - command: Int, - firstArg: Int = 0, - secondArg: Int = 0, - payloadSize: Int = 0, - payload: String? = null -): ByteBuffer { - val bufferSize = 24 + payloadSize - return ByteBuffer.allocate(bufferSize).apply { - order(ByteOrder.LITTLE_ENDIAN) - putInt(command) - putInt(firstArg) - putInt(secondArg) - putInt(payloadSize) - putInt(0) // crc - unused - putInt(0) // magic - unused - payload?.let { put(payload.toByteArray()) } - position(bufferSize) - flip() - } -} diff --git a/adb-proxy/testSrc/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ResponseWriterTest.kt b/adb-proxy/testSrc/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ResponseWriterTest.kt new file mode 100644 index 0000000000..65cf63e6cd --- /dev/null +++ b/adb-proxy/testSrc/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ResponseWriterTest.kt @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2023 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.google.services.firebase.directaccess.client.device.remote.service.adb.forwardingdaemon + +import com.android.adblib.AdbChannel +import com.android.adblib.AdbServerSocket +import com.android.adblib.testing.FakeAdbSession +import com.android.adblib.testingutils.CoroutineTestUtils.runBlockingWithTimeout +import org.junit.After +import org.junit.Before +import org.junit.Test + +class ResponseWriterTest { + + private val fakeAdbSession = FakeAdbSession() + private lateinit var testSocket: AdbServerSocket + private lateinit var adbChannel: AdbChannel + private lateinit var responseWriter: ResponseWriter + + @Before + fun setUp() = runBlockingWithTimeout { + testSocket = + fakeAdbSession.channelFactory.createServerSocket().also { serverSocket -> + serverSocket.bind() + } + adbChannel = fakeAdbSession.channelFactory.connectSocket(testSocket.localAddress()!!) + responseWriter = ResponseWriter(adbChannel) + } + + @After + fun tearDown() = runBlockingWithTimeout { + adbChannel.close() + testSocket.close() + } + + @Test + fun testWriteOkayResponseWithoutPayload() = runBlockingWithTimeout { + responseWriter.writeOkayResponse(0) + testSocket.accept().use { channel -> + channel.assertCommand(OKAY) + channel.assertCommand(WRTE, payload = "OKAY") + channel.assertCommand(CLSE, 0) + } + } + + @Test + fun testWriteOkayResponseWithPayload() = runBlockingWithTimeout { + val okayPayload = "OKAY PAYLOAD" + responseWriter.writeOkayResponse(0, okayPayload) + testSocket.accept().use { channel -> + channel.assertCommand(OKAY) + channel.assertCommand(WRTE, payload = "OKAY${okayPayload.hexLength}$okayPayload") + channel.assertCommand(CLSE, 0) + } + } + + @Test + fun testWriteFailResponseWithPayload() = runBlockingWithTimeout { + val failedPayload = "FAIL PAYLOAD" + responseWriter.writeFailResponse(0, failedPayload) + testSocket.accept().use { channel -> + channel.assertCommand(OKAY) + channel.assertCommand(WRTE, payload = "FAIL${failedPayload.hexLength}$failedPayload") + channel.assertCommand(CLSE, 0) + } + } +} diff --git a/adb-proxy/testSrc/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ReverseServiceTest.kt b/adb-proxy/testSrc/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ReverseServiceTest.kt new file mode 100644 index 0000000000..a81a3a8b53 --- /dev/null +++ b/adb-proxy/testSrc/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/ReverseServiceTest.kt @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2023 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.google.services.firebase.directaccess.client.device.remote.service.adb.forwardingdaemon + +import com.android.adblib.AdbChannel +import com.android.adblib.AdbServerSocket +import com.android.adblib.testing.FakeAdbSession +import com.android.adblib.testingutils.CoroutineTestUtils.runBlockingWithTimeout +import com.android.testutils.MockitoKt.mock +import com.android.testutils.MockitoKt.whenever +import java.util.concurrent.CountDownLatch +import kotlinx.coroutines.runBlocking +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.mockito.Mockito.doAnswer +import org.mockito.Mockito.doReturn +import org.mockito.Mockito.times +import org.mockito.Mockito.verify + +class ReverseServiceTest { + private val fakeAdbSession = FakeAdbSession() + private val mockReverseForwardStream: ReverseForwardStream = mock() + private lateinit var testSocket: AdbServerSocket + private lateinit var adbChannel: AdbChannel + private lateinit var reverseService: ReverseService + private lateinit var countDownLatch: CountDownLatch + + @Before + fun setUp() = runBlockingWithTimeout { + testSocket = + fakeAdbSession.channelFactory.createServerSocket().also { serverSocket -> + serverSocket.bind() + } + adbChannel = fakeAdbSession.channelFactory.connectSocket(testSocket.localAddress()!!) + val serialNumber = "localhost:${testSocket.port}" + reverseService = + ReverseService( + serialNumber, + fakeAdbSession.scope, + ResponseWriter(adbChannel), + fakeAdbSession + ) { _, _, _ -> + mockReverseForwardStream + } + doAnswer { countDownLatch.countDown() }.whenever(mockReverseForwardStream).run() + } + + @After + fun tearDown() { + adbChannel.close() + testSocket.close() + fakeAdbSession.close() + } + + @Test + fun testHandleForward() = runBlockingWithTimeout { + countDownLatch = CountDownLatch(1) + reverseService.handleReverse(getReverseCommand(testSocket), 0) + // Wait until run is called. This also implies that reverseForwardStream.run() was called + countDownLatch.await() + + reverseService.handleReverse("reverse:killforward:command-${testSocket.port}", 0) + verify(mockReverseForwardStream).kill() + + testSocket.accept().use { channel -> + channel.assertCommand(OKAY) + channel.assertCommand(WRTE, payload = "OKAY") + channel.assertCommand(CLSE) + } + } + + @Test + fun testKillAll() = runBlockingWithTimeout { + val testSocket2 = fakeAdbSession.channelFactory.createServerSocket().apply { bind() } + countDownLatch = CountDownLatch(2) + reverseService.handleReverse(getReverseCommand(testSocket), 0) + reverseService.handleReverse(getReverseCommand(testSocket2), 1) + countDownLatch.await() + + reverseService.handleReverse("reverse:killforward-all", 0) + verify(mockReverseForwardStream, times(2)).kill() + + testSocket.accept().use { channel -> + channel.assertCommand(OKAY) + channel.assertCommand(WRTE, payload = "OKAY") + channel.assertCommand(CLSE) + } + testSocket2.close() + } + + @Test + fun testListForward() = runBlockingWithTimeout { + countDownLatch = CountDownLatch(2) + val testSocket2 = fakeAdbSession.channelFactory.createServerSocket().apply { bind() } + doReturn(getCommand(testSocket.port), getCommand(testSocket2.port)) + .whenever(mockReverseForwardStream) + .devicePort + doReturn("${testSocket.port}", "${testSocket2.port}") + .whenever(mockReverseForwardStream) + .localPort + reverseService.handleReverse(getReverseCommand(testSocket), 0) + reverseService.handleReverse(getReverseCommand(testSocket2), 1) + countDownLatch.await() + + reverseService.handleReverse("reverse:list-forward", 0) + + testSocket.accept().use { channel -> + channel.assertCommand(OKAY) + val payload = + "(reverse) ${getCommand(testSocket.port)} ${testSocket.port}\n" + + "(reverse) ${getCommand(testSocket2.port)} ${testSocket2.port}\n" + channel.assertCommand(WRTE, payload = "OKAY${payload.hexLength}$payload") + channel.assertCommand(CLSE) + } + + testSocket2.close() + } +} + +private fun getReverseCommand(socket: AdbServerSocket): String { + val port = socket.port + return "reverse:forward:${getCommand(port)};tcp:$port" +} + +private fun getCommand(port: Int) = "command-$port" + +private val AdbServerSocket.port: Int + get() = runBlocking { + assert(localAddress() != null) + return@runBlocking localAddress()!!.port + } diff --git a/adb-proxy/testSrc/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/TestUtils.kt b/adb-proxy/testSrc/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/TestUtils.kt new file mode 100644 index 0000000000..30ba23a9ba --- /dev/null +++ b/adb-proxy/testSrc/com/google/services/firebase/directaccess/client/device/remote/service/adb/forwardingdaemon/TestUtils.kt @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2023 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.google.services.firebase.directaccess.client.device.remote.service.adb.forwardingdaemon + +import com.android.adblib.AdbChannel +import com.google.common.truth.Truth.assertThat +import java.nio.ByteBuffer +import java.nio.ByteOrder + +internal fun createByteBuffer( + command: Int, + firstArg: Int = 0, + secondArg: Int = 0, + payloadSize: Int = 0, + payload: String? = null +): ByteBuffer { + val bufferSize = 24 + payloadSize + return ByteBuffer.allocate(bufferSize).apply { + order(ByteOrder.LITTLE_ENDIAN) + putInt(command) + putInt(firstArg) + putInt(secondArg) + putInt(payloadSize) + putInt(0) // crc - unused + putInt(0) // magic - unused + payload?.let { put(payload.toByteArray()) } + position(bufferSize) + flip() + } +} + +suspend fun AdbChannel.assertCommand(vararg values: Int, payload: String? = null) { + val buffer = ByteBuffer.allocate(24).order(ByteOrder.LITTLE_ENDIAN) + readExactly(buffer) + // Read payload so that next assertCommand call will read the next command written to channel + val payloadBuffer = ByteBuffer.allocate(buffer.getInt(12)).order(ByteOrder.LITTLE_ENDIAN) + readExactly(payloadBuffer) + payload?.let { assertThat(String(payloadBuffer.array())).isEqualTo(it) } + values.forEachIndexed { index, value -> assertThat(buffer.getInt(index * 4)).isEqualTo(value) } +} + +val String.hexLength: String + get() = String.format("%04X", length) diff --git a/adblib-ddmlibcompatibility/test/src/com/android/adblib/ddmlibcompatibility/debugging/AdbLibDeviceClientManagerTest.kt b/adblib-ddmlibcompatibility/test/src/com/android/adblib/ddmlibcompatibility/debugging/AdbLibDeviceClientManagerTest.kt index f24d62f568..b63ad7a27b 100644 --- a/adblib-ddmlibcompatibility/test/src/com/android/adblib/ddmlibcompatibility/debugging/AdbLibDeviceClientManagerTest.kt +++ b/adblib-ddmlibcompatibility/test/src/com/android/adblib/ddmlibcompatibility/debugging/AdbLibDeviceClientManagerTest.kt @@ -641,7 +641,7 @@ class AdbLibDeviceClientManagerTest { DdmsProtocolKind.EmptyRepliesDiscarded, client.jdwpProcess.device.ddmsProtocolKind() ) - Assert.assertEquals(1, clientState.hgpcRequestsCount) + Assert.assertEquals(1, clientState.getHgpcRequestsCount()) } @Test @@ -679,7 +679,7 @@ class AdbLibDeviceClientManagerTest { DdmsProtocolKind.EmptyRepliesAllowed, client.jdwpProcess.device.ddmsProtocolKind() ) - Assert.assertEquals(1, clientState.hgpcRequestsCount) + Assert.assertEquals(1, clientState.getHgpcRequestsCount()) } @Test diff --git a/adblib-tools/src/com/android/adblib/tools/debugging/SharedJdwpSessionUtils.kt b/adblib-tools/src/com/android/adblib/tools/debugging/SharedJdwpSessionUtils.kt index d828cdc47a..cf752108e3 100644 --- a/adblib-tools/src/com/android/adblib/tools/debugging/SharedJdwpSessionUtils.kt +++ b/adblib-tools/src/com/android/adblib/tools/debugging/SharedJdwpSessionUtils.kt @@ -25,7 +25,6 @@ import com.android.adblib.tools.debugging.packets.MutableJdwpPacket import com.android.adblib.tools.debugging.packets.ddms.DdmsChunkTypes import com.android.adblib.tools.debugging.packets.ddms.DdmsChunkTypes.Companion.MPRQ import com.android.adblib.tools.debugging.packets.ddms.DdmsChunkTypes.Companion.VURTOpCode -import com.android.adblib.tools.debugging.packets.ddms.DdmsChunkTypes.Companion.chunkTypeToString import com.android.adblib.tools.debugging.packets.ddms.DdmsChunkView import com.android.adblib.tools.debugging.packets.ddms.DdmsFailException import com.android.adblib.tools.debugging.packets.ddms.DdmsPacketConstants @@ -135,7 +134,12 @@ suspend fun SharedJdwpSession.sendDdmsExit(status: Int) { buffer.putInt(status) // [pos = 4, limit =4] buffer.flip() // [pos = 0, limit =4] val packet = createDdmsPacket(DdmsChunkTypes.EXIT, buffer) - sendPacket(packet) + + // Send packet and wait for EOF (i.e. wait for JDWP session to end when process terminates) + newPacketReceiver() + .withName("sendDdmsExit") + .onActivation { sendPacket(packet) } + .collect { } } /** @@ -303,7 +307,7 @@ suspend fun <R> SharedJdwpSession.handleDdmsCaptureView( * @throws DdmsCommandException if there is an unexpected DDMS/JDWP protocol error */ suspend fun <R> SharedJdwpSession.handleDdmsCommand( - chunkType: Int, + chunkType: DdmsChunkTypes, payload: ByteBuffer, progress: JdwpCommandProgress? = null, replyHandler: suspend (DdmsChunkView) -> R @@ -318,11 +322,11 @@ suspend fun <R> SharedJdwpSession.handleDdmsCommand( private suspend fun <R> SharedJdwpSession.processDdmsReplyPacket( packet: JdwpPacketView, - chunkType: Int, + chunkType: DdmsChunkTypes, block: suspend (packet: DdmsChunkView) -> R ): R { val logger = thisLogger(device.session) - val chunkTypeString = chunkTypeToString(chunkType) + val chunkTypeString = chunkType.text // Error: FAIL packet packet.getDdmsFail()?.also { failChunk -> @@ -335,7 +339,7 @@ private suspend fun <R> SharedJdwpSession.processDdmsReplyPacket( return packet.ddmsChunks().map { replyChunk -> if (replyChunk.type != chunkType) { - val message = "DDMS reply '${chunkTypeToString(replyChunk.type)}' " + + val message = "DDMS reply '${replyChunk.type}' " + "does not match DDMS command '$chunkTypeString'" logger.warn(message) throw DdmsCommandException(message) @@ -368,13 +372,11 @@ private suspend fun <R> SharedJdwpSession.processDdmsReplyPacket( */ suspend fun SharedJdwpSession.handleDdmsCommandWithEmptyReply( requestPacket: JdwpPacketView, - chunkType: Int, + chunkType: DdmsChunkTypes, progress: JdwpCommandProgress? ) { val logger = thisLogger(device.session).withPrefix("pid=$pid: ") - val chunkTypeString = chunkTypeToString(chunkType) - - logger.debug { "Invoking DDMS command $chunkTypeString" } + logger.debug { "Invoking DDMS command ${chunkType.text}" } return handleDdmsCommandAndReplyProtocol(progress) { signal -> handleAlwaysEmptyReplyDdmsCommand(requestPacket, chunkType, progress, signal) @@ -383,15 +385,14 @@ suspend fun SharedJdwpSession.handleDdmsCommandWithEmptyReply( private suspend fun SharedJdwpSession.handleAlwaysEmptyReplyDdmsCommand( requestPacket: JdwpPacketView, - chunkType: Int, + chunkType: DdmsChunkTypes, progress: JdwpCommandProgress?, signal: Signal<Unit>? ) { val logger = thisLogger(device.session).withPrefix("pid=$pid: ") - val chunkTypeString = chunkTypeToString(chunkType) newPacketReceiver() - .withName("handleEmptyReplyDdmsCommand($chunkTypeString)") + .withName("handleEmptyReplyDdmsCommand(${chunkType.text})") .onActivation { progress?.beforeSend(requestPacket) sendPacket(requestPacket) @@ -412,9 +413,12 @@ private suspend fun SharedJdwpSession.handleAlwaysEmptyReplyDdmsCommand( } } -suspend fun SharedJdwpSession.processEmptyDdmsReplyPacket(packet: JdwpPacketView, chunkType: Int) { +suspend fun SharedJdwpSession.processEmptyDdmsReplyPacket( + packet: JdwpPacketView, + chunkType: DdmsChunkTypes +) { val logger = thisLogger(device.session).withPrefix("pid=$pid: ") - val chunkTypeString = chunkTypeToString(chunkType) + val chunkTypeString = chunkType.text // Error: FAIL packet packet.getDdmsFail()?.also { failChunk -> @@ -499,11 +503,11 @@ suspend fun AdbInputChannel.toByteArray(size: Int): ByteArray { return result } -fun SharedJdwpSession.createDdmsPacket(chunkType: Int, chunkPayload: ByteBuffer): JdwpPacketView { +fun SharedJdwpSession.createDdmsPacket(chunkType: DdmsChunkTypes, chunkPayload: ByteBuffer): JdwpPacketView { return JdwpPacketFactory.createDdmsPacket(nextPacketId(), chunkType, chunkPayload) .also { packet -> val logger = thisLogger(device.session) - logger.verbose { "Sending DDMS command '${chunkTypeToString(chunkType)}' in JDWP packet $packet" } + logger.verbose { "Sending DDMS command '$chunkType' in JDWP packet $packet" } } } diff --git a/adblib-tools/src/com/android/adblib/tools/debugging/impl/JdwpProcessProfilerImpl.kt b/adblib-tools/src/com/android/adblib/tools/debugging/impl/JdwpProcessProfilerImpl.kt index dc2e3509f5..492a16601d 100644 --- a/adblib-tools/src/com/android/adblib/tools/debugging/impl/JdwpProcessProfilerImpl.kt +++ b/adblib-tools/src/com/android/adblib/tools/debugging/impl/JdwpProcessProfilerImpl.kt @@ -107,7 +107,7 @@ internal class JdwpProcessProfilerImpl( private suspend fun <R> SharedJdwpSession.handleMPSEReply( requestPacket: JdwpPacketView, - chunkType: Int, + chunkType: DdmsChunkTypes, progress: JdwpCommandProgress?, block: suspend (data: AdbInputChannel, dataLength: Int) -> R ): R { @@ -118,7 +118,7 @@ internal class JdwpProcessProfilerImpl( private suspend fun <R> SharedJdwpSession.handleMPSEReplyImpl( requestPacket: JdwpPacketView, - chunkType: Int, + chunkType: DdmsChunkTypes, progress: JdwpCommandProgress?, signal: Signal<R>, block: suspend (data: AdbInputChannel, dataLength: Int) -> R diff --git a/adblib-tools/src/com/android/adblib/tools/debugging/impl/JdwpProcessPropertiesCollector.kt b/adblib-tools/src/com/android/adblib/tools/debugging/impl/JdwpProcessPropertiesCollector.kt index 84be72e4f9..3de290f388 100644 --- a/adblib-tools/src/com/android/adblib/tools/debugging/impl/JdwpProcessPropertiesCollector.kt +++ b/adblib-tools/src/com/android/adblib/tools/debugging/impl/JdwpProcessPropertiesCollector.kt @@ -379,7 +379,7 @@ internal class JdwpProcessPropertiesCollector( private suspend fun createDdmsChunkPacket( packetId: Int, - chunkType: Int, + chunkType: DdmsChunkTypes, chunkData: ByteBuffer ): JdwpPacketView { val chunk = MutableDdmsChunk() diff --git a/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkTypes.kt b/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkTypes.kt index 197570660f..81fa27212c 100644 --- a/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkTypes.kt +++ b/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkTypes.kt @@ -15,80 +15,91 @@ */ package com.android.adblib.tools.debugging.packets.ddms -class DdmsChunkTypes { +@JvmInline +value class DdmsChunkTypes(val value: Int) { + + val text: String + get() = chunkTypeToString(this) + + override fun toString(): String { + return text + } + @Suppress("SpellCheckingInspection") companion object { - val FAIL: Int = chunkTypeFromString("FAIL") + val NULL = DdmsChunkTypes(0) + + val FAIL = chunkTypeFromString("FAIL") - val HELO: Int = chunkTypeFromString("HELO") + val HELO = chunkTypeFromString("HELO") - val FEAT: Int = chunkTypeFromString("FEAT") + val FEAT = chunkTypeFromString("FEAT") /** * "REAE: REcent Allocation Enable" */ - val REAE: Int = chunkTypeFromString("REAE") + val REAE = chunkTypeFromString("REAE") /** * "REAQ: REcent Allocation Query" */ - val REAQ: Int = chunkTypeFromString("REAQ") + val REAQ = chunkTypeFromString("REAQ") /** * "REAL: REcent Allocation List" */ - val REAL: Int = chunkTypeFromString("REAL") + val REAL = chunkTypeFromString("REAL") - val APNM: Int = chunkTypeFromString("APNM") + val APNM = chunkTypeFromString("APNM") - val WAIT: Int = chunkTypeFromString("WAIT") + val WAIT = chunkTypeFromString("WAIT") - val EXIT: Int = chunkTypeFromString("EXIT") + val EXIT = chunkTypeFromString("EXIT") /** * Requests a `Method Profiling Streaming Start` */ - val MPSS: Int = chunkTypeFromString("MPSS") + val MPSS = chunkTypeFromString("MPSS") /** * Requests a `Method Profiling Streaming End` */ - val MPSE: Int = chunkTypeFromString("MPSE") + val MPSE = chunkTypeFromString("MPSE") /** * Requests a `Method PRofiling Start` */ - val MPRS: Int = chunkTypeFromString("MPRS") + val MPRS = chunkTypeFromString("MPRS") /** * Requests a `Method PRofiling End` */ - val MPRE: Int = chunkTypeFromString("MPRE") + val MPRE = chunkTypeFromString("MPRE") /** * Requests a `Method PRofiling Query` */ - val MPRQ: Int = chunkTypeFromString("MPRQ") + val MPRQ = chunkTypeFromString("MPRQ") /** * Requests a `Sampling Profiling Streaming Start` */ - val SPSS: Int = chunkTypeFromString("SPSS") + val SPSS = chunkTypeFromString("SPSS") /** * Requests a `Sampling Profiling Streaming End` */ - val SPSE: Int = chunkTypeFromString("SPSE") + val SPSE = chunkTypeFromString("SPSE") /** * List `ViewRootImpl`'s of this process */ - val VULW: Int = chunkTypeFromString("VULW") + val VULW = chunkTypeFromString("VULW") /** * Operation on view root, first parameter in packet should be one of VURT_* constants */ - val VURT: Int = chunkTypeFromString("VURT") + val VURT = chunkTypeFromString("VURT") enum class VURTOpCode(val value: Int) { /** @@ -101,12 +112,12 @@ class DdmsChunkTypes { * Generic View Operation, first parameter in the packet should be one of the VUOP_* constants * below. */ - val VUOP: Int = chunkTypeFromString("VUOP") + val VUOP = chunkTypeFromString("VUOP") /** * Requests a Gabage Collection of a process (`HeaP Gabage Collect`) */ - val HPGC: Int = chunkTypeFromString("HPGC") + val HPGC = chunkTypeFromString("HPGC") enum class VUOPOpCode(val value: Int) { @@ -117,25 +128,25 @@ class DdmsChunkTypes { /** * Convert a 4-character string to a 32-bit chunk type. */ - private fun chunkTypeFromString(type: String): Int { + private fun chunkTypeFromString(type: String): DdmsChunkTypes { var result = 0 check(type.length == 4) { "Type name must be 4 letter long" } for (i in 0..3) { result = result shl 8 result = result or type[i].code.toByte().toInt() } - return result + return DdmsChunkTypes(result) } /** * Convert an integer type to a 4-character string. */ - fun chunkTypeToString(type: Int): String { + private fun chunkTypeToString(type: DdmsChunkTypes): String { val ascii = ByteArray(4) - ascii[0] = (type shr 24 and 0xff).toByte() - ascii[1] = (type shr 16 and 0xff).toByte() - ascii[2] = (type shr 8 and 0xff).toByte() - ascii[3] = (type and 0xff).toByte() + ascii[0] = (type.value shr 24 and 0xff).toByte() + ascii[1] = (type.value shr 16 and 0xff).toByte() + ascii[2] = (type.value shr 8 and 0xff).toByte() + ascii[3] = (type.value and 0xff).toByte() return String(ascii, Charsets.US_ASCII) } } diff --git a/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkUtils.kt b/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkUtils.kt index 1b15041127..cf4844123e 100644 --- a/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkUtils.kt +++ b/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkUtils.kt @@ -49,7 +49,7 @@ internal suspend fun DdmsChunkView.writeToChannel( workBuffer.order(DDMS_CHUNK_BYTE_ORDER) // Write header - workBuffer.appendInt(type) + workBuffer.appendInt(type.value) workBuffer.appendInt(length) channel.writeExactly(workBuffer.forChannelWrite()) @@ -125,7 +125,7 @@ internal fun JdwpPacketView.ddmsChunks( // Prepare chunk source val chunk = MutableDdmsChunk().apply { - this.type = payloadBuffer.getInt() + this.type = DdmsChunkTypes(payloadBuffer.getInt()) this.length = payloadBuffer.getInt() val slice = AdbInputChannelSlice(jdwpPacketView.payload, this.length) this.payload = AdbBufferedInputChannel.forInputChannel(slice) @@ -182,7 +182,7 @@ internal suspend fun DdmsChunkView.throwFailException(): Nothing { throw createFailException() } -class DdmsFailException(val errorCode: Int, val failMessage: String): Exception() { +class DdmsFailException(val errorCode: Int, val failMessage: String) : Exception() { override val message: String? get() = "DDMS Failure on AndroidVM: errorCode=$errorCode, message=$failMessage" diff --git a/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkView.kt b/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkView.kt index d045bf471f..2b50889923 100644 --- a/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkView.kt +++ b/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkView.kt @@ -25,7 +25,7 @@ interface DdmsChunkView { /** * The chunk type, a 4-byte integer, see [DdmsChunkTypes] */ - val type: Int + val type: DdmsChunkTypes /** * The length (in bytes) of [payload], a 4-byte integer. diff --git a/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/JdwpPacketFactory.kt b/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/JdwpPacketFactory.kt index 86efc286bd..1d20b9e440 100644 --- a/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/JdwpPacketFactory.kt +++ b/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/JdwpPacketFactory.kt @@ -26,14 +26,14 @@ object JdwpPacketFactory { */ fun createDdmsPacket( jdwpPacketId: Int, - chunkType: Int, + chunkType: DdmsChunkTypes, chunkPayload: ByteBuffer ): MutableJdwpPacket { // Serialize chunk into a ByteBuffer val serializedChunk = ByteBuffer.allocate(DDMS_CHUNK_HEADER_LENGTH + chunkPayload.remaining()) serializedChunk.order(DdmsPacketConstants.DDMS_CHUNK_BYTE_ORDER) - serializedChunk.putInt(chunkType) + serializedChunk.putInt(chunkType.value) serializedChunk.putInt(chunkPayload.remaining()) serializedChunk.put(chunkPayload) serializedChunk.flip() diff --git a/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/MutableDdmsChunk.kt b/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/MutableDdmsChunk.kt index e721fb179a..f99977f620 100644 --- a/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/MutableDdmsChunk.kt +++ b/adblib-tools/src/com/android/adblib/tools/debugging/packets/ddms/MutableDdmsChunk.kt @@ -16,20 +16,19 @@ package com.android.adblib.tools.debugging.packets.ddms import com.android.adblib.tools.debugging.packets.AdbBufferedInputChannel -import com.android.adblib.tools.debugging.packets.ddms.DdmsChunkTypes.Companion.chunkTypeToString /** * A mutable version of [DdmsChunkView], to be used when creating DDMS "chunks" */ internal class MutableDdmsChunk : DdmsChunkView { - override var type: Int = 0 + override var type: DdmsChunkTypes = DdmsChunkTypes.NULL override var length: Int = 0 override var payload = AdbBufferedInputChannel.empty() override fun toString(): String { - return "DDMS Chunk: type=$type (${chunkTypeToString(type)}), length=$length" + return "DDMS Chunk: type=$type (${type.value}), length=$length" } } diff --git a/adblib-tools/test/src/com/android/adblib/tools/JavaBridgeTest.java b/adblib-tools/test/src/com/android/adblib/tools/JavaBridgeTest.java index 4a6b817454..5ebf3c9577 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/JavaBridgeTest.java +++ b/adblib-tools/test/src/com/android/adblib/tools/JavaBridgeTest.java @@ -24,8 +24,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import com.android.adblib.AdbSession; -import com.android.adblib.testingutils.FakeAdbServerProvider; import com.android.adblib.tools.testutils.AdbLibToolsTestBase; import java.io.IOException; import java.lang.reflect.InvocationTargetException; @@ -44,18 +42,15 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { @Test public void runBlockingWorks() { // Prepare - FakeAdbServerProvider fakeAdb = - registerCloseable(new FakeAdbServerProvider().buildDefault().start()); - AdbSession session = createHostServices(fakeAdb).getSession(); // Act int version = JavaBridge.runBlocking( - session, + getSession(), continuation -> { - return session.getHostServices().version(continuation); + return getSession().getHostServices().version(continuation); }, - session.getScope(), + getSession().getScope(), 30_000); // Assert @@ -65,16 +60,13 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { @Test public void runBlockingHandlesNonSuspendingCoroutines() { // Prepare - FakeAdbServerProvider fakeAdb = - registerCloseable(new FakeAdbServerProvider().buildDefault().start()); - AdbSession session = createHostServices(fakeAdb).getSession(); // Act int result = JavaBridge.runBlocking( - session, + getSession(), cnt -> JavaBridgeTestUtils.immediateResultCoroutine(5, cnt), - session.getScope(), + getSession().getScope(), 30_000); // Assert @@ -84,17 +76,14 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { @Test public void runBlockingHandlesExceptionNonSuspendingCoroutines() { // Prepare - FakeAdbServerProvider fakeAdb = - registerCloseable(new FakeAdbServerProvider().buildDefault().start()); - AdbSession session = createHostServices(fakeAdb).getSession(); // Act exceptionRule.expect(Exception.class); exceptionRule.expectMessage("test"); JavaBridge.runBlocking( - session, + getSession(), cnt -> JavaBridgeTestUtils.immediateExceptionCoroutine("test", cnt), - session.getScope(), + getSession().getScope(), 30_000); // Assert @@ -104,15 +93,12 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { @Test public void runBlockingIsTransparentToExceptions() { // Prepare - FakeAdbServerProvider fakeAdb = - registerCloseable(new FakeAdbServerProvider().buildDefault().start()); - AdbSession session = createHostServices(fakeAdb).getSession(); // Act exceptionRule.expect(RuntimeException.class); exceptionRule.expectMessage("My Message"); JavaBridge.runBlocking( - session, + getSession(), continuation -> { throw new RuntimeException("My Message"); }); @@ -124,18 +110,15 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { @Test public void runBlockingHandlesTimeout() { // Prepare - FakeAdbServerProvider fakeAdb = - registerCloseable(new FakeAdbServerProvider().buildDefault().start()); - AdbSession session = createHostServices(fakeAdb).getSession(); // Act exceptionRule.expect(TimeoutCancellationException.class); JavaBridge.runBlocking( - session, + getSession(), cnt -> { return delay(5_000, cnt); }, - session.getScope(), + getSession().getScope(), 10); // Assert @@ -146,9 +129,6 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { @Test public void runBlockingIsCancelledWhenScopeIsCancelled() throws Throwable { // Prepare - FakeAdbServerProvider fakeAdb = - registerCloseable(new FakeAdbServerProvider().buildDefault().start()); - AdbSession session = createHostServices(fakeAdb).getSession(); // Act AtomicBoolean hasStarted = new AtomicBoolean(false); @@ -156,7 +136,7 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { new Thread( () -> { JavaBridge.runBlocking( - session, + getSession(), continuation -> { hasStarted.set(true); return delay(10_000, continuation); @@ -171,7 +151,7 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { while (!hasStarted.get()) { // Wait until thread has started } - session.close(); + getSession().close(); t.join(1_000); // Assert @@ -183,16 +163,13 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { @Test public void runBlockingThrowsWhenCalledOnEventDispatchThread() throws Throwable { // Prepare - FakeAdbServerProvider fakeAdb = - registerCloseable(new FakeAdbServerProvider().buildDefault().start()); - AdbSession session = createHostServices(fakeAdb).getSession(); // Act exceptionRule.expect(InvocationTargetException.class); exceptionRule.expectCause(instanceOf(IllegalStateException.class)); SwingUtilities.invokeAndWait( () -> { - JavaBridge.runBlocking(session, continuation -> delay(10, continuation)); + JavaBridge.runBlocking(getSession(), continuation -> delay(10, continuation)); }); // Assert @@ -202,14 +179,12 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { @Test public void invokeAsyncWorks() { // Prepare - FakeAdbServerProvider fakeAdb = - registerCloseable(new FakeAdbServerProvider().buildDefault().start()); - AdbSession session = createHostServices(fakeAdb).getSession(); // Act JavaDeferred<Integer> deferredVersion = JavaBridge.invokeAsync( - session, continuation -> session.getHostServices().version(continuation)); + getSession(), + continuation -> getSession().getHostServices().version(continuation)); int version = deferredVersion.awaitBlocking(); // Assert @@ -219,14 +194,11 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { @Test public void invokeAsyncIsTransparentToExceptions() { // Prepare - FakeAdbServerProvider fakeAdb = - registerCloseable(new FakeAdbServerProvider().buildDefault().start()); - AdbSession session = createHostServices(fakeAdb).getSession(); // Act JavaDeferred<Object> deferred = JavaBridge.invokeAsync( - session, + getSession(), continuation -> { throw new RuntimeException("My Message"); }); @@ -243,19 +215,16 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { @Test public void invokeAsyncCanBeCancelled() throws Throwable { // Prepare - FakeAdbServerProvider fakeAdb = - registerCloseable(new FakeAdbServerProvider().buildDefault().start()); - AdbSession session = createHostServices(fakeAdb).getSession(); // Act JavaDeferred<Unit> deferred = - JavaBridge.invokeAsync(session, continuation -> delay(10_000, continuation)); + JavaBridge.invokeAsync(getSession(), continuation -> delay(10_000, continuation)); // Wait until async has started running while (!deferred.isActive()) { // Wait until thread has started } - session.close(); + getSession().close(); // Assert assertTrue(deferred.isCancelled()); @@ -264,9 +233,6 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { @Test public void invokeAsyncWorksOnEventDispatchThread() throws Throwable { // Prepare - FakeAdbServerProvider fakeAdb = - registerCloseable(new FakeAdbServerProvider().buildDefault().start()); - AdbSession session = createHostServices(fakeAdb).getSession(); // Act AtomicReference<JavaDeferred<Integer>> deferredVersion = new AtomicReference<>(); @@ -274,9 +240,9 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { () -> { JavaDeferred<Integer> deferred = JavaBridge.invokeAsync( - session, + getSession(), continuation -> - session.getHostServices().version(continuation)); + getSession().getHostServices().version(continuation)); deferredVersion.set(deferred); }); @@ -289,14 +255,12 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { @Test public void invokeAsyncAddCallbackWorks() throws Throwable { // Prepare - FakeAdbServerProvider fakeAdb = - registerCloseable(new FakeAdbServerProvider().buildDefault().start()); - AdbSession session = createHostServices(fakeAdb).getSession(); // Act JavaDeferred<Integer> deferredVersion = JavaBridge.invokeAsync( - session, continuation -> session.getHostServices().version(continuation)); + getSession(), + continuation -> getSession().getHostServices().version(continuation)); AtomicInteger version = new AtomicInteger(); deferredVersion.addCallback( (throwable, value) -> { @@ -313,14 +277,11 @@ public class JavaBridgeTest extends AdbLibToolsTestBase { @Test public void invokeAsyncAddCallbackIsTransparentToExceptions() throws Throwable { // Prepare - FakeAdbServerProvider fakeAdb = - registerCloseable(new FakeAdbServerProvider().buildDefault().start()); - AdbSession session = createHostServices(fakeAdb).getSession(); // Act JavaDeferred<Integer> deferredVersion = JavaBridge.invokeAsync( - session, + getSession(), continuation -> { throw new IOException("My Message"); }); diff --git a/adblib-tools/test/src/com/android/adblib/tools/debugging/AppProcessTrackerTest.kt b/adblib-tools/test/src/com/android/adblib/tools/debugging/AppProcessTrackerTest.kt index 8aa8f8b610..4bed13695f 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/debugging/AppProcessTrackerTest.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/debugging/AppProcessTrackerTest.kt @@ -18,8 +18,8 @@ package com.android.adblib.tools.debugging import com.android.adblib.connectedDevicesTracker import com.android.adblib.serialNumber import com.android.adblib.testingutils.CoroutineTestUtils -import com.android.adblib.testingutils.FakeAdbServerProvider -import com.android.adblib.tools.testutils.AdbLibToolsTestBase +import com.android.adblib.testingutils.FakeAdbServerProviderRule +import com.android.adblib.tools.testutils.waitForOnlineConnectedDevice import com.android.fakeadbserver.DeviceState import kotlinx.coroutines.cancel import kotlinx.coroutines.delay @@ -29,20 +29,29 @@ import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.takeWhile import kotlinx.coroutines.isActive import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import org.junit.Assert +import org.junit.Rule import org.junit.Test import java.time.Duration import java.util.concurrent.CancellationException import java.util.concurrent.CopyOnWriteArrayList -class AppProcessTrackerTest : AdbLibToolsTestBase() { +class AppProcessTrackerTest { + + @JvmField + @Rule + val fakeAdbRule = FakeAdbServerProviderRule { + installDefaultCommandHandlers() + setFeatures("push_sync") + } + + private val fakeAdb get() = fakeAdbRule.fakeAdb + private val hostServices get() = fakeAdbRule.adbSession.hostServices @Test fun testAppProcessTrackerWorks(): Unit = CoroutineTestUtils.runBlockingWithTimeout { val deviceID = "1234" - val theOneFeatureSupported = "push_sync" - val features = setOf(theOneFeatureSupported) - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildWithFeatures(features).start()) val fakeDevice = fakeAdb.connectDevice( deviceID, @@ -53,7 +62,6 @@ class AppProcessTrackerTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) val connectedDevice = waitForOnlineConnectedDevice(hostServices.session, fakeDevice.deviceId) val pid10 = 10 @@ -166,10 +174,6 @@ class AppProcessTrackerTest : AdbLibToolsTestBase() { CoroutineTestUtils.runBlockingWithTimeout { // Prepare val deviceID = "1234" - val theOneFeatureSupported = "push_sync" - val features = setOf(theOneFeatureSupported) - val fakeAdb = - registerCloseable(FakeAdbServerProvider().buildWithFeatures(features).start()) val fakeDevice = fakeAdb.connectDevice( deviceID, @@ -180,7 +184,6 @@ class AppProcessTrackerTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) val connectedDevice = waitForOnlineConnectedDevice(hostServices.session, fakeDevice.deviceId) val pid10 = 10 @@ -213,10 +216,6 @@ class AppProcessTrackerTest : AdbLibToolsTestBase() { CoroutineTestUtils.runBlockingWithTimeout { // Prepare val deviceID = "1234" - val theOneFeatureSupported = "push_sync" - val features = setOf(theOneFeatureSupported) - val fakeAdb = - registerCloseable(FakeAdbServerProvider().buildWithFeatures(features).start()) val fakeDevice = fakeAdb.connectDevice( deviceID, @@ -227,23 +226,23 @@ class AppProcessTrackerTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) val connectedDevice = waitForOnlineConnectedDevice(hostServices.session, fakeDevice.deviceId) val pid10 = 10 // Act - exceptionRule.expect(Exception::class.java) - exceptionRule.expectMessage("My Test Exception") - fakeDevice.startClient(pid10, 0, "a.b.c", false) - - val appTracker = AppProcessTracker.create(connectedDevice) - appTracker.appProcessFlow.collect { - throw Exception("My Test Exception") + val exception = Assert.assertThrows(Exception::class.java) { + fakeDevice.startClient(pid10, 0, "a.b.c", false) + val appTracker = AppProcessTracker.create(connectedDevice) + runBlocking { + appTracker.appProcessFlow.collect { + throw Exception("My Test Exception") + } + } } - // Assert (should not reach) - Assert.fail() + // Assert + Assert.assertEquals(exception.message, "My Test Exception") } @Test @@ -251,10 +250,6 @@ class AppProcessTrackerTest : AdbLibToolsTestBase() { CoroutineTestUtils.runBlockingWithTimeout { // Prepare val deviceID = "1234" - val theOneFeatureSupported = "push_sync" - val features = setOf(theOneFeatureSupported) - val fakeAdb = - registerCloseable(FakeAdbServerProvider().buildWithFeatures(features).start()) val fakeDevice = fakeAdb.connectDevice( deviceID, @@ -265,23 +260,23 @@ class AppProcessTrackerTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) val connectedDevice = waitForOnlineConnectedDevice(hostServices.session, fakeDevice.deviceId) val pid10 = 10 - // Act - exceptionRule.expect(CancellationException()::class.java) - exceptionRule.expectMessage("My Test Exception") - fakeDevice.startClient(pid10, 0, "a.b.c", false) - - val appTracker = AppProcessTracker.create(connectedDevice) - appTracker.appProcessFlow.collect { - cancel("My Test Exception") + // Act/Assert + val exception = Assert.assertThrows(CancellationException::class.java) { + fakeDevice.startClient(pid10, 0, "a.b.c", false) + val appTracker = AppProcessTracker.create(connectedDevice) + runBlocking { + appTracker.appProcessFlow.collect { + cancel("My Test Exception") + } + } } - // Assert (should not reach) - Assert.fail() + // Assert + Assert.assertEquals(exception.message, "My Test Exception") } @Test @@ -289,10 +284,6 @@ class AppProcessTrackerTest : AdbLibToolsTestBase() { CoroutineTestUtils.runBlockingWithTimeout { // Prepare val deviceID = "1234" - val theOneFeatureSupported = "push_sync" - val features = setOf(theOneFeatureSupported) - val fakeAdb = - registerCloseable(FakeAdbServerProvider().buildWithFeatures(features).start()) val fakeDevice = fakeAdb.connectDevice( deviceID, @@ -302,7 +293,6 @@ class AppProcessTrackerTest : AdbLibToolsTestBase() { "30", // SDK >= 30 is required for abb_exec feature. DeviceState.HostConnectionType.USB ) - val hostServices = createHostServices(fakeAdb) val connectedDevice = hostServices.session.connectedDevicesTracker.connectedDevices .mapNotNull { connectedDevices -> diff --git a/adblib-tools/test/src/com/android/adblib/tools/debugging/JdwpProcessTrackerTest.kt b/adblib-tools/test/src/com/android/adblib/tools/debugging/JdwpProcessTrackerTest.kt index 965c01cf02..8da132d1f0 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/debugging/JdwpProcessTrackerTest.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/debugging/JdwpProcessTrackerTest.kt @@ -17,8 +17,8 @@ package com.android.adblib.tools.debugging import com.android.adblib.testingutils.CoroutineTestUtils.runBlockingWithTimeout import com.android.adblib.testingutils.CoroutineTestUtils.yieldUntil -import com.android.adblib.testingutils.FakeAdbServerProvider -import com.android.adblib.tools.testutils.AdbLibToolsTestBase +import com.android.adblib.testingutils.FakeAdbServerProviderRule +import com.android.adblib.tools.testutils.waitForOnlineConnectedDevice import com.android.fakeadbserver.DeviceState import kotlinx.coroutines.CancellationException import kotlinx.coroutines.cancel @@ -28,18 +28,27 @@ import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.takeWhile import kotlinx.coroutines.isActive import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import org.junit.Assert +import org.junit.Rule import org.junit.Test import java.util.concurrent.CopyOnWriteArrayList -class JdwpProcessTrackerTest : AdbLibToolsTestBase() { +class JdwpProcessTrackerTest { + + @JvmField + @Rule + val fakeAdbRule = FakeAdbServerProviderRule { + installDefaultCommandHandlers() + setFeatures("push_sync") + } + + private val fakeAdb get() = fakeAdbRule.fakeAdb + private val hostServices get() = fakeAdbRule.adbSession.hostServices @Test fun testJdwpProcessTrackerWorks(): Unit = runBlockingWithTimeout { val deviceID = "1234" - val theOneFeatureSupported = "push_sync" - val features = setOf(theOneFeatureSupported) - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildWithFeatures(features).start()) val fakeDevice = fakeAdb.connectDevice( deviceID, @@ -50,8 +59,8 @@ class JdwpProcessTrackerTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) - val connectedDevice = waitForOnlineConnectedDevice(hostServices.session, fakeDevice.deviceId) + val connectedDevice = + waitForOnlineConnectedDevice(hostServices.session, fakeDevice.deviceId) val pid10 = 10 val pid11 = 11 @@ -123,6 +132,7 @@ class JdwpProcessTrackerTest : AdbLibToolsTestBase() { true } } + else -> { Assert.fail("Should not reach") false @@ -157,9 +167,6 @@ class JdwpProcessTrackerTest : AdbLibToolsTestBase() { @Test fun testJdwpProcessTrackerCollectsProcessProperties() = runBlockingWithTimeout { val deviceID = "1234" - val theOneFeatureSupported = "push_sync" - val features = setOf(theOneFeatureSupported) - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildWithFeatures(features).start()) val fakeDevice = fakeAdb.connectDevice( deviceID, @@ -170,8 +177,8 @@ class JdwpProcessTrackerTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) - val connectedDevice = waitForOnlineConnectedDevice(hostServices.session, fakeDevice.deviceId) + val connectedDevice = + waitForOnlineConnectedDevice(hostServices.session, fakeDevice.deviceId) val pid10 = 10 val pid11 = 11 fakeDevice.startClient(pid10, 100, "a.b.c", false) @@ -208,9 +215,6 @@ class JdwpProcessTrackerTest : AdbLibToolsTestBase() { @Test fun testJdwpProcessTrackerFlowStopsWhenDeviceDisconnects(): Unit = runBlockingWithTimeout { val deviceID = "1234" - val theOneFeatureSupported = "push_sync" - val features = setOf(theOneFeatureSupported) - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildWithFeatures(features).start()) val fakeDevice = fakeAdb.connectDevice( deviceID, @@ -221,8 +225,8 @@ class JdwpProcessTrackerTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) - val connectedDevice = waitForOnlineConnectedDevice(hostServices.session, fakeDevice.deviceId) + val connectedDevice = + waitForOnlineConnectedDevice(hostServices.session, fakeDevice.deviceId) val pid10 = 10 val pid11 = 11 @@ -251,9 +255,6 @@ class JdwpProcessTrackerTest : AdbLibToolsTestBase() { @Test fun testJdwpProcessTrackerFlowIsExceptionTransparent(): Unit = runBlockingWithTimeout { val deviceID = "1234" - val theOneFeatureSupported = "push_sync" - val features = setOf(theOneFeatureSupported) - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildWithFeatures(features).start()) val fakeDevice = fakeAdb.connectDevice( deviceID, @@ -264,30 +265,28 @@ class JdwpProcessTrackerTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) - val connectedDevice = waitForOnlineConnectedDevice(hostServices.session, fakeDevice.deviceId) + val connectedDevice = + waitForOnlineConnectedDevice(hostServices.session, fakeDevice.deviceId) val pid10 = 10 // Act - exceptionRule.expect(Exception::class.java) - exceptionRule.expectMessage("My Test Exception") - fakeDevice.startClient(pid10, 0, "a.b.c", false) - - val jdwpTracker = JdwpProcessTracker.create(connectedDevice) - jdwpTracker.processesFlow.collect { - throw Exception("My Test Exception") + val exception = Assert.assertThrows(Exception::class.java) { + fakeDevice.startClient(pid10, 0, "a.b.c", false) + val jdwpTracker = JdwpProcessTracker.create(connectedDevice) + runBlocking { + jdwpTracker.processesFlow.collect { + throw Exception("My Test Exception") + } + } } - // Assert (should not reach) - Assert.fail() + // Assert + Assert.assertEquals(exception.message, "My Test Exception") } @Test fun testJdwpProcessTrackerFlowICanBeCancelled(): Unit = runBlockingWithTimeout { val deviceID = "1234" - val theOneFeatureSupported = "push_sync" - val features = setOf(theOneFeatureSupported) - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildWithFeatures(features).start()) val fakeDevice = fakeAdb.connectDevice( deviceID, @@ -298,21 +297,22 @@ class JdwpProcessTrackerTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) - val connectedDevice = waitForOnlineConnectedDevice(hostServices.session, fakeDevice.deviceId) + val connectedDevice = + waitForOnlineConnectedDevice(hostServices.session, fakeDevice.deviceId) val pid10 = 10 // Act - exceptionRule.expect(CancellationException()::class.java) - exceptionRule.expectMessage("My Test Exception") - fakeDevice.startClient(pid10, 0, "a.b.c", false) - - val jdwpTracker = JdwpProcessTracker.create(connectedDevice) - jdwpTracker.processesFlow.collect { - cancel("My Test Exception") + val exception = Assert.assertThrows(CancellationException::class.java) { + fakeDevice.startClient(pid10, 0, "a.b.c", false) + val jdwpTracker = JdwpProcessTracker.create(connectedDevice) + runBlocking { + jdwpTracker.processesFlow.collect { + cancel("My Test Exception") + } + } } - // Assert (should not reach) - Assert.fail() + // Assert + Assert.assertEquals(exception.message, "My Test Exception") } } diff --git a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/AppProcessNameRetrieverTest.kt b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/AppProcessNameRetrieverTest.kt index 25a1656bc5..d7edf3528e 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/AppProcessNameRetrieverTest.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/AppProcessNameRetrieverTest.kt @@ -18,7 +18,6 @@ package com.android.adblib.tools.debugging.impl import com.android.adblib.connectedDevicesTracker import com.android.adblib.serialNumber import com.android.adblib.testingutils.CoroutineTestUtils -import com.android.adblib.testingutils.FakeAdbServerProvider import com.android.adblib.tools.debugging.AppProcessTracker import com.android.adblib.tools.testutils.AdbLibToolsTestBase import com.android.fakeadbserver.DeviceState @@ -34,7 +33,6 @@ class AppProcessNameRetrieverTest : AdbLibToolsTestBase() { fun retrieveProcessNameFromJdwpProcess(): Unit = CoroutineTestUtils.runBlockingWithTimeout { // Prepare val deviceId = "1234" - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( deviceId, @@ -45,7 +43,6 @@ class AppProcessNameRetrieverTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) val connectedDevice = hostServices.session.connectedDevicesTracker.connectedDevices .mapNotNull { connectedDevices -> @@ -71,7 +68,6 @@ class AppProcessNameRetrieverTest : AdbLibToolsTestBase() { fun retrieveProcessNameFromProc(): Unit = CoroutineTestUtils.runBlockingWithTimeout { // Prepare val deviceId = "1234" - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( deviceId, @@ -82,7 +78,6 @@ class AppProcessNameRetrieverTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) val connectedDevice = hostServices.session.connectedDevicesTracker.connectedDevices .mapNotNull { connectedDevices -> diff --git a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpProcessAllocationTrackerTest.kt b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpProcessAllocationTrackerTest.kt index d672abad7a..3b9cf3a9ca 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpProcessAllocationTrackerTest.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpProcessAllocationTrackerTest.kt @@ -22,6 +22,7 @@ import com.android.adblib.tools.debugging.packets.ddms.DdmsPacketConstants import com.android.adblib.tools.debugging.toByteBuffer import com.android.adblib.tools.testutils.AdbLibToolsTestBase import com.android.adblib.tools.testutils.FakeJdwpCommandProgress +import com.android.adblib.tools.testutils.waitForOnlineConnectedDevice import com.android.fakeadbserver.DeviceState import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue @@ -32,7 +33,6 @@ class JdwpProcessAllocationTrackerTest : AdbLibToolsTestBase() { @Test fun getEnabledStatus_returnsResult() = CoroutineTestUtils.runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val processAllocationTracker = createJdwpProcessAllocationTracker(fakeAdb) fakeAdb.device("1234").getClient(10)?.isAllocationTrackerEnabled = true @@ -50,7 +50,6 @@ class JdwpProcessAllocationTrackerTest : AdbLibToolsTestBase() { @Test fun setEnabledWorks() = CoroutineTestUtils.runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val processAllocationTracker = createJdwpProcessAllocationTracker(fakeAdb) // Act @@ -67,7 +66,6 @@ class JdwpProcessAllocationTrackerTest : AdbLibToolsTestBase() { @Test fun fetchAllocationDetailsReturnsResult() = CoroutineTestUtils.runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val processAllocationTracker = createJdwpProcessAllocationTracker(fakeAdb) val allocationDetails = "some data" fakeAdb.device("1234").getClient(10)?.allocationTrackerDetails = allocationDetails @@ -105,7 +103,6 @@ class JdwpProcessAllocationTrackerTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val session = createHostServices(fakeAdb).session val connectedDevice = waitForOnlineConnectedDevice(session, fakeDevice.deviceId) fakeDevice.startClient(10, 0, "a.b.c", false) val process = registerCloseable(JdwpProcessImpl(session, connectedDevice, 10)) diff --git a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpProcessProfilerTest.kt b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpProcessProfilerTest.kt index 852639349e..15e694e472 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpProcessProfilerTest.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpProcessProfilerTest.kt @@ -22,6 +22,7 @@ import com.android.adblib.tools.debugging.ProfilerStatus import com.android.adblib.tools.debugging.toByteArray import com.android.adblib.tools.testutils.AdbLibToolsTestBase import com.android.adblib.tools.testutils.FakeJdwpCommandProgress +import com.android.adblib.tools.testutils.waitForOnlineConnectedDevice import com.android.fakeadbserver.ClientState import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.ProfilerState @@ -37,7 +38,6 @@ class JdwpProcessProfilerTest : AdbLibToolsTestBase() { @Test fun queryStatusWorksForOff() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val profiler = createJdwpProcessProfiler(fakeAdb) fakeAdb.device("1234").client(10).profilerState.status = ProfilerState.Status.Off val progress = FakeJdwpCommandProgress() @@ -56,7 +56,6 @@ class JdwpProcessProfilerTest : AdbLibToolsTestBase() { @Test fun queryStatusWorksForInstrumentation() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val profiler = createJdwpProcessProfiler(fakeAdb) fakeAdb.device("1234").client(10).profilerState.status = ProfilerState.Status.Instrumentation @@ -71,7 +70,6 @@ class JdwpProcessProfilerTest : AdbLibToolsTestBase() { @Test fun queryStatusWorksForSampling() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val profiler = createJdwpProcessProfiler(fakeAdb) fakeAdb.device("1234").client(10).profilerState.status = ProfilerState.Status.Sampling @@ -85,7 +83,6 @@ class JdwpProcessProfilerTest : AdbLibToolsTestBase() { @Test fun startSampleProfilingWorks() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val profiler = createJdwpProcessProfiler(fakeAdb) val profilerState = fakeAdb.device("1234").client(10).profilerState val progress = FakeJdwpCommandProgress() @@ -113,7 +110,6 @@ class JdwpProcessProfilerTest : AdbLibToolsTestBase() { @Test fun stopSampleProfilingWorks() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val profiler = createJdwpProcessProfiler(fakeAdb) val samplingData = "This is a test".toByteArray(Charsets.UTF_8) val profilerState = fakeAdb.device("1234").client(10).profilerState @@ -139,7 +135,6 @@ class JdwpProcessProfilerTest : AdbLibToolsTestBase() { @Test fun startInstrumentationProfilingWorks() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val profiler = createJdwpProcessProfiler(fakeAdb) val profilerState = fakeAdb.device("1234").client(10).profilerState val progress = FakeJdwpCommandProgress() @@ -160,7 +155,6 @@ class JdwpProcessProfilerTest : AdbLibToolsTestBase() { @Test fun stopInstrumentationProfilingWorks() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val profiler = createJdwpProcessProfiler(fakeAdb) val instrumentationData = "This is a test".toByteArray(Charsets.UTF_8) val profilerState = fakeAdb.device("1234").client(10).profilerState @@ -195,7 +189,6 @@ class JdwpProcessProfilerTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val session = createHostServices(fakeAdb).session val connectedDevice = waitForOnlineConnectedDevice(session, fakeDevice.deviceId) fakeDevice.startClient(10, 0, "a.b.c", false) val process = registerCloseable(JdwpProcessImpl(session, connectedDevice, 10)) diff --git a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpProcessTest.kt b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpProcessTest.kt index cdb55a67f3..075c2ab300 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpProcessTest.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpProcessTest.kt @@ -30,6 +30,7 @@ import com.android.adblib.tools.debugging.packets.payloadLength import com.android.adblib.tools.debugging.properties import com.android.adblib.tools.debugging.toByteArray import com.android.adblib.tools.testutils.AdbLibToolsTestBase +import com.android.adblib.tools.testutils.waitForOnlineConnectedDevice import kotlinx.coroutines.delay import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map @@ -354,9 +355,7 @@ class JdwpProcessTest : AdbLibToolsTestBase() { deviceApi: Int = 30, waitForDebugger: Boolean = true ): Triple<FakeAdbServerProvider, ConnectedDevice, JdwpProcessImpl> { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, deviceApi) - val session = createSession(fakeAdb) val device = waitForOnlineConnectedDevice(session, fakeDevice.deviceId) fakeAdb.device(fakeDevice.deviceId).startClient(10, 2, "p1", "pkg", waitForDebugger) val process = registerCloseable(JdwpProcessImpl(session, device, 10)) diff --git a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpSessionProxyTest.kt b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpSessionProxyTest.kt index 7c259f33d4..658897004e 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpSessionProxyTest.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpSessionProxyTest.kt @@ -18,7 +18,6 @@ package com.android.adblib.tools.debugging.impl import com.android.adblib.ByteBufferAdbOutputChannel import com.android.adblib.testingutils.CoroutineTestUtils.runBlockingWithTimeout import com.android.adblib.testingutils.CoroutineTestUtils.yieldUntil -import com.android.adblib.testingutils.FakeAdbServerProvider import com.android.adblib.tools.debugging.JdwpSession import com.android.adblib.tools.debugging.packets.AdbBufferedInputChannel import com.android.adblib.tools.debugging.packets.JdwpCommands @@ -32,6 +31,7 @@ import com.android.adblib.tools.debugging.packets.ddms.MutableDdmsChunk import com.android.adblib.tools.debugging.packets.ddms.writeToChannel import com.android.adblib.tools.debugging.properties import com.android.adblib.tools.testutils.AdbLibToolsTestBase +import com.android.adblib.tools.testutils.waitForOnlineConnectedDevice import com.android.adblib.utils.ResizableBuffer import com.android.fakeadbserver.DeviceState import kotlinx.coroutines.async @@ -49,7 +49,6 @@ class JdwpSessionProxyTest : AdbLibToolsTestBase() { @Test fun socketAddressIsAssignedAutomatically() = runBlockingWithTimeout { val deviceID = "1234" - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( deviceID, @@ -60,7 +59,6 @@ class JdwpSessionProxyTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val session = createHostServices(fakeAdb).session val connectedDevice = waitForOnlineConnectedDevice(session, fakeDevice.deviceId) fakeDevice.startClient(10, 0, "a.b.c", false) @@ -131,7 +129,6 @@ class JdwpSessionProxyTest : AdbLibToolsTestBase() { private suspend fun createJdwpProxySession(): JdwpSession { val deviceID = "1234" - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( deviceID, @@ -142,7 +139,6 @@ class JdwpSessionProxyTest : AdbLibToolsTestBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val session = createHostServices(fakeAdb).session val connectedDevice = waitForOnlineConnectedDevice(session, fakeDevice.deviceId) fakeDevice.startClient(10, 0, "a.b.c", false) diff --git a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpSessionTest.kt b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpSessionTest.kt index 1c95ad30f2..2f363cd4e9 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpSessionTest.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/JdwpSessionTest.kt @@ -19,7 +19,6 @@ import com.android.adblib.ByteBufferAdbOutputChannel import com.android.adblib.skipRemaining import com.android.adblib.testingutils.CoroutineTestUtils.runBlockingWithTimeout import com.android.adblib.testingutils.CoroutineTestUtils.waitNonNull -import com.android.adblib.testingutils.FakeAdbServerProvider import com.android.adblib.tools.debugging.JdwpSession import com.android.adblib.tools.debugging.packets.AdbBufferedInputChannel import com.android.adblib.tools.debugging.packets.JdwpPacketView @@ -33,6 +32,7 @@ import com.android.adblib.tools.debugging.packets.ddms.ddmsChunks import com.android.adblib.tools.debugging.packets.ddms.isDdmsCommand import com.android.adblib.tools.debugging.packets.ddms.writeToChannel import com.android.adblib.tools.testutils.AdbLibToolsTestBase +import com.android.adblib.tools.testutils.waitForOnlineConnectedDevice import com.android.adblib.utils.ResizableBuffer import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -47,9 +47,7 @@ class JdwpSessionTest : AdbLibToolsTestBase() { @Test fun nextPacketIdIsThreadSafe() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val connectedDevice = waitForOnlineConnectedDevice(session, fakeDevice.deviceId) @@ -75,9 +73,7 @@ class JdwpSessionTest : AdbLibToolsTestBase() { @Test fun nextPacketIdThrowsIfNotSupported() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val connectedDevice = waitForOnlineConnectedDevice(session, fakeDevice.deviceId) val jdwpSession = registerCloseable(JdwpSession.openJdwpSession(connectedDevice, 10, null)) @@ -92,9 +88,7 @@ class JdwpSessionTest : AdbLibToolsTestBase() { @Test fun sendAndReceivePacketWorks() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val connectedDevice = waitForOnlineConnectedDevice(session, fakeDevice.deviceId) @@ -114,9 +108,7 @@ class JdwpSessionTest : AdbLibToolsTestBase() { @Test fun receivePacketRewindsTheCorrectPayload() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val connectedDevice = waitForOnlineConnectedDevice(session, fakeDevice.deviceId) @@ -142,9 +134,7 @@ class JdwpSessionTest : AdbLibToolsTestBase() { @Test fun receivePacketThrowsEofOnClientTerminate() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val connectedDevice = waitForOnlineConnectedDevice(session, fakeDevice.deviceId) @@ -168,9 +158,7 @@ class JdwpSessionTest : AdbLibToolsTestBase() { @Test fun receivePacketThrowsEofConsistentlyOnClientTerminate() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val connectedDevice = waitForOnlineConnectedDevice(session, fakeDevice.deviceId) @@ -191,9 +179,7 @@ class JdwpSessionTest : AdbLibToolsTestBase() { @Test fun sendPacketThrowExceptionAfterShutdown() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val connectedDevice = waitForOnlineConnectedDevice(session, fakeDevice.deviceId) val jdwpSession = registerCloseable(JdwpSession.openJdwpSession(connectedDevice, 10, 100)) @@ -211,9 +197,7 @@ class JdwpSessionTest : AdbLibToolsTestBase() { @Test fun receivePacketThrowExceptionAfterShutdown() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val connectedDevice = waitForOnlineConnectedDevice(session, fakeDevice.deviceId) val jdwpSession = registerCloseable(JdwpSession.openJdwpSession(connectedDevice, 10, 100)) diff --git a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/SharedJdwpSessionTest.kt b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/SharedJdwpSessionTest.kt index af78e1f045..884221fa63 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/SharedJdwpSessionTest.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/SharedJdwpSessionTest.kt @@ -20,7 +20,6 @@ import com.android.adblib.ByteBufferAdbOutputChannel import com.android.adblib.skipRemaining import com.android.adblib.testingutils.CoroutineTestUtils.runBlockingWithTimeout import com.android.adblib.testingutils.CoroutineTestUtils.yieldUntil -import com.android.adblib.testingutils.FakeAdbServerProvider import com.android.adblib.tools.debugging.DdmsCommandException import com.android.adblib.tools.debugging.DdmsProtocolKind import com.android.adblib.tools.debugging.JdwpSession @@ -46,6 +45,7 @@ import com.android.adblib.tools.debugging.sendDdmsExit import com.android.adblib.tools.debugging.sendVmExit import com.android.adblib.tools.testutils.AdbLibToolsTestBase import com.android.adblib.tools.testutils.FakeJdwpCommandProgress +import com.android.adblib.tools.testutils.waitForOnlineConnectedDevice import com.android.adblib.utils.ResizableBuffer import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CompletableDeferred @@ -73,9 +73,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun nextPacketIdIsThreadSafe() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) // Act @@ -100,9 +98,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun sendPacketWithActiveReceiverWorks() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val jdwpSession = openSharedJdwpSession(session, fakeDevice.deviceId, 10) val ready = MutableStateFlow(false) @@ -130,9 +126,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun receiverFlowIsTransparentToExceptions(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val jdwpSession = openSharedJdwpSession(session, fakeDevice.deviceId, 10) @@ -155,9 +149,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun receiverFlowCanBeCancelled(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val jdwpSession = openSharedJdwpSession(session, fakeDevice.deviceId, 10) @@ -181,9 +173,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun receiversCollectionIsSerialized(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val receiverCount = 10 val jdwpSession = openSharedJdwpSession(session, fakeDevice.deviceId, 10) @@ -224,9 +214,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun receiversActivationsAreNotSerialized(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val receiverCount = 10 val jdwpSession = openSharedJdwpSession(session, fakeDevice.deviceId, 10) @@ -262,9 +250,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun receiverActivationIsNotExecutedIfNoCollection(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val receiverCount = 10 val jdwpSession = openSharedJdwpSession(session, fakeDevice.deviceId, 10) @@ -296,9 +282,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun receivePacketsFlowEndsOnClientTerminate() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) // Act @@ -322,9 +306,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun receivePacketsFlowEndsConsistentlyOnClientTerminate() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) // Act @@ -354,9 +336,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun sendPacketThrowExceptionAfterClose() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val jdwpSession = openSharedJdwpSession(session, fakeDevice.deviceId, 10) val packet = createHeloDdmsPacket(jdwpSession) @@ -373,9 +353,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun receivePacketThrowExceptionAfterClose() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val jdwpSession = openSharedJdwpSession(session, fakeDevice.deviceId, 10) val packet = createHeloDdmsPacket(jdwpSession) @@ -399,9 +377,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun receivePacketFlowContainsReplayPackets() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) // Act @@ -442,9 +418,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun addReplayPacketDoesCloneJdwpPacket() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) // Act @@ -463,9 +437,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun sendVmExitPacketWorks() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) // Act @@ -478,14 +450,13 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun sendDdmsExitPacketWorks() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) // Act - val jdwpSession = openSharedJdwpSession(session, fakeDevice.deviceId, 10) - jdwpSession.sendDdmsExit(1) + openSharedJdwpSession(session, fakeDevice.deviceId, 10).use { jdwpSession -> + jdwpSession.sendDdmsExit(1) + } // Assert: Wait until client process is gone yieldUntil { fakeDevice.getClient(10) == null } @@ -493,9 +464,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun sendDdmsHpgcPacketWorks() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) val client = fakeDevice.startClient(10, 0, "a.b.c", false) // Act @@ -504,7 +473,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { jdwpSession.handleDdmsHPGC(jdwpCommandProgress) assertEquals(DdmsProtocolKind.EmptyRepliesDiscarded, jdwpSession.device.ddmsProtocolKind()) - assertEquals(1, client.hgpcRequestsCount) + assertEquals(1, client.getHgpcRequestsCount()) assertTrue(jdwpCommandProgress.beforeSendIsCalled) assertTrue(jdwpCommandProgress.afterSendIsCalled) assertTrue(jdwpCommandProgress.onReplyTimeoutIsCalled) @@ -513,9 +482,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun sendDdmsHpgcPacketOnPreApi28DeviceWorks() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 27) - val session = createSession(fakeAdb) val client = fakeDevice.startClient(10, 0, "a.b.c", false) // Act @@ -524,7 +491,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { jdwpSession.handleDdmsHPGC(jdwpCommandProgress) assertEquals(DdmsProtocolKind.EmptyRepliesAllowed, jdwpSession.device.ddmsProtocolKind()) - assertEquals(1, client.hgpcRequestsCount) + assertEquals(1, client.getHgpcRequestsCount()) assertTrue(jdwpCommandProgress.beforeSendIsCalled) assertTrue(jdwpCommandProgress.afterSendIsCalled) assertFalse(jdwpCommandProgress.onReplyTimeoutIsCalled) @@ -533,9 +500,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun handleInvalidDdmsCommandThrows() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) // Act @@ -553,9 +518,7 @@ class SharedJdwpSessionTest : AdbLibToolsTestBase() { @Test fun sharedJdwpSessionMonitorAreInvokedIfRegistered(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) val testJdwpSessionMonitorFactory = TestJdwpSessionMonitorFactory() session.addSharedJdwpSessionMonitorFactory(testJdwpSessionMonitorFactory) diff --git a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/SharedJdwpSessionUtilsTest.kt b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/SharedJdwpSessionUtilsTest.kt index 75b484bc66..cde5e5c52f 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/SharedJdwpSessionUtilsTest.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/debugging/impl/SharedJdwpSessionUtilsTest.kt @@ -18,7 +18,6 @@ package com.android.adblib.tools.debugging.impl import com.android.adblib.AdbSession import com.android.adblib.property import com.android.adblib.testingutils.CoroutineTestUtils.runBlockingWithTimeout -import com.android.adblib.testingutils.FakeAdbServerProvider import com.android.adblib.tools.AdbLibToolsProperties.DDMS_REPLY_WAIT_TIMEOUT import com.android.adblib.tools.debugging.DdmsProtocolKind import com.android.adblib.tools.debugging.JdwpSession @@ -29,6 +28,7 @@ import com.android.adblib.tools.debugging.handleDdmsCommandAndReplyProtocol import com.android.adblib.tools.debugging.withTimeoutAfterSignal import com.android.adblib.tools.testutils.AdbLibToolsTestBase import com.android.adblib.tools.testutils.FakeJdwpCommandProgress +import com.android.adblib.tools.testutils.waitForOnlineConnectedDevice import kotlinx.coroutines.CancellationException import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.cancel @@ -137,10 +137,8 @@ class SharedJdwpSessionUtilsTest : AdbLibToolsTestBase() { @Test fun handleDdmsCommandWithEmptyReplyWithEmptyRepliesAllowed_doesNotTimeOut() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) // Api 27 maps to DdmsProtocolKind.EmptyRepliesAllowed val fakeDevice = addFakeDevice(fakeAdb, 27) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) // Act @@ -148,7 +146,10 @@ class SharedJdwpSessionUtilsTest : AdbLibToolsTestBase() { val jdwpCommandProgress = FakeJdwpCommandProgress() val result = jdwpSession.handleDdmsCommandAndReplyProtocol(jdwpCommandProgress) { signal: Signal<Long> -> - signalAndWait(session.property(DDMS_REPLY_WAIT_TIMEOUT).toMillis() + 100, signal) { 101L } + signalAndWait( + session.property(DDMS_REPLY_WAIT_TIMEOUT).toMillis() + 100, + signal + ) { 101L } } assertEquals( @@ -164,10 +165,8 @@ class SharedJdwpSessionUtilsTest : AdbLibToolsTestBase() { @Test fun handleDdmsCommandWithEmptyReplyWithEmptyRepliesAllowed_canHandleExceptionAfterSignal() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) // Api 27 maps to DdmsProtocolKind.EmptyRepliesAllowed val fakeDevice = addFakeDevice(fakeAdb, 27) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) // Act @@ -191,9 +190,7 @@ class SharedJdwpSessionUtilsTest : AdbLibToolsTestBase() { @Test fun handleDdmsCommandWithEmptyReplyWithEmptyRepliesDiscarded_returnsResultBeforeTimeout() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) // Act @@ -217,9 +214,7 @@ class SharedJdwpSessionUtilsTest : AdbLibToolsTestBase() { @Test fun handleDdmsCommandWithEmptyReplyWithEmptyRepliesDiscarded_returnsResultOnTimeout() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) // Act @@ -241,9 +236,7 @@ class SharedJdwpSessionUtilsTest : AdbLibToolsTestBase() { @Test fun handleDdmsCommandWithEmptyReplyWithEmptyRepliesDiscarded_canHandleExceptionAfterSignal() = runBlockingWithTimeout { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val session = createSession(fakeAdb) fakeDevice.startClient(10, 0, "a.b.c", false) // Act diff --git a/adblib-tools/test/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkViewTest.kt b/adblib-tools/test/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkViewTest.kt index d79c8a316c..69c1313cea 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkViewTest.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/debugging/packets/ddms/DdmsChunkViewTest.kt @@ -153,7 +153,7 @@ class DdmsChunkViewTest : AdbLibToolsTestBase() { } private fun createTestDdmsChunk( - chunkType: Int = DdmsChunkTypes.REAQ, + chunkType: DdmsChunkTypes = DdmsChunkTypes.REAQ, bytes: List<Int> = listOf(128, 0, 255, 10) ): DdmsChunkView { val ddmsChunk = MutableDdmsChunk() diff --git a/adblib-tools/test/src/com/android/adblib/tools/debugging/utils/ReferenceCountedResourceTest.kt b/adblib-tools/test/src/com/android/adblib/tools/debugging/utils/ReferenceCountedResourceTest.kt index 51b76216da..12a3a4860b 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/debugging/utils/ReferenceCountedResourceTest.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/debugging/utils/ReferenceCountedResourceTest.kt @@ -17,7 +17,6 @@ package com.android.adblib.tools.debugging.utils import com.android.adblib.AutoShutdown import com.android.adblib.testingutils.CoroutineTestUtils.runBlockingWithTimeout -import com.android.adblib.testingutils.FakeAdbServerProvider import com.android.adblib.tools.testutils.AdbLibToolsTestBase import kotlinx.coroutines.Job import kotlinx.coroutines.delay @@ -33,8 +32,6 @@ class ReferenceCountedResourceTest : AdbLibToolsTestBase() { @Test fun testUnderlyingResourceIsNotCreatedRightAway() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val session = createSession(fakeAdb) val res = MyTestResource() /*val ref = */ReferenceCountedResource(session) { res.creationCount.incrementAndGet() @@ -50,8 +47,6 @@ class ReferenceCountedResourceTest : AdbLibToolsTestBase() { @Test fun testUnderlyingResourceIsCreatedLazily() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val session = createSession(fakeAdb) val res = MyTestResource() val ref = ReferenceCountedResource(session) { res.creationCount.incrementAndGet() @@ -70,8 +65,6 @@ class ReferenceCountedResourceTest : AdbLibToolsTestBase() { @Test fun testUnderlyingResourceIsShutDownOnRelease() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val session = createSession(fakeAdb) val res = MyTestResource() val ref = ReferenceCountedResource(session) { res.creationCount.incrementAndGet() @@ -91,8 +84,6 @@ class ReferenceCountedResourceTest : AdbLibToolsTestBase() { @Test fun testUnderlyingResourceIsClosedOnClose() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val session = createSession(fakeAdb) val res = MyTestResource() val ref = ReferenceCountedResource(session) { res.creationCount.incrementAndGet() @@ -112,8 +103,6 @@ class ReferenceCountedResourceTest : AdbLibToolsTestBase() { @Test fun testUnderlyingResourceIsCreatedOnlyOnce() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val session = createSession(fakeAdb) val res = MyTestResource() val ref = ReferenceCountedResource(session) { res.creationCount.incrementAndGet() @@ -133,8 +122,6 @@ class ReferenceCountedResourceTest : AdbLibToolsTestBase() { @Test fun testUnderlyingResourceIsCreatedOnlyOnceFromConcurrentThreads() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val session = createSession(fakeAdb) val res = MyTestResource() val ref = ReferenceCountedResource(session) { res.creationCount.incrementAndGet() @@ -165,8 +152,6 @@ class ReferenceCountedResourceTest : AdbLibToolsTestBase() { @Test fun testUnderlyingResourceIsClosedFromConcurrentThreads() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val session = createSession(fakeAdb) val res = MyTestResource() val ref = ReferenceCountedResource(session) { res.creationCount.incrementAndGet() @@ -194,8 +179,6 @@ class ReferenceCountedResourceTest : AdbLibToolsTestBase() { @Test fun testUnderlyingResourceIsCreatedOnlyOnceEvenIfDelayed() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val session = createSession(fakeAdb) val res = MyTestResource() val ref = ReferenceCountedResource(session) { delay(100) @@ -215,8 +198,6 @@ class ReferenceCountedResourceTest : AdbLibToolsTestBase() { @Test fun testUnderlyingResourceCreationIsCancelledIfRefIsClosedEarly() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val session = createSession(fakeAdb) val res = MyTestResource() val ref = ReferenceCountedResource(session) { delay(10_000) diff --git a/adblib-tools/test/src/com/android/adblib/tools/tests/TestAdbHostServicesExt.kt b/adblib-tools/test/src/com/android/adblib/tools/tests/TestAdbHostServicesExt.kt index acd58a8b1f..ddf2c98c2a 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/tests/TestAdbHostServicesExt.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/tests/TestAdbHostServicesExt.kt @@ -16,25 +16,30 @@ package com.android.adblib.tools.tests import com.android.adblib.DeviceSelector -import com.android.adblib.testingutils.FakeAdbServerProvider +import com.android.adblib.testingutils.FakeAdbServerProviderRule import com.android.adblib.tools.availableFeatures import com.android.fakeadbserver.DeviceState import kotlinx.coroutines.runBlocking import org.junit.Assert +import org.junit.Rule import org.junit.Test -class TestAdbHostServicesExt: TestInstallBase() { +class TestAdbHostServicesExt { + + @JvmField + @Rule + val fakeAdbRule = FakeAdbServerProviderRule { + installDefaultCommandHandlers() + setFeatures("push_sync") + } // Test that an older host, supporting a subset of the device features, actually only exposes // the common set of features. @Test fun testFeaturesWithLimitedHost() { val deviceID = "1234" - val theOneFeatureSupported = "push_sync" - val features = setOf(theOneFeatureSupported) - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildWithFeatures(features).start()) val fakeDevice = - fakeAdb.connectDevice( + fakeAdbRule.fakeAdb.connectDevice( deviceID, "test1", "test2", @@ -43,20 +48,19 @@ class TestAdbHostServicesExt: TestInstallBase() { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val availableFeaturesList = runBlocking { - hostServices.availableFeatures(DeviceSelector.fromSerialNumber(deviceID)) + fakeAdbRule.adbSession.hostServices.availableFeatures(DeviceSelector.fromSerialNumber(deviceID)) } val hostFeaturesList = runBlocking { - hostServices.hostFeatures() + fakeAdbRule.adbSession.hostServices.hostFeatures() } // Assert Assert.assertTrue(hostFeaturesList.size == 1) Assert.assertTrue(availableFeaturesList.size == 1) - Assert.assertTrue(availableFeaturesList.contains(theOneFeatureSupported)) + Assert.assertTrue(availableFeaturesList.contains("push_sync")) } } diff --git a/adblib-tools/test/src/com/android/adblib/tools/tests/TestInstall.kt b/adblib-tools/test/src/com/android/adblib/tools/tests/TestInstall.kt index 3cd9ce5f60..f8b1d39943 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/tests/TestInstall.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/tests/TestInstall.kt @@ -16,7 +16,6 @@ package com.android.adblib.tools.tests import com.android.adblib.DeviceSelector -import com.android.adblib.testingutils.FakeAdbServerProvider import com.android.adblib.tools.INSTALL_APK_STAGING import com.android.adblib.tools.InstallException import com.android.adblib.tools.PMAbb @@ -36,9 +35,7 @@ class TestInstall : TestInstallBase() { @Test fun testInstallSuccess() { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) runBlocking { @@ -48,9 +45,7 @@ class TestInstall : TestInstallBase() { @Test fun testInstallCommFailure() { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 29) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) runBlocking { @@ -68,9 +63,7 @@ class TestInstall : TestInstallBase() { @Test fun testInstallBadParameterFailureCommit() { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) runBlocking { @@ -105,9 +98,7 @@ class TestInstall : TestInstallBase() { // Use API = 20, when streaming and multi-apk was not supported. @Test fun testLegacyStrategyMultipleApksFail() { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 20) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val apk1 = Files.createTempFile("adblib-tools_test.apk", null) @@ -126,9 +117,7 @@ class TestInstall : TestInstallBase() { // Use API = 20, when streaming and multi-apk was not supported. this should be a remote install. @Test fun testLegacyStrategy() { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 20) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val apk = Files.createTempFile("adblib-tools_test.apk", null) @@ -143,9 +132,7 @@ class TestInstall : TestInstallBase() { // Use API = 23, just before CMD was introduced. This should use PM binary. @Test fun testPmStrategy() { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 23) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) runBlocking { @@ -160,9 +147,7 @@ class TestInstall : TestInstallBase() { // Use API = 24, just when CMD was introduced. @Test fun testCmdStrategy() { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 24) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) runBlocking { @@ -177,9 +162,7 @@ class TestInstall : TestInstallBase() { // Use API = 29, just before ABB was introduced. This should be using CMD. @Test fun testCmdBeforeAbbStrategy() { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 29) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) runBlocking { @@ -194,9 +177,7 @@ class TestInstall : TestInstallBase() { // Use API = 30 which should have ABB and ABB_EXEC @Test fun testAbbStrategy() { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) runBlocking { diff --git a/adblib-tools/test/src/com/android/adblib/tools/tests/TestUninstall.kt b/adblib-tools/test/src/com/android/adblib/tools/tests/TestUninstall.kt index 738ff9673a..587398765b 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/tests/TestUninstall.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/tests/TestUninstall.kt @@ -17,7 +17,6 @@ package com.android.adblib.tools.tests import com.android.adblib.DeviceSelector -import com.android.adblib.testingutils.FakeAdbServerProvider import com.android.adblib.tools.UninstallResult import com.android.adblib.tools.uninstall import com.android.fakeadbserver.shellcommandhandlers.ShellConstants @@ -29,9 +28,7 @@ class TestUninstall : TestInstallBase() { @Test fun testUninstallSuccess() { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) var r : UninstallResult @@ -44,9 +41,7 @@ class TestUninstall : TestInstallBase() { @Test fun testUninstallFailure() { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) var r : UninstallResult @@ -59,9 +54,7 @@ class TestUninstall : TestInstallBase() { @Test fun testUninstallOptions() { - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb, 30) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val options = listOf("-myOptions", "-r", "-t") val applicationID = "foo.bar" diff --git a/adblib-tools/test/src/com/android/adblib/tools/testutils/AdbLibToolsTestBase.kt b/adblib-tools/test/src/com/android/adblib/tools/testutils/AdbLibToolsTestBase.kt index 25060a536b..0d45f74565 100644 --- a/adblib-tools/test/src/com/android/adblib/tools/testutils/AdbLibToolsTestBase.kt +++ b/adblib-tools/test/src/com/android/adblib/tools/testutils/AdbLibToolsTestBase.kt @@ -17,8 +17,6 @@ package com.android.adblib.tools.testutils import com.android.adblib.AdbChannel import com.android.adblib.AdbChannelProvider -import com.android.adblib.AdbDeviceServices -import com.android.adblib.AdbHostServices import com.android.adblib.AdbSession import com.android.adblib.AdbSessionHost import com.android.adblib.ConnectedDevice @@ -28,8 +26,10 @@ import com.android.adblib.isOnline import com.android.adblib.serialNumber import com.android.adblib.testingutils.CloseablesRule import com.android.adblib.testingutils.FakeAdbServerProvider +import com.android.adblib.testingutils.FakeAdbServerProviderRule import com.android.adblib.testingutils.TestingAdbSessionHost import com.android.fakeadbserver.DeviceState +import com.android.fakeadbserver.devicecommandhandlers.SyncCommandHandler import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.mapNotNull import org.hamcrest.CoreMatchers @@ -43,6 +43,18 @@ open class AdbLibToolsTestBase { @JvmField @Rule + val fakeAdbRule = FakeAdbServerProviderRule { + installDefaultCommandHandlers() + installDeviceHandler(SyncCommandHandler()) + } + + protected val fakeAdb get() = fakeAdbRule.fakeAdb + protected val session get() = fakeAdbRule.adbSession + protected val hostServices get() = session.hostServices + protected val deviceServices get() = session.deviceServices + + @JvmField + @Rule val closeables = CloseablesRule() @JvmField @@ -53,16 +65,6 @@ open class AdbLibToolsTestBase { return closeables.register(item) } - protected fun createSession(fakeAdb: FakeAdbServerProvider): AdbSession { - val host = registerCloseable(TestingAdbSessionHost()) - val channelProvider = fakeAdb.createChannelProvider(host) - return registerCloseable(AdbSession.create( - host, - channelProvider, - Duration.ofMillis(SOCKET_CONNECT_TIMEOUT_MS) - )) - } - protected fun createDisconnectedSession(): AdbSession { val host = registerCloseable(TestingAdbSessionHost()) val channelProvider = object: AdbChannelProvider { @@ -77,14 +79,6 @@ open class AdbLibToolsTestBase { )) } - protected fun createDeviceServices(fakeAdb: FakeAdbServerProvider): AdbDeviceServices { - return createSession(fakeAdb).deviceServices - } - - protected fun createHostServices(fakeAdb: FakeAdbServerProvider): AdbHostServices { - return createSession(fakeAdb).hostServices - } - protected fun addFakeDevice(fakeAdb: FakeAdbServerProvider, api: Int): DeviceState { val fakeDevice = fakeAdb.connectDevice( @@ -103,18 +97,6 @@ open class AdbLibToolsTestBase { (host as TestingAdbSessionHost).setPropertyValue(property, value) } - protected suspend fun waitForOnlineConnectedDevice( - session: AdbSession, - serialNumber: String - ): ConnectedDevice { - return session.connectedDevicesTracker.connectedDevices - .mapNotNull { connectedDevices -> - connectedDevices.firstOrNull { device -> - device.isOnline && device.serialNumber == serialNumber - } - }.first() - } - protected inline fun <reified T> assertThrows(block: () -> Unit) { try { block() @@ -125,3 +107,15 @@ open class AdbLibToolsTestBase { Assert.fail("Expected: An exception instance of ${T::class}, but got no exception instead") } } + +internal suspend fun waitForOnlineConnectedDevice( + session: AdbSession, + serialNumber: String +): ConnectedDevice { + return session.connectedDevicesTracker.connectedDevices + .mapNotNull { connectedDevices -> + connectedDevices.firstOrNull { device -> + device.isOnline && device.serialNumber == serialNumber + } + }.first() +} diff --git a/adblib/src/com/android/adblib/testing/FakeAdbSession.kt b/adblib/src/com/android/adblib/testing/FakeAdbSession.kt index f3f0c98d49..2ed3b34d07 100644 --- a/adblib/src/com/android/adblib/testing/FakeAdbSession.kt +++ b/adblib/src/com/android/adblib/testing/FakeAdbSession.kt @@ -24,6 +24,7 @@ import com.android.adblib.impl.channels.AdbChannelFactoryImpl import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.cancel /** * A fake implementation of [FakeAdbSession] for tests. @@ -48,5 +49,6 @@ class FakeAdbSession : AdbSession { override fun close() { (cache as CoroutineScopeCacheImpl).close() + scope.cancel("adblib session has been cancelled") } } diff --git a/adblib/test/src/com/android/adblib/AdbDeviceServicesTest.kt b/adblib/test/src/com/android/adblib/AdbDeviceServicesTest.kt index a20a397d60..fa0dbb846b 100644 --- a/adblib/test/src/com/android/adblib/AdbDeviceServicesTest.kt +++ b/adblib/test/src/com/android/adblib/AdbDeviceServicesTest.kt @@ -18,10 +18,10 @@ package com.android.adblib import com.android.adblib.impl.channels.AdbInputChannelReader import com.android.adblib.impl.channels.AdbInputStreamChannel import com.android.adblib.impl.channels.AdbOutputStreamChannel -import com.android.adblib.testingutils.CloseablesRule import com.android.adblib.testingutils.CoroutineTestUtils.runBlockingWithTimeout import com.android.adblib.testingutils.CoroutineTestUtils.yieldUntil import com.android.adblib.testingutils.FakeAdbServerProvider +import com.android.adblib.testingutils.FakeAdbServerProviderRule import com.android.adblib.testingutils.TestingAdbSessionHost import com.android.adblib.testingutils.TimeWaitSocketsThrottler import com.android.adblib.testingutils.asAdbInputChannel @@ -72,22 +72,22 @@ class AdbDeviceServicesTest { @JvmField @Rule - val closeables = CloseablesRule() + var exceptionRule: ExpectedException = ExpectedException.none() @JvmField @Rule - var exceptionRule: ExpectedException = ExpectedException.none() - - private fun <T : AutoCloseable> registerCloseable(item: T): T { - return closeables.register(item) + val fakeAdbRule = FakeAdbServerProviderRule { + installDefaultCommandHandlers() + installDeviceHandler(SyncCommandHandler()) } + private val fakeAdb get() = fakeAdbRule.fakeAdb + private val deviceServices get() = fakeAdbRule.adbSession.deviceServices + @Test fun testShell(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) val collector = ByteBufferShellCollector() @@ -114,9 +114,7 @@ class AdbDeviceServicesTest { @Test fun testShellAllowsNonAscii(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) val collector = TextShellCollector() @@ -131,9 +129,7 @@ class AdbDeviceServicesTest { @Test fun testShellCanStripCrLf(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb, 23) // older device to force \r\n newlines - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) val collector = ByteBufferShellCollector() @@ -160,9 +156,7 @@ class AdbDeviceServicesTest { @Test fun testShellCanKeepCrLf(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb, 23) // older device to force \r\n newlines - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) val collector = ByteBufferShellCollector() @@ -189,9 +183,7 @@ class AdbDeviceServicesTest { @Test fun testShellToText(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) // Act @@ -218,9 +210,7 @@ class AdbDeviceServicesTest { @Test fun testShellToLines(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) // Act @@ -249,9 +239,7 @@ class AdbDeviceServicesTest { @Test fun testShellWithArguments(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) // Act @@ -270,9 +258,7 @@ class AdbDeviceServicesTest { @Test fun testShellWithTimeout() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) val collector = ByteBufferShellCollector() @@ -295,9 +281,7 @@ class AdbDeviceServicesTest { @Test fun testShellWithStdin(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val input = """ This is some text with @@ -325,9 +309,7 @@ class AdbDeviceServicesTest { @Test fun testShellWithNoShutdownOutput(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val input = "foo" @@ -354,9 +336,7 @@ class AdbDeviceServicesTest { @Test fun testShellWithLargeInputAndSmallBufferSize(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) // To ensure we don't spam the log during this test deviceServices.session.host.setTestLoggerMinLevel( deviceServices.session.host.logger.minLevel.coerceAtLeast(AdbLogger.Level.INFO) @@ -391,9 +371,7 @@ class AdbDeviceServicesTest { @Test fun testShellWithErroneousStdinMaintainsInitialException(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val errorInputChannel = object : AdbInputChannel { private var firstCall = true @@ -429,9 +407,7 @@ class AdbDeviceServicesTest { @Test fun testShellWithCancelledStdinMaintainsCancellation() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val errorInputChannel = object : AdbInputChannel { private var firstCall = true @@ -481,9 +457,7 @@ class AdbDeviceServicesTest { @Test fun testShellStdinIsForwardedConcurrentlyWithStdout(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) // Channel used to coordinate our custom AdbInputChannel and consuming the flow @@ -554,9 +528,7 @@ class AdbDeviceServicesTest { @Test fun testShellWithMonitoringCanDetectInactiveCommand(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val slowInputChannel = object : AdbInputChannel { var firstCall = true @@ -595,9 +567,7 @@ class AdbDeviceServicesTest { @Test fun testShellWithMonitoringWorksAsLongAsTimeoutIsNotExceeded(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val slowInputChannel = object : AdbInputChannel { var callCount = 0 @@ -636,9 +606,7 @@ class AdbDeviceServicesTest { @Test fun testExec(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) val collector = ByteBufferShellCollector() @@ -665,9 +633,7 @@ class AdbDeviceServicesTest { @Test fun testShellV2Works(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) val collector = ShellV2ResultCollector() @@ -699,9 +665,7 @@ class AdbDeviceServicesTest { @Test fun testShellV2SplitsShellPackets(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) val collector = ShellV2ResultCollector() val input = """ @@ -752,9 +716,7 @@ class AdbDeviceServicesTest { @Test fun testShellV2WithErroneousStdinMaintainsInitialException(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val errorInputChannel = object : AdbInputChannel { private var firstCall = true @@ -790,9 +752,7 @@ class AdbDeviceServicesTest { @Test fun testShellV2WithCancelledStdinMaintainsCancellation(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val errorInputChannel = object : AdbInputChannel { private var firstCall = true @@ -829,9 +789,7 @@ class AdbDeviceServicesTest { @Test fun testShellAsTextWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val input = """ stdout: This is some text with @@ -873,9 +831,7 @@ class AdbDeviceServicesTest { @Test fun testShellV2AsLineWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val input = """ stdout: This is some text with @@ -926,9 +882,7 @@ class AdbDeviceServicesTest { @Test fun testShellInputChannelCollectorWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val input = """ stdout: This is some text with @@ -994,9 +948,7 @@ class AdbDeviceServicesTest { @Test fun testShellInputChannelCollectorUseWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val input = """ stdout: This is some text with @@ -1065,9 +1017,7 @@ class AdbDeviceServicesTest { @Test fun testShellCommandExecuteSingleOutputIsTransparentToExceptions(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val input = """ stdout: This is some text with @@ -1118,9 +1068,7 @@ class AdbDeviceServicesTest { @Test fun testShellCommandExecuteSingleOutputIsTransparentToExceptionsInStdoutReader(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val input = """ stdout: This is some text with @@ -1155,9 +1103,7 @@ class AdbDeviceServicesTest { @Test fun testShellCommandExecuteSingleOutputIsTransparentToExceptionsInStderrReader(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val input = """ stdout: This is some text with @@ -1192,9 +1138,7 @@ class AdbDeviceServicesTest { @Test fun testShellCommandExecuteSingleOutputAllowsCancellation(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val input = """ stdout: This is some text with @@ -1247,9 +1191,7 @@ class AdbDeviceServicesTest { @Test fun testShellCommandExecuteSingleOutputAllowsCancellationInStdoutReader(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val input = """ stdout: This is some text with @@ -1287,9 +1229,7 @@ class AdbDeviceServicesTest { @Test fun testShellCommandExecuteSingleOutputAllowsCancellationInStderrReader(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val input = """ stdout: This is some text with @@ -1325,10 +1265,8 @@ class AdbDeviceServicesTest { @Test fun testShellCommandUsesLegacyExecIfSupported(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) // "exec" is supported starting API 21 val fakeDevice = addFakeDevice(fakeAdb, 21) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) // Act @@ -1347,10 +1285,8 @@ class AdbDeviceServicesTest { @Test fun testShellCommandUsesLegacyShellIfSupported(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) // Below API 21, only "shell" is supported val fakeDevice = addFakeDevice(fakeAdb, 19) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) // Act @@ -1370,10 +1306,8 @@ class AdbDeviceServicesTest { @Test fun testShellCommandWithCommandOutputTimeoutUsesLegacyExecIfSupported(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) // "exec" is supported starting API 21 val fakeDevice = addFakeDevice(fakeAdb, 21) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) // Act @@ -1393,10 +1327,8 @@ class AdbDeviceServicesTest { @Test fun testShellCommandWithCommandOutputTimeoutUsesLegacyShellIfSupported(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) // Below API 21, only "shell" is supported val fakeDevice = addFakeDevice(fakeAdb, 19) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) // Act @@ -1417,10 +1349,8 @@ class AdbDeviceServicesTest { @Test fun testShellCommandThrowsIfNoCollectorSet(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) // Below API 21, only "shell" is supported val fakeDevice = addFakeDevice(fakeAdb, 19) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) // Act @@ -1436,10 +1366,8 @@ class AdbDeviceServicesTest { @Test fun testShellCommandThrowsIfLegacyShellProtocolNotAllowedOnOldDevice(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) // Below API 21, only "shell" is supported val fakeDevice = addFakeDevice(fakeAdb, 19) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) // Act @@ -1456,10 +1384,8 @@ class AdbDeviceServicesTest { @Test fun testShellCommandStripsCrLfOnOldDevices(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) // Below API 21, only "shell" is supported val fakeDevice = addFakeDevice(fakeAdb, 19) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) // Act @@ -1488,10 +1414,8 @@ class AdbDeviceServicesTest { @Test fun testShellCommandAllowsCrLfOnOldDevices(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) // Below API 21, only "shell" is supported val fakeDevice = addFakeDevice(fakeAdb, 19) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) // Act @@ -1538,9 +1462,7 @@ class AdbDeviceServicesTest { @Test fun testDevicePropertiesAllWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) // Act @@ -1555,9 +1477,7 @@ class AdbDeviceServicesTest { @Test fun testDevicePropertiesAllWorksOnApi16(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb, sdk = 16) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) // Act @@ -1572,9 +1492,7 @@ class AdbDeviceServicesTest { @Test fun testDevicePropertiesAllReadonlyWorks() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) // Wait until device shows up as a connected device yieldUntil { @@ -1604,9 +1522,7 @@ class AdbDeviceServicesTest { @Test fun testDevicePropertiesApiWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val device = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(device.deviceId) // Act @@ -1619,12 +1535,7 @@ class AdbDeviceServicesTest { @Test fun testSyncSendFileWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider()) - .installDeviceHandler(SyncCommandHandler()) - .build() - .start() val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val filePath = "/sdcard/foo/bar.bin" @@ -1661,12 +1572,7 @@ class AdbDeviceServicesTest { @Test fun testSyncSendEmptyFileWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider()) - .installDeviceHandler(SyncCommandHandler()) - .build() - .start() val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val filePath = "/sdcard/foo/bar.bin" @@ -1703,12 +1609,7 @@ class AdbDeviceServicesTest { @Test fun testSyncSendWithTimeoutWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider()) - .installDeviceHandler(SyncCommandHandler()) - .build() - .start() val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val filePath = "/sdcard/foo/bar.bin" @@ -1753,12 +1654,7 @@ class AdbDeviceServicesTest { @Test fun testSyncSendRethrowsProgressException(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider()) - .installDeviceHandler(SyncCommandHandler()) - .build() - .start() val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val filePath = "/sdcard/foo/bar.bin" @@ -1790,12 +1686,7 @@ class AdbDeviceServicesTest { @Test fun testSyncSendTwoFilesInSameSessionWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider()) - .installDeviceHandler(SyncCommandHandler()) - .build() - .start() val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val filePath = "/sdcard/foo/bar.bin" @@ -1860,12 +1751,7 @@ class AdbDeviceServicesTest { @Test fun testSyncSendFileWithNoDateSetsModifiedDateToCurrentTime(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider()) - .installDeviceHandler(SyncCommandHandler()) - .build() - .start() val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val filePath = "/sdcard/foo/bar.bin" @@ -1901,12 +1787,7 @@ class AdbDeviceServicesTest { @Test fun testSyncRecvFileWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider()) - .installDeviceHandler(SyncCommandHandler()) - .build() - .start() val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val filePath = "/sdcard/foo/bar.bin" @@ -1945,12 +1826,7 @@ class AdbDeviceServicesTest { @Test fun testSyncRecvTwoFileInSameSessionWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider()) - .installDeviceHandler(SyncCommandHandler()) - .build() - .start() val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val filePath = "/sdcard/foo/bar.bin" @@ -2019,12 +1895,7 @@ class AdbDeviceServicesTest { @Test fun testSyncSendThenRecvFileInSameSessionWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider()) - .installDeviceHandler(SyncCommandHandler()) - .build() - .start() val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val filePath = "/sdcard/foo/bar.bin" @@ -2081,12 +1952,7 @@ class AdbDeviceServicesTest { @Test fun testSyncRecvFileThrowsExceptionIfFileDoesNotExist(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider()) - .installDeviceHandler(SyncCommandHandler()) - .build() - .start() val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val filePath = "/sdcard/foo/bar.bin" @@ -2111,12 +1977,7 @@ class AdbDeviceServicesTest { @Test fun testSyncRecvRethrowsProgressException(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider()) - .installDeviceHandler(SyncCommandHandler()) - .build() - .start() val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val filePath = "/sdcard/foo/bar.bin" @@ -2156,12 +2017,7 @@ class AdbDeviceServicesTest { @Test fun testSyncRecvRethrowsOutputChannelException(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider()) - .installDeviceHandler(SyncCommandHandler()) - .build() - .start() val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val filePath = "/sdcard/foo/bar.bin" @@ -2203,9 +2059,7 @@ class AdbDeviceServicesTest { @Test fun testReverseForward(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) // Act @@ -2222,9 +2076,7 @@ class AdbDeviceServicesTest { @Test fun testReverseForwardNoRebind(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val port = deviceServices.reverseForward( @@ -2252,9 +2104,7 @@ class AdbDeviceServicesTest { @Test fun testReverseForwardRebind(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val port = runBlocking { @@ -2280,9 +2130,7 @@ class AdbDeviceServicesTest { @Test fun testReverseKillForward(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val port = runBlocking { @@ -2307,9 +2155,7 @@ class AdbDeviceServicesTest { @Test fun testReverseKillForwardAll(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) deviceServices.reverseForward( @@ -2331,9 +2177,7 @@ class AdbDeviceServicesTest { @Test fun testReverseListForward(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) deviceServices.reverseForward( @@ -2361,9 +2205,7 @@ class AdbDeviceServicesTest { @Test fun testAbbExec(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val appId = "com.foo.bar.app" @@ -2385,9 +2227,7 @@ class AdbDeviceServicesTest { @Test fun testAbb(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val appId = "com.foo.bar.app" @@ -2409,9 +2249,7 @@ class AdbDeviceServicesTest { @Test fun testAbbProvidesStderrAndExitCode(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) // Act @@ -2437,9 +2275,7 @@ class AdbDeviceServicesTest { @Test fun testAbbWithStdin(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val dataToSend = ByteArray(1_000_000) val stdin = AdbInputStreamChannel(deviceServices.session.host, dataToSend.inputStream()) @@ -2465,9 +2301,7 @@ class AdbDeviceServicesTest { @Test fun testTrackJdwp(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) addClient(fakeDevice, 50) // Add a single client to start with @@ -2491,9 +2325,7 @@ class AdbDeviceServicesTest { @Test fun testTrackAppFlowWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) addProfileableProcess(fakeDevice, 50) // Add a single client to start with @@ -2517,8 +2349,6 @@ class AdbDeviceServicesTest { @Test fun testTrackAppFlowThrowsIfInvalidDeviceSelector(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val deviceServices = createDeviceServices(fakeAdb) // Act exceptionRule.expect(AdbFailResponseException::class.java) @@ -2533,9 +2363,7 @@ class AdbDeviceServicesTest { @Test fun testTrackAppFlowIsTransparentToExceptions(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) addProfileableProcess(fakeDevice, 50) // Add a single client to start with @@ -2553,9 +2381,7 @@ class AdbDeviceServicesTest { @Test fun testTrackAppFlowIsTransparentToCancellation(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) addProfileableProcess(fakeDevice, 50) // Add a single client to start with @@ -2573,9 +2399,7 @@ class AdbDeviceServicesTest { @Test fun testJdwpSessionOpens(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = addFakeDevice(fakeAdb) - val deviceServices = createDeviceServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) val pid = 10 addClient(fakeDevice, pid) @@ -2632,18 +2456,6 @@ class AdbDeviceServicesTest { return result } - private fun createDeviceServices(fakeAdb: FakeAdbServerProvider): AdbDeviceServices { - val host = registerCloseable(TestingAdbSessionHost()) - val channelProvider = fakeAdb.createChannelProvider(host) - val session = - AdbSession.create( - host, - channelProvider, - Duration.ofMillis(SOCKET_CONNECT_TIMEOUT_MS) - ) - return session.deviceServices - } - private fun addFakeDevice(fakeAdb: FakeAdbServerProvider, sdk: Int = 30): DeviceState { val fakeDevice = fakeAdb.connectDevice( diff --git a/adblib/test/src/com/android/adblib/AdbHostServicesTest.kt b/adblib/test/src/com/android/adblib/AdbHostServicesTest.kt index 48d6e995bb..73cfb10b17 100644 --- a/adblib/test/src/com/android/adblib/AdbHostServicesTest.kt +++ b/adblib/test/src/com/android/adblib/AdbHostServicesTest.kt @@ -18,11 +18,10 @@ package com.android.adblib import com.android.adblib.AdbHostServices.DeviceInfoFormat.LONG_FORMAT import com.android.adblib.AdbHostServices.DeviceInfoFormat.SHORT_FORMAT import com.android.adblib.DeviceState.ONLINE -import com.android.adblib.testingutils.CloseablesRule -import com.android.adblib.testingutils.FakeAdbServerProvider -import com.android.adblib.testingutils.TestingAdbSessionHost +import com.android.adblib.testingutils.FakeAdbServerProviderRule import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.MdnsService +import com.android.fakeadbserver.devicecommandhandlers.SyncCommandHandler import com.android.fakeadbserver.hostcommandhandlers.FaultyVersionCommandHandler import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking @@ -32,7 +31,6 @@ import org.junit.Test import org.junit.rules.ExpectedException import java.io.IOException import java.net.InetSocketAddress -import java.time.Duration import java.util.concurrent.TimeUnit /** @@ -48,21 +46,21 @@ class AdbHostServicesTest { @JvmField @Rule - val closeables = CloseablesRule() + val fakeAdbRule = FakeAdbServerProviderRule { + installDefaultCommandHandlers() + installDeviceHandler(SyncCommandHandler()) + } + + private val fakeAdb get() = fakeAdbRule.fakeAdb + private val hostServices get() = fakeAdbRule.adbSession.hostServices @JvmField @Rule var exceptionRule: ExpectedException = ExpectedException.none() - private fun <T : AutoCloseable> registerCloseable(item: T): T { - return closeables.register(item) - } - @Test fun testConnect() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val hostServices = createHostServices(fakeAdb) fakeAdb.registerNetworkDevice("localhost:12345", "1234", "test1", @@ -71,7 +69,7 @@ class AdbHostServicesTest { "sdk") // Act - val result = runBlocking { hostServices.connect(DeviceAddress("localhost:12345")) } + runBlocking { hostServices.connect(DeviceAddress("localhost:12345")) } // Assert runBlocking { @@ -85,8 +83,6 @@ class AdbHostServicesTest { @Test fun testDisconnect() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val hostServices = createHostServices(fakeAdb) fakeAdb.registerNetworkDevice("localhost:12345", "1234", "test1", @@ -114,9 +110,6 @@ class AdbHostServicesTest { @Test fun testVersion() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val hostServices = - createHostServices(fakeAdb) // Act val internalVersion = runBlocking { hostServices.version() } @@ -128,8 +121,7 @@ class AdbHostServicesTest { @Test fun testVersionConnectionFailure() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider()) - val hostServices = createHostServices(fakeAdb) + fakeAdb.stop() // Act (should throw) exceptionRule.expect(IOException::class.java) @@ -142,10 +134,7 @@ class AdbHostServicesTest { @Test fun testVersionFaultyProtocol() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider()) fakeAdb.installHostHandler(FaultyVersionCommandHandler.COMMAND) { FaultyVersionCommandHandler() } - fakeAdb.build().start() - val hostServices = createHostServices(fakeAdb) // Act (should throw) exceptionRule.expect(AdbProtocolErrorException::class.java) @@ -158,8 +147,6 @@ class AdbHostServicesTest { @Test fun testHostFeaturesWorks() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val hostServices = createHostServices(fakeAdb) // Act val featureList = runBlocking { hostServices.hostFeatures() } @@ -174,7 +161,6 @@ class AdbHostServicesTest { @Test fun testDevicesShortFormatWorks() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -185,7 +171,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val deviceList = runBlocking { hostServices.devices(SHORT_FORMAT) } @@ -206,7 +191,6 @@ class AdbHostServicesTest { @Test fun testDevicesLongFormatWorks() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -217,7 +201,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val deviceList = runBlocking { hostServices.devices(LONG_FORMAT) } @@ -238,7 +221,6 @@ class AdbHostServicesTest { @Test fun testTrackDevicesWorks() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -249,7 +231,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val deviceList = runBlocking { @@ -280,7 +261,6 @@ class AdbHostServicesTest { @Test fun testTrackDevicesPropagatesExceptions() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -291,7 +271,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act var exception: Throwable? = null @@ -319,8 +298,6 @@ class AdbHostServicesTest { @Test fun testKillServer() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val hostServices = createHostServices(fakeAdb) // Act runBlocking { hostServices.kill() } @@ -341,8 +318,6 @@ class AdbHostServicesTest { @Test fun testMdnsCheck() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val hostServices = createHostServices(fakeAdb) // Act val result = runBlocking { hostServices.mdnsCheck() } @@ -355,8 +330,6 @@ class AdbHostServicesTest { @Test fun testMdnsServices() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val hostServices = createHostServices(fakeAdb) // Act fakeAdb.addMdnsService( @@ -395,7 +368,6 @@ class AdbHostServicesTest { @Test fun testPair() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) fakeAdb.addMdnsService( MdnsService( "foo-bar2", @@ -403,7 +375,6 @@ class AdbHostServicesTest { InetSocketAddress.createUnresolved("foo", 11) ) ) - val hostServices = createHostServices(fakeAdb) // Act val result = runBlocking { @@ -417,8 +388,6 @@ class AdbHostServicesTest { @Test fun testPairFailsIfDeviceNotPresent() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val hostServices = createHostServices(fakeAdb) // Act val result = runBlocking { @@ -432,7 +401,6 @@ class AdbHostServicesTest { @Test fun testGetState() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -443,7 +411,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val state = runBlocking { @@ -457,7 +424,6 @@ class AdbHostServicesTest { @Test fun testGetSerialNo() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -468,7 +434,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val serialNumber = runBlocking { @@ -482,7 +447,6 @@ class AdbHostServicesTest { @Test fun testGetSerialNoUsesKnownSerialNumber() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -493,7 +457,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val serialNumber = runBlocking { @@ -508,7 +471,6 @@ class AdbHostServicesTest { @Test fun testGetSerialNoConnectsWhenForceRoundTripIsTrue() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -519,7 +481,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val serialNumber = runBlocking { @@ -534,7 +495,6 @@ class AdbHostServicesTest { @Test fun testGetSerialConnectsWhenNoSerialNumber() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -545,7 +505,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val serialNumber = runBlocking { @@ -560,7 +519,6 @@ class AdbHostServicesTest { @Test fun testGetDevPath() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -571,7 +529,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val devPath = runBlocking { @@ -585,7 +542,6 @@ class AdbHostServicesTest { @Test fun testFeatures() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -596,7 +552,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val featureList = runBlocking { @@ -613,7 +568,6 @@ class AdbHostServicesTest { @Test fun testForward() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -624,7 +578,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val port = runBlocking { @@ -642,7 +595,6 @@ class AdbHostServicesTest { @Test fun testForwardNoRebind() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -653,7 +605,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) val port = runBlocking { hostServices.forward( DeviceSelector.any(), @@ -680,7 +631,6 @@ class AdbHostServicesTest { @Test fun testForwardRebind() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -691,7 +641,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) val port = runBlocking { hostServices.forward( DeviceSelector.any(), @@ -717,7 +666,6 @@ class AdbHostServicesTest { @Test fun testKillForward() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -728,7 +676,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) val port = runBlocking { hostServices.forward( DeviceSelector.any(), @@ -753,7 +700,6 @@ class AdbHostServicesTest { @Test fun testKillForwardAll() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -764,7 +710,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) runBlocking { hostServices.forward( DeviceSelector.any(), @@ -786,7 +731,6 @@ class AdbHostServicesTest { @Test fun testListForward() { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -797,7 +741,6 @@ class AdbHostServicesTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) runBlocking { hostServices.forward( DeviceSelector.any(), @@ -821,22 +764,4 @@ class AdbHostServicesTest { Assert.assertEquals("tcp:4000", forwardEntry.remote.toQueryString()) } } - - private fun createHostServices(fakeAdb: FakeAdbServerProvider): AdbHostServices { - val host = registerCloseable(TestingAdbSessionHost()) - val channelProvider = fakeAdb.createChannelProvider(host) - val session = registerCloseable(createSession(host, channelProvider)) - return session.hostServices - } - - private fun createSession( - host: AdbSessionHost, - channelProvider: AdbChannelProvider - ): AdbSession { - return AdbSession.create( - host, - channelProvider, - Duration.ofMillis(SOCKET_CONNECT_TIMEOUT_MS) - ) - } } diff --git a/adblib/test/src/com/android/adblib/AdbSessionTest.kt b/adblib/test/src/com/android/adblib/AdbSessionTest.kt index f20ac261d6..8f9f1c4255 100644 --- a/adblib/test/src/com/android/adblib/AdbSessionTest.kt +++ b/adblib/test/src/com/android/adblib/AdbSessionTest.kt @@ -15,11 +15,10 @@ */ package com.android.adblib -import com.android.adblib.testingutils.CloseablesRule import com.android.adblib.testingutils.CoroutineTestUtils.runBlockingWithTimeout -import com.android.adblib.testingutils.FakeAdbServerProvider -import com.android.adblib.testingutils.TestingAdbSessionHost +import com.android.adblib.testingutils.FakeAdbServerProviderRule import com.android.fakeadbserver.DeviceState +import com.android.fakeadbserver.devicecommandhandlers.SyncCommandHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.TimeoutCancellationException @@ -29,12 +28,10 @@ import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.toList import kotlinx.coroutines.job import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withTimeout import kotlinx.coroutines.yield import org.junit.Assert @@ -50,23 +47,23 @@ class AdbSessionTest { @JvmField @Rule - val closeables = CloseablesRule() + val fakeAdbRule = FakeAdbServerProviderRule { + installDefaultCommandHandlers() + installDeviceHandler(SyncCommandHandler()) + } + + private val fakeAdb get() = fakeAdbRule.fakeAdb + private val session get() = fakeAdbRule.adbSession + private val hostServices get() = session.hostServices + private val host get() = fakeAdbRule.host @JvmField @Rule var exceptionRule: ExpectedException = ExpectedException.none() - private fun <T : AutoCloseable> registerCloseable(item: T): T { - return closeables.register(item) - } - @Test fun testSessionScopeUsesSupervisorJob(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val host = registerCloseable(TestingAdbSessionHost()) - val channelProvider = fakeAdb.createChannelProvider(host) - val session = registerCloseable(AdbSession.create(host, channelProvider)) // Act val job1 = session.scope.launch { @@ -93,10 +90,6 @@ class AdbSessionTest { @Test fun testSessionScopeUsesHostDispatcher(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val host = registerCloseable(TestingAdbSessionHost()) - val channelProvider = fakeAdb.createChannelProvider(host) - val session = registerCloseable(AdbSession.create(host, channelProvider)) // Act val sessionDispatcher = session.scope.async { @@ -110,10 +103,6 @@ class AdbSessionTest { @Test fun testSessionShouldReturnHostServices(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val host = registerCloseable(TestingAdbSessionHost()) - val channelProvider = fakeAdb.createChannelProvider(host) - val session = registerCloseable(AdbSession.create(host, channelProvider)) // Act val services = session.hostServices @@ -126,10 +115,6 @@ class AdbSessionTest { @Test fun testSessionShouldReturnDeviceServices(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val host = registerCloseable(TestingAdbSessionHost()) - val channelProvider = fakeAdb.createChannelProvider(host) - val session = registerCloseable(AdbSession.create(host, channelProvider)) // Act /*val services = */ session.deviceServices @@ -138,10 +123,6 @@ class AdbSessionTest { @Test fun testSessionShouldThrowIfClosed(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val host = registerCloseable(TestingAdbSessionHost()) - val channelProvider = fakeAdb.createChannelProvider(host) - val session = registerCloseable(AdbSession.create(host, channelProvider)) // Act session.close() @@ -155,7 +136,6 @@ class AdbSessionTest { @Test fun testTrackDevicesIsStartedEagerly(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", "test1", @@ -165,7 +145,6 @@ class AdbSessionTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val session = createHostServices(fakeAdb).session // Act // Ensure the connected device shows in the stateFlow.value property even @@ -187,7 +166,6 @@ class AdbSessionTest { @Test fun testTrackDevicesRetriesOnError(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -198,7 +176,6 @@ class AdbSessionTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val flow = hostServices.session.trackDevices(retryDelay = Duration.ofMillis(100)) @@ -263,7 +240,6 @@ class AdbSessionTest { @Test fun testTrackDevicesOpensOnlyOneAdbConnection(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -274,7 +250,6 @@ class AdbSessionTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val flow = hostServices.session.trackDevices(retryDelay = Duration.ofMillis(100)) @@ -321,7 +296,6 @@ class AdbSessionTest { @Test fun testTrackDevicesKeepsWorkingAfterExceptionsInDownstreamCollector(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -332,7 +306,6 @@ class AdbSessionTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val hostServices = createHostServices(fakeAdb) // Act val exceptions = Collections.synchronizedList(ArrayList<MyTestException>()) @@ -393,7 +366,6 @@ class AdbSessionTest { @Test fun testTrackDeviceInfoWorks(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -403,7 +375,6 @@ class AdbSessionTest { "sdk", DeviceState.HostConnectionType.USB ) - val hostServices = createHostServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) // Act @@ -441,7 +412,6 @@ class AdbSessionTest { @Test fun testTrackDeviceInfoStopAfterDeviceDisconnects(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -451,7 +421,6 @@ class AdbSessionTest { "sdk", DeviceState.HostConnectionType.USB ) - val hostServices = createHostServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) // Act @@ -478,7 +447,6 @@ class AdbSessionTest { @Test fun testTrackDeviceInfoStopsAfterAdbRestart(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -488,7 +456,6 @@ class AdbSessionTest { "sdk", DeviceState.HostConnectionType.USB ) - val hostServices = createHostServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) // Act @@ -524,8 +491,6 @@ class AdbSessionTest { @Test fun testTrackDeviceInfoEndsIfDeviceNotFound(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val hostServices = createHostServices(fakeAdb) fakeAdb.connectDevice( "1234", "test1", @@ -546,8 +511,6 @@ class AdbSessionTest { @Test fun testTrackDeviceInfoEndsIfNoDeviceConnected(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val hostServices = createHostServices(fakeAdb) val deviceSelector = DeviceSelector.fromSerialNumber("1234") // Act @@ -560,7 +523,6 @@ class AdbSessionTest { @Test fun testDeviceCoroutineScopeWorksForOnlineDevice(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -572,7 +534,6 @@ class AdbSessionTest { ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) - val session = createHostServices(fakeAdb).session // Act var deviceCoroutineIsRunning = false @@ -612,9 +573,7 @@ class AdbSessionTest { @Test fun testDeviceCoroutineScopeWorksForDisconnectedDevice(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val deviceSelector = DeviceSelector.fromSerialNumber("1234") - val session = createHostServices(fakeAdb).session // Act var deviceCoroutineIsRunning = false @@ -641,7 +600,6 @@ class AdbSessionTest { @Test fun testDeviceCoroutineScopeIsCancelledWithSessionClose(): Unit = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", @@ -653,7 +611,6 @@ class AdbSessionTest { ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE val deviceSelector = DeviceSelector.fromSerialNumber(fakeDevice.deviceId) - val session = createHostServices(fakeAdb).session // Act var deviceCoroutineIsRunning = false @@ -685,24 +642,6 @@ class AdbSessionTest { Assert.assertFalse(deviceCoroutineIsRunning) } - private fun createHostServices(fakeAdb: FakeAdbServerProvider): AdbHostServices { - val host = registerCloseable(TestingAdbSessionHost()) - val channelProvider = fakeAdb.createChannelProvider(host) - val session = registerCloseable(createSession(host, channelProvider)) - return session.hostServices - } - - private fun createSession( - host: AdbSessionHost, - channelProvider: AdbChannelProvider - ): AdbSession { - return AdbSession.create( - host, - channelProvider, - Duration.ofMillis(SOCKET_CONNECT_TIMEOUT_MS) - ) - } - class MyTestException(message: String) : IOException(message) private suspend fun yieldUntil( diff --git a/adblib/test/src/com/android/adblib/ConnectedDevicesTrackerTest.kt b/adblib/test/src/com/android/adblib/ConnectedDevicesTrackerTest.kt index e5c8e95a5c..a911fb29ae 100644 --- a/adblib/test/src/com/android/adblib/ConnectedDevicesTrackerTest.kt +++ b/adblib/test/src/com/android/adblib/ConnectedDevicesTrackerTest.kt @@ -16,40 +16,39 @@ package com.android.adblib import com.android.adblib.impl.ConnectedDevicesTrackerImpl -import com.android.adblib.testingutils.CloseablesRule import com.android.adblib.testingutils.CoroutineTestUtils.runBlockingWithTimeout import com.android.adblib.testingutils.CoroutineTestUtils.yieldUntil -import com.android.adblib.testingutils.FakeAdbServerProvider -import com.android.adblib.testingutils.TestingAdbSessionHost +import com.android.adblib.testingutils.FakeAdbServerProviderRule import com.android.fakeadbserver.DeviceState +import com.android.fakeadbserver.devicecommandhandlers.SyncCommandHandler import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import org.junit.Assert import org.junit.Rule import org.junit.Test import org.junit.rules.ExpectedException -import java.time.Duration class ConnectedDevicesTrackerTest { @JvmField @Rule - val closeables = CloseablesRule() + val fakeAdbRule = FakeAdbServerProviderRule { + installDefaultCommandHandlers() + installDeviceHandler(SyncCommandHandler()) + } @JvmField @Rule var exceptionRule: ExpectedException = ExpectedException.none() - private fun <T : AutoCloseable> registerCloseable(item: T): T { - return closeables.register(item) - } + private val fakeAdb get() = fakeAdbRule.fakeAdb + private val session get() = fakeAdbRule.adbSession data class TestKey(val id: String) : CoroutineScopeCache.Key<Any>("test key $id") @Test fun constructorDoesNotStartTracking() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", "test1", @@ -59,7 +58,6 @@ class ConnectedDevicesTrackerTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val session = createSession(fakeAdb) // Act val deviceCacheManager = ConnectedDevicesTrackerImpl(session) @@ -72,7 +70,6 @@ class ConnectedDevicesTrackerTest { @Test fun startWorks() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", "test1", @@ -82,7 +79,6 @@ class ConnectedDevicesTrackerTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val session = createSession(fakeAdb) // Act val deviceCacheManager = ConnectedDevicesTrackerImpl(session) @@ -97,7 +93,6 @@ class ConnectedDevicesTrackerTest { @Test fun closingSessionEndsStateFlow() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", "test1", @@ -107,7 +102,6 @@ class ConnectedDevicesTrackerTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val session = createSession(fakeAdb) // Act val deviceCacheManager = ConnectedDevicesTrackerImpl(session) @@ -127,7 +121,6 @@ class ConnectedDevicesTrackerTest { @Test fun connectedDeviceShowsInStateFlow() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", "test1", @@ -137,7 +130,6 @@ class ConnectedDevicesTrackerTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val session = createSession(fakeAdb) // Act val deviceCacheManager = ConnectedDevicesTrackerImpl(session) @@ -158,7 +150,6 @@ class ConnectedDevicesTrackerTest { @Test fun connectedDeviceShowsChangingDeviceStateInStateFlow() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", "test1", @@ -168,7 +159,6 @@ class ConnectedDevicesTrackerTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val session = createSession(fakeAdb) // Act val deviceInfoList = mutableListOf<DeviceInfo>() @@ -210,7 +200,6 @@ class ConnectedDevicesTrackerTest { @Test fun connectedDeviceBecomesInactiveWhenDeviceIsDisconnected() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", "test1", @@ -221,7 +210,6 @@ class ConnectedDevicesTrackerTest { ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE val cacheKey = TestKey("foo") - val session = createSession(fakeAdb) // Act val deviceCacheManager = ConnectedDevicesTrackerImpl(session) @@ -249,7 +237,6 @@ class ConnectedDevicesTrackerTest { @Test fun deviceCacheCreatesCache() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", "test1", @@ -259,7 +246,6 @@ class ConnectedDevicesTrackerTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val session = createSession(fakeAdb) val deviceCacheManager = ConnectedDevicesTrackerImpl(session) val key = TestKey("foo") @@ -281,8 +267,6 @@ class ConnectedDevicesTrackerTest { @Test fun deviceCacheReturnsNoOpCacheForUnknownDevice() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) - val session = createSession(fakeAdb) val deviceCacheManager = ConnectedDevicesTrackerImpl(session) val key = TestKey("foo") @@ -301,7 +285,6 @@ class ConnectedDevicesTrackerTest { @Test fun deviceCacheIsClosedWhenDeviceDisconnected() = runBlockingWithTimeout { // Prepare - val fakeAdb = registerCloseable(FakeAdbServerProvider().buildDefault().start()) val fakeDevice = fakeAdb.connectDevice( "1234", "test1", @@ -311,7 +294,6 @@ class ConnectedDevicesTrackerTest { DeviceState.HostConnectionType.USB ) fakeDevice.deviceStatus = DeviceState.DeviceStatus.ONLINE - val session = createSession(fakeAdb) val deviceCacheManager = ConnectedDevicesTrackerImpl(session) val key = TestKey("foo") val closeable = object : AutoCloseable { @@ -338,14 +320,4 @@ class ConnectedDevicesTrackerTest { Assert.assertTrue(closeable.closed) Assert.assertEquals(0, deviceCacheManager.connectedDevices.value.size) } - - private fun createSession(fakeAdb: FakeAdbServerProvider): AdbSession { - val host = registerCloseable(TestingAdbSessionHost()) - val channelProvider = fakeAdb.createChannelProvider(host) - return AdbSession.create( - host, - channelProvider, - Duration.ofMillis(SOCKET_CONNECT_TIMEOUT_MS) - ) - } } diff --git a/adblib/test/src/com/android/adblib/testingutils/FakeAdbServerProvider.kt b/adblib/test/src/com/android/adblib/testingutils/FakeAdbServerProvider.kt index d7deca0ce6..f25519f86d 100644 --- a/adblib/test/src/com/android/adblib/testingutils/FakeAdbServerProvider.kt +++ b/adblib/test/src/com/android/adblib/testingutils/FakeAdbServerProvider.kt @@ -39,7 +39,7 @@ import java.util.function.Supplier */ val FAKE_ADB_SERVER_EXECUTOR_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(2) -class FakeAdbServerProvider : AutoCloseable { +class FakeAdbServerProvider internal constructor(): AutoCloseable { val inetAddress: InetAddress get() = server?.inetAddress ?: throw IllegalStateException("Server not started") @@ -78,6 +78,11 @@ class FakeAdbServerProvider : AutoCloseable { return this } + fun setFeatures(vararg features : String) : FakeAdbServerProvider { + builder.setFeatures(features.toSet()) + return this + } + fun buildWithFeatures(features : Set<String>) : FakeAdbServerProvider { // Build the server and configure it to use the default ADB command handlers. builder.installDefaultCommandHandlers() @@ -155,6 +160,11 @@ class FakeAdbServerProvider : AutoCloseable { return this } + fun stop(): FakeAdbServerProvider { + server?.close() + return this + } + fun restart() { // Save current server config and close it val config = server?.currentConfig diff --git a/adblib/test/src/com/android/adblib/testingutils/FakeAdbServerProviderRule.kt b/adblib/test/src/com/android/adblib/testingutils/FakeAdbServerProviderRule.kt new file mode 100644 index 0000000000..4c1659e74b --- /dev/null +++ b/adblib/test/src/com/android/adblib/testingutils/FakeAdbServerProviderRule.kt @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2023 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.adblib.testingutils + +import com.android.adblib.AdbSession +import com.android.adblib.SOCKET_CONNECT_TIMEOUT_MS +import org.junit.rules.ExternalResource +import java.time.Duration + +/** Manages the lifecycle of a FakeAdbServerProvider */ +open class FakeAdbServerProviderRule( + configure: (FakeAdbServerProvider.() -> FakeAdbServerProvider)? = null +) : ExternalResource() { + + private val configure: FakeAdbServerProvider.() -> FakeAdbServerProvider = configure ?: { + installDefaultCommandHandlers() + } + + lateinit var fakeAdb: FakeAdbServerProvider + private set + + lateinit var host: TestingAdbSessionHost + private set + + lateinit var adbSession: AdbSession + private set + + public override fun before() { + fakeAdb = FakeAdbServerProvider().configure().build().start() + host = TestingAdbSessionHost() + adbSession = AdbSession.create( + host, + fakeAdb.createChannelProvider(host), + Duration.ofMillis(SOCKET_CONNECT_TIMEOUT_MS), + ) + } + + override fun after() { + adbSession.close() + host.close() + fakeAdb.close() + } +} diff --git a/apkparser/analyzer/BUILD b/apkparser/analyzer/BUILD index 88465c9bd4..da512b946d 100644 --- a/apkparser/analyzer/BUILD +++ b/apkparser/analyzer/BUILD @@ -22,8 +22,6 @@ iml_module( "//prebuilts/tools/common/archive-patcher:shared", "//tools/adt/idea/.idea/libraries:google-dexlib2", "//tools/adt/idea/.idea/libraries:google-baksmali", - "//tools/adt/idea/.idea/libraries:dexlib2", - "//tools/adt/idea/.idea/libraries:baksmali", "//tools/base/testutils:studio.android.sdktools.testutils[module, test]", "//tools/adt/idea/.idea/libraries:truth[test]", "//tools/adt/idea/.idea/libraries:jimfs[test]", @@ -48,8 +46,6 @@ coverage_java_library( "@maven//:com.android.tools.smali.smali-baksmali", "@maven//:com.android.tools.smali.smali-dexlib2", "@maven//:com.google.guava.guava", - "@maven//:org.smali.baksmali", - "@maven//:org.smali.dexlib2", ], ) @@ -76,8 +72,6 @@ maven_library( "@maven//:com.android.tools.smali.smali-baksmali", "@maven//:com.android.tools.smali.smali-dexlib2", "@maven//:com.google.guava.guava", - "@maven//:org.smali.baksmali", - "@maven//:org.smali.dexlib2", ], ) @@ -96,6 +90,5 @@ coverage_java_test( "@maven//:com.google.jimfs.jimfs", "@maven//:com.google.truth.truth", "@maven//:junit.junit", - "@maven//:org.smali.dexlib2", ], ) diff --git a/apkparser/analyzer/android.sdktools.analyzer.iml b/apkparser/analyzer/android.sdktools.analyzer.iml index 0673763460..acbe41b85c 100644 --- a/apkparser/analyzer/android.sdktools.analyzer.iml +++ b/apkparser/analyzer/android.sdktools.analyzer.iml @@ -41,8 +41,6 @@ </orderEntry> <orderEntry type="library" name="google-dexlib2" level="project" /> <orderEntry type="library" name="google-baksmali" level="project" /> - <orderEntry type="library" name="dexlib2" level="project" /> - <orderEntry type="library" name="baksmali" level="project" /> <orderEntry type="module" module-name="android.sdktools.testutils" scope="TEST" /> <orderEntry type="library" scope="TEST" name="truth" level="project" /> <orderEntry type="library" scope="TEST" name="jimfs" level="project" /> diff --git a/apkparser/analyzer/android.sdktools.base.apkparser.analyzer-base.iml b/apkparser/analyzer/android.sdktools.base.apkparser.analyzer-base.iml index dd21b8eb48..390c4003b8 100644 --- a/apkparser/analyzer/android.sdktools.base.apkparser.analyzer-base.iml +++ b/apkparser/analyzer/android.sdktools.base.apkparser.analyzer-base.iml @@ -39,8 +39,6 @@ <SOURCES /> </library> </orderEntry> - <orderEntry type="library" name="dexlib2" level="project" /> - <orderEntry type="library" name="baksmali" level="project" /> <orderEntry type="library" name="google-dexlib2" level="project" /> <orderEntry type="library" name="google-baksmali" level="project" /> <orderEntry type="module" module-name="android.sdktools.testutils" scope="TEST" /> diff --git a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexDisassembler.java b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexDisassembler.java index 1bfd283f7f..56d1dc3d72 100644 --- a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexDisassembler.java +++ b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexDisassembler.java @@ -21,28 +21,28 @@ import com.android.tools.apk.analyzer.internal.SigUtils; import com.android.tools.apk.analyzer.internal.rewriters.FieldReferenceWithNameRewriter; import com.android.tools.apk.analyzer.internal.rewriters.MethodReferenceWithNameRewriter; import com.android.tools.proguard.ProguardMap; +import com.android.tools.smali.baksmali.Adaptors.ClassDefinition; +import com.android.tools.smali.baksmali.Adaptors.MethodDefinition; +import com.android.tools.smali.baksmali.BaksmaliOptions; +import com.android.tools.smali.baksmali.formatter.BaksmaliWriter; +import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile; +import com.android.tools.smali.dexlib2.iface.ClassDef; +import com.android.tools.smali.dexlib2.iface.DexFile; +import com.android.tools.smali.dexlib2.iface.Method; +import com.android.tools.smali.dexlib2.iface.MethodImplementation; +import com.android.tools.smali.dexlib2.iface.reference.FieldReference; +import com.android.tools.smali.dexlib2.iface.reference.MethodReference; +import com.android.tools.smali.dexlib2.rewriter.DexRewriter; +import com.android.tools.smali.dexlib2.rewriter.Rewriter; +import com.android.tools.smali.dexlib2.rewriter.RewriterModule; +import com.android.tools.smali.dexlib2.rewriter.Rewriters; +import com.android.tools.smali.dexlib2.rewriter.TypeRewriter; +import com.android.tools.smali.dexlib2.util.ReferenceUtil; +import com.android.tools.smali.util.IndentingWriter; import java.io.IOException; import java.io.StringWriter; import java.util.Optional; import java.util.stream.StreamSupport; -import org.jf.baksmali.Adaptors.ClassDefinition; -import org.jf.baksmali.Adaptors.MethodDefinition; -import org.jf.baksmali.BaksmaliOptions; -import org.jf.baksmali.formatter.BaksmaliWriter; -import org.jf.dexlib2.dexbacked.DexBackedDexFile; -import org.jf.dexlib2.iface.ClassDef; -import org.jf.dexlib2.iface.DexFile; -import org.jf.dexlib2.iface.Method; -import org.jf.dexlib2.iface.MethodImplementation; -import org.jf.dexlib2.iface.reference.FieldReference; -import org.jf.dexlib2.iface.reference.MethodReference; -import org.jf.dexlib2.rewriter.DexRewriter; -import org.jf.dexlib2.rewriter.Rewriter; -import org.jf.dexlib2.rewriter.RewriterModule; -import org.jf.dexlib2.rewriter.Rewriters; -import org.jf.dexlib2.rewriter.TypeRewriter; -import org.jf.dexlib2.util.ReferenceUtil; -import org.jf.util.IndentingWriter; public class DexDisassembler { @NonNull private final DexFile dexFile; diff --git a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexFileStats.java b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexFileStats.java index 0aa92fb1be..eaec7adfd8 100644 --- a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexFileStats.java +++ b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexFileStats.java @@ -16,11 +16,11 @@ package com.android.tools.apk.analyzer.dex; import com.android.annotations.NonNull; +import com.android.tools.smali.dexlib2.dexbacked.DexBackedClassDef; +import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile; import com.google.common.collect.Iterables; import java.util.Collection; import java.util.Set; -import org.jf.dexlib2.dexbacked.DexBackedClassDef; -import org.jf.dexlib2.dexbacked.DexBackedDexFile; public class DexFileStats { public final int classCount; diff --git a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexFiles.java b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexFiles.java index 9e92de8568..7a92d22301 100644 --- a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexFiles.java +++ b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexFiles.java @@ -16,13 +16,13 @@ package com.android.tools.apk.analyzer.dex; import com.android.annotations.NonNull; +import com.android.tools.smali.dexlib2.Opcodes; +import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile; +import com.android.tools.smali.dexlib2.dexbacked.raw.HeaderItem; +import com.android.tools.smali.dexlib2.util.DexUtil; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import org.jf.dexlib2.Opcodes; -import org.jf.dexlib2.dexbacked.DexBackedDexFile; -import org.jf.dexlib2.dexbacked.raw.HeaderItem; -import org.jf.dexlib2.util.DexUtil; public final class DexFiles { diff --git a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexReferences.java b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexReferences.java index 4cf123fbc3..b0c728518c 100644 --- a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexReferences.java +++ b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/DexReferences.java @@ -17,24 +17,24 @@ package com.android.tools.apk.analyzer.dex; import com.android.annotations.NonNull; import com.android.tools.apk.analyzer.dex.tree.*; +import com.android.tools.smali.dexlib2.dexbacked.*; +import com.android.tools.smali.dexlib2.dexbacked.reference.DexBackedFieldReference; +import com.android.tools.smali.dexlib2.dexbacked.reference.DexBackedMethodReference; +import com.android.tools.smali.dexlib2.dexbacked.reference.DexBackedTypeReference; +import com.android.tools.smali.dexlib2.iface.Annotation; +import com.android.tools.smali.dexlib2.iface.AnnotationElement; +import com.android.tools.smali.dexlib2.iface.instruction.DualReferenceInstruction; +import com.android.tools.smali.dexlib2.iface.instruction.Instruction; +import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction; +import com.android.tools.smali.dexlib2.iface.reference.FieldReference; +import com.android.tools.smali.dexlib2.iface.reference.MethodReference; +import com.android.tools.smali.dexlib2.iface.reference.Reference; +import com.android.tools.smali.dexlib2.iface.reference.TypeReference; +import com.android.tools.smali.dexlib2.iface.value.*; +import com.android.tools.smali.dexlib2.immutable.reference.*; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import java.util.*; -import org.jf.dexlib2.dexbacked.*; -import org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference; -import org.jf.dexlib2.dexbacked.reference.DexBackedMethodReference; -import org.jf.dexlib2.dexbacked.reference.DexBackedTypeReference; -import org.jf.dexlib2.iface.Annotation; -import org.jf.dexlib2.iface.AnnotationElement; -import org.jf.dexlib2.iface.instruction.DualReferenceInstruction; -import org.jf.dexlib2.iface.instruction.Instruction; -import org.jf.dexlib2.iface.instruction.ReferenceInstruction; -import org.jf.dexlib2.iface.reference.FieldReference; -import org.jf.dexlib2.iface.reference.MethodReference; -import org.jf.dexlib2.iface.reference.Reference; -import org.jf.dexlib2.iface.reference.TypeReference; -import org.jf.dexlib2.iface.value.*; -import org.jf.dexlib2.immutable.reference.*; public class DexReferences { diff --git a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/PackageTreeCreator.java b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/PackageTreeCreator.java index 50ce31e2da..a80df00479 100644 --- a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/PackageTreeCreator.java +++ b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/PackageTreeCreator.java @@ -21,6 +21,19 @@ import com.android.tools.apk.analyzer.dex.tree.*; import com.android.tools.apk.analyzer.internal.SigUtils; import com.android.tools.proguard.ProguardMap; import com.android.tools.proguard.ProguardUsagesMap; +import com.android.tools.smali.dexlib2.dexbacked.DexBackedClassDef; +import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile; +import com.android.tools.smali.dexlib2.dexbacked.DexBackedField; +import com.android.tools.smali.dexlib2.dexbacked.DexBackedMethod; +import com.android.tools.smali.dexlib2.dexbacked.reference.DexBackedFieldReference; +import com.android.tools.smali.dexlib2.dexbacked.reference.DexBackedMethodReference; +import com.android.tools.smali.dexlib2.dexbacked.reference.DexBackedTypeReference; +import com.android.tools.smali.dexlib2.iface.reference.FieldReference; +import com.android.tools.smali.dexlib2.iface.reference.MethodReference; +import com.android.tools.smali.dexlib2.iface.reference.TypeReference; +import com.android.tools.smali.dexlib2.immutable.reference.ImmutableFieldReference; +import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference; +import com.android.tools.smali.dexlib2.util.ReferenceUtil; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import java.nio.file.Path; @@ -29,19 +42,6 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.jf.dexlib2.dexbacked.DexBackedClassDef; -import org.jf.dexlib2.dexbacked.DexBackedDexFile; -import org.jf.dexlib2.dexbacked.DexBackedField; -import org.jf.dexlib2.dexbacked.DexBackedMethod; -import org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference; -import org.jf.dexlib2.dexbacked.reference.DexBackedMethodReference; -import org.jf.dexlib2.dexbacked.reference.DexBackedTypeReference; -import org.jf.dexlib2.iface.reference.FieldReference; -import org.jf.dexlib2.iface.reference.MethodReference; -import org.jf.dexlib2.iface.reference.TypeReference; -import org.jf.dexlib2.immutable.reference.ImmutableFieldReference; -import org.jf.dexlib2.immutable.reference.ImmutableMethodReference; -import org.jf.dexlib2.util.ReferenceUtil; public class PackageTreeCreator { public static final String PARAMS_DELIMITER = ","; diff --git a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexClassNode.java b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexClassNode.java index b335a5e8dc..00b66d5015 100644 --- a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexClassNode.java +++ b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexClassNode.java @@ -20,8 +20,8 @@ import com.android.annotations.Nullable; import com.android.tools.apk.analyzer.dex.PackageTreeCreator; import com.android.tools.proguard.ProguardMap; import com.android.tools.proguard.ProguardSeedsMap; -import org.jf.dexlib2.iface.reference.TypeReference; -import org.jf.dexlib2.immutable.reference.ImmutableTypeReference; +import com.android.tools.smali.dexlib2.iface.reference.TypeReference; +import com.android.tools.smali.dexlib2.immutable.reference.ImmutableTypeReference; public class DexClassNode extends DexElementNode { private long size = 0; diff --git a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexElementNode.java b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexElementNode.java index 00afb1ec02..899fb2d097 100644 --- a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexElementNode.java +++ b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexElementNode.java @@ -19,11 +19,11 @@ import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.tools.proguard.ProguardMap; import com.android.tools.proguard.ProguardSeedsMap; +import com.android.tools.smali.dexlib2.iface.reference.Reference; +import com.android.tools.smali.dexlib2.immutable.reference.ImmutableReference; import java.util.Comparator; import java.util.List; import javax.swing.tree.DefaultMutableTreeNode; -import org.jf.dexlib2.iface.reference.Reference; -import org.jf.dexlib2.immutable.reference.ImmutableReference; public abstract class DexElementNode extends DefaultMutableTreeNode { diff --git a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexElementNodeFactory.java b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexElementNodeFactory.java index d88475e762..7226e19433 100644 --- a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexElementNodeFactory.java +++ b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexElementNodeFactory.java @@ -17,13 +17,13 @@ package com.android.tools.apk.analyzer.dex.tree; import com.android.annotations.NonNull; import com.android.tools.apk.analyzer.internal.SigUtils; -import org.jf.dexlib2.iface.reference.FieldReference; -import org.jf.dexlib2.iface.reference.MethodReference; -import org.jf.dexlib2.iface.reference.TypeReference; -import org.jf.dexlib2.immutable.reference.ImmutableFieldReference; -import org.jf.dexlib2.immutable.reference.ImmutableMethodReference; -import org.jf.dexlib2.immutable.reference.ImmutableReference; -import org.jf.dexlib2.immutable.reference.ImmutableTypeReference; +import com.android.tools.smali.dexlib2.iface.reference.FieldReference; +import com.android.tools.smali.dexlib2.iface.reference.MethodReference; +import com.android.tools.smali.dexlib2.iface.reference.TypeReference; +import com.android.tools.smali.dexlib2.immutable.reference.ImmutableFieldReference; +import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference; +import com.android.tools.smali.dexlib2.immutable.reference.ImmutableReference; +import com.android.tools.smali.dexlib2.immutable.reference.ImmutableTypeReference; public class DexElementNodeFactory { diff --git a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexFieldNode.java b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexFieldNode.java index 6e6ff5a7d6..dddae61fef 100644 --- a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexFieldNode.java +++ b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexFieldNode.java @@ -20,8 +20,8 @@ import com.android.annotations.Nullable; import com.android.tools.apk.analyzer.dex.PackageTreeCreator; import com.android.tools.proguard.ProguardMap; import com.android.tools.proguard.ProguardSeedsMap; -import org.jf.dexlib2.iface.reference.FieldReference; -import org.jf.dexlib2.immutable.reference.ImmutableFieldReference; +import com.android.tools.smali.dexlib2.iface.reference.FieldReference; +import com.android.tools.smali.dexlib2.immutable.reference.ImmutableFieldReference; public class DexFieldNode extends DexElementNode { private long size; diff --git a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexMethodNode.java b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexMethodNode.java index 828ad12a0b..ab1511f185 100644 --- a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexMethodNode.java +++ b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexMethodNode.java @@ -21,8 +21,8 @@ import com.android.tools.apk.analyzer.dex.PackageTreeCreator; import com.android.tools.apk.analyzer.internal.SigUtils; import com.android.tools.proguard.ProguardMap; import com.android.tools.proguard.ProguardSeedsMap; -import org.jf.dexlib2.iface.reference.MethodReference; -import org.jf.dexlib2.immutable.reference.ImmutableMethodReference; +import com.android.tools.smali.dexlib2.iface.reference.MethodReference; +import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference; public class DexMethodNode extends DexElementNode { private long size; diff --git a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexPackageNode.java b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexPackageNode.java index 0197e4a20e..32da210df8 100644 --- a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexPackageNode.java +++ b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/dex/tree/DexPackageNode.java @@ -17,9 +17,9 @@ package com.android.tools.apk.analyzer.dex.tree; import com.android.annotations.NonNull; import com.android.annotations.Nullable; +import com.android.tools.smali.dexlib2.iface.reference.TypeReference; +import com.android.tools.smali.dexlib2.immutable.reference.ImmutableTypeReference; import javax.swing.*; -import org.jf.dexlib2.iface.reference.TypeReference; -import org.jf.dexlib2.immutable.reference.ImmutableTypeReference; public class DexPackageNode extends DexElementNode { @Nullable private final String packageName; diff --git a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/internal/rewriters/FieldReferenceWithNameRewriter.java b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/internal/rewriters/FieldReferenceWithNameRewriter.java index e060a1fd10..684bcff01a 100644 --- a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/internal/rewriters/FieldReferenceWithNameRewriter.java +++ b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/internal/rewriters/FieldReferenceWithNameRewriter.java @@ -16,9 +16,9 @@ package com.android.tools.apk.analyzer.internal.rewriters; import com.android.annotations.NonNull; -import org.jf.dexlib2.iface.reference.FieldReference; -import org.jf.dexlib2.rewriter.FieldReferenceRewriter; -import org.jf.dexlib2.rewriter.Rewriters; +import com.android.tools.smali.dexlib2.iface.reference.FieldReference; +import com.android.tools.smali.dexlib2.rewriter.FieldReferenceRewriter; +import com.android.tools.smali.dexlib2.rewriter.Rewriters; public abstract class FieldReferenceWithNameRewriter extends FieldReferenceRewriter { diff --git a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/internal/rewriters/MethodReferenceWithNameRewriter.java b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/internal/rewriters/MethodReferenceWithNameRewriter.java index a353e49c67..5fced3952a 100644 --- a/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/internal/rewriters/MethodReferenceWithNameRewriter.java +++ b/apkparser/analyzer/src/main/java/com/android/tools/apk/analyzer/internal/rewriters/MethodReferenceWithNameRewriter.java @@ -17,9 +17,9 @@ package com.android.tools.apk.analyzer.internal.rewriters; import com.android.annotations.NonNull; -import org.jf.dexlib2.iface.reference.MethodReference; -import org.jf.dexlib2.rewriter.MethodReferenceRewriter; -import org.jf.dexlib2.rewriter.Rewriters; +import com.android.tools.smali.dexlib2.iface.reference.MethodReference; +import com.android.tools.smali.dexlib2.rewriter.MethodReferenceRewriter; +import com.android.tools.smali.dexlib2.rewriter.Rewriters; public abstract class MethodReferenceWithNameRewriter extends MethodReferenceRewriter { diff --git a/apkparser/analyzer/src/test/java/com/android/tools/apk/analyzer/dex/DexReferencesTest.java b/apkparser/analyzer/src/test/java/com/android/tools/apk/analyzer/dex/DexReferencesTest.java index 8375a1cd70..1b444d705a 100644 --- a/apkparser/analyzer/src/test/java/com/android/tools/apk/analyzer/dex/DexReferencesTest.java +++ b/apkparser/analyzer/src/test/java/com/android/tools/apk/analyzer/dex/DexReferencesTest.java @@ -21,10 +21,10 @@ import static org.junit.Assert.assertTrue; import com.android.annotations.NonNull; import com.android.tools.apk.analyzer.dex.tree.DexElementNode; +import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile; +import com.android.tools.smali.dexlib2.immutable.reference.ImmutableTypeReference; +import com.android.tools.smali.dexlib2.util.ReferenceUtil; import java.io.IOException; -import org.jf.dexlib2.dexbacked.DexBackedDexFile; -import org.jf.dexlib2.immutable.reference.ImmutableTypeReference; -import org.jf.dexlib2.util.ReferenceUtil; import org.junit.Test; public class DexReferencesTest { diff --git a/apkparser/analyzer/src/test/java/com/android/tools/apk/analyzer/dex/FilteredTreeModelTest.java b/apkparser/analyzer/src/test/java/com/android/tools/apk/analyzer/dex/FilteredTreeModelTest.java index b6042156cd..c8fd0bf0d0 100644 --- a/apkparser/analyzer/src/test/java/com/android/tools/apk/analyzer/dex/FilteredTreeModelTest.java +++ b/apkparser/analyzer/src/test/java/com/android/tools/apk/analyzer/dex/FilteredTreeModelTest.java @@ -26,12 +26,12 @@ import com.android.tools.apk.analyzer.dex.tree.DexPackageNode; import com.android.tools.proguard.ProguardMap; import com.android.tools.proguard.ProguardSeedsMap; import com.android.tools.proguard.ProguardUsagesMap; +import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.text.ParseException; import javax.swing.tree.TreeModel; -import org.jf.dexlib2.dexbacked.DexBackedDexFile; import org.junit.Test; public class FilteredTreeModelTest { diff --git a/apkparser/analyzer/src/test/java/com/android/tools/apk/analyzer/dex/PackageTreeCreatorTest.java b/apkparser/analyzer/src/test/java/com/android/tools/apk/analyzer/dex/PackageTreeCreatorTest.java index bc9a2e6d45..d84d8a9b55 100644 --- a/apkparser/analyzer/src/test/java/com/android/tools/apk/analyzer/dex/PackageTreeCreatorTest.java +++ b/apkparser/analyzer/src/test/java/com/android/tools/apk/analyzer/dex/PackageTreeCreatorTest.java @@ -25,6 +25,7 @@ import com.android.tools.apk.analyzer.dex.tree.DexPackageNode; import com.android.tools.proguard.ProguardMap; import com.android.tools.proguard.ProguardSeedsMap; import com.android.tools.proguard.ProguardUsagesMap; +import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -32,7 +33,6 @@ import java.text.ParseException; import java.util.Comparator; import java.util.Map; import java.util.TreeMap; -import org.jf.dexlib2.dexbacked.DexBackedDexFile; import org.junit.Test; public class PackageTreeCreatorTest { diff --git a/apkparser/cli/BUILD b/apkparser/cli/BUILD index dd02ebae8a..6eb74d4f66 100644 --- a/apkparser/cli/BUILD +++ b/apkparser/cli/BUILD @@ -13,8 +13,8 @@ coverage_java_library( "//tools/base/profgen/profgen", "//tools/base/sdk-common:tools.sdk-common", "//tools/base/sdklib:tools.sdklib", + "@maven//:com.android.tools.smali.smali-dexlib2", "@maven//:net.sf.jopt-simple.jopt-simple", - "@maven//:org.smali.dexlib2", ], ) diff --git a/apkparser/cli/src/main/java/com/android/tools/apk/analyzer/ApkAnalyzerImpl.java b/apkparser/cli/src/main/java/com/android/tools/apk/analyzer/ApkAnalyzerImpl.java index 9b5a51a16d..5c0c13658e 100644 --- a/apkparser/cli/src/main/java/com/android/tools/apk/analyzer/ApkAnalyzerImpl.java +++ b/apkparser/cli/src/main/java/com/android/tools/apk/analyzer/ApkAnalyzerImpl.java @@ -41,6 +41,11 @@ import com.android.tools.apk.analyzer.internal.SigUtils; import com.android.tools.proguard.ProguardMap; import com.android.tools.proguard.ProguardSeedsMap; import com.android.tools.proguard.ProguardUsagesMap; +import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile; +import com.android.tools.smali.dexlib2.iface.reference.FieldReference; +import com.android.tools.smali.dexlib2.iface.reference.MethodReference; +import com.android.tools.smali.dexlib2.iface.reference.Reference; +import com.android.tools.smali.dexlib2.immutable.reference.ImmutableTypeReference; import com.google.common.base.Charsets; import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; @@ -76,11 +81,6 @@ import java.util.stream.Stream; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeModel; import javax.xml.parsers.ParserConfigurationException; -import org.jf.dexlib2.dexbacked.DexBackedDexFile; -import org.jf.dexlib2.iface.reference.FieldReference; -import org.jf.dexlib2.iface.reference.MethodReference; -import org.jf.dexlib2.iface.reference.Reference; -import org.jf.dexlib2.immutable.reference.ImmutableTypeReference; import org.xml.sax.SAXException; /** diff --git a/bazel/kotlin.bzl b/bazel/kotlin.bzl index 6912e09acb..5c31dec155 100644 --- a/bazel/kotlin.bzl +++ b/bazel/kotlin.bzl @@ -55,8 +55,8 @@ def kotlin_compile(ctx, name, srcs, deps, friend_jars, out, out_ijar, java_runti args.add("-Xsam-conversions=class") # Needed for Gradle configuration caching (see b/202512551). tools = [] + tools.append(ctx.file._jvm_abi_gen) if out_ijar: - tools.append(ctx.file._jvm_abi_gen) args.add(ctx.file._jvm_abi_gen, format = "-Xplugin=%s") args.add("-P", out_ijar, format = "plugin:org.jetbrains.kotlin.jvm.abi:outputDir=%s") @@ -64,8 +64,8 @@ def kotlin_compile(ctx, name, srcs, deps, friend_jars, out, out_ijar, java_runti args.add("-Xallow-unstable-dependencies") # Use the Compiler Compose plugin + tools.append(ctx.file._compose_plugin) if ctx.attr.kotlin_use_compose: - tools.append(ctx.file._compose_plugin) args.add(ctx.file._compose_plugin, format = "-Xplugin=%s") args.add("-P", "plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=true") @@ -264,12 +264,11 @@ def _kotlin_library_impl(ctx): fail("Unexpected file type passed to kotlin_library target: " + src.path) name = ctx.label.name - use_ijar = not ctx.attr.testonly java_jar = ctx.actions.declare_file(name + ".java.jar") if java_srcs or source_jars else None kotlin_jar = ctx.actions.declare_file(name + ".kotlin.jar") if kotlin_srcs else None - kotlin_ijar = ctx.actions.declare_file(name + ".kotlin-ijar.jar") if kotlin_srcs and use_ijar else None - full_ijar = ctx.actions.declare_file(name + ".merged-ijar-kotlin-lib.jar") if use_ijar else None + kotlin_ijar = ctx.actions.declare_file(name + ".kotlin-ijar.jar") if kotlin_srcs else None + full_ijar = ctx.actions.declare_file(name + ".merged-ijar-kotlin-lib.jar") deps = [dep[JavaInfo] for dep in ctx.attr.deps + ctx.attr.exports] java_info_deps = [dep[JavaInfo] for dep in ctx.attr.deps] @@ -300,8 +299,7 @@ def _kotlin_library_impl(ctx): transitive_classpath = True, # Matches Java rules (sans strict-deps enforcement) )] jars += [kotlin_jar] - if use_ijar: - ijars += [kotlin_ijar] + ijars += [kotlin_ijar] # Resources. # We only add Resources to the output jar, but exclude them from the compile_jar. @@ -324,12 +322,10 @@ def _kotlin_library_impl(ctx): javac_opts = java_common.default_javac_opts(java_toolchain = java_toolchain) + ctx.attr.javacopts, java_toolchain = java_toolchain, plugins = [plugin[JavaPluginInfo] for plugin in ctx.attr.plugins], - # TODO(b/216385876) After updating to Bazel 5.0, use enable_compile_jar_action = use_ijar, ) jars += [java_jar] - if use_ijar: - ijars += java_provider.compile_jars.to_list() + ijars += java_provider.compile_jars.to_list() run_singlejar( ctx = ctx, @@ -338,16 +334,15 @@ def _kotlin_library_impl(ctx): # allow_duplicates = True, # TODO: Ideally we could be more strict here. ) - if use_ijar: - run_singlejar( - ctx = ctx, - jars = ijars, - out = full_ijar, - # Even if there are no duplicates in the jars, there might be duplicates in the ijars. - # For example, protoc adds a stripped version of its runtime dependency under - # META-INF/TRANSITIVE, which results in duplicates for multiple proto dependencies. - allow_duplicates = True, - ) + run_singlejar( + ctx = ctx, + jars = ijars, + out = full_ijar, + # Even if there are no duplicates in the jars, there might be duplicates in the ijars. + # For example, protoc adds a stripped version of its runtime dependency under + # META-INF/TRANSITIVE, which results in duplicates for multiple proto dependencies. + allow_duplicates = True, + ) _sources(ctx, java_srcs + kotlin_srcs, source_jars, ctx.outputs.source_jar, java_toolchain) @@ -415,6 +410,11 @@ _kotlin_library = rule( cfg = "host", allow_single_file = [".jar"], ), + "_compose_plugin": attr.label( + default = Label("//prebuilts/tools/common/m2:compose-compiler-hosted"), + cfg = "host", + allow_single_file = [".jar"], + ), "_zipper": attr.label( default = Label("@bazel_tools//tools/zip:zipper"), cfg = "host", diff --git a/bazel/maven/BUILD.maven b/bazel/maven/BUILD.maven index fc5862c21a..c0e79b6787 100644 --- a/bazel/maven/BUILD.maven +++ b/bazel/maven/BUILD.maven @@ -723,30 +723,6 @@ maven_import( ) maven_artifact( - name = "com.github.gundy.semver4j_0.16.4", - pom = "repository/com/github/gundy/semver4j/0.16.4/semver4j-0.16.4.pom", - repo_root_path = "repository", - repo_path = "com/github/gundy/semver4j/0.16.4", - deps = [ - "org.antlr.antlr4-runtime_4.5.2-1", - ], - visibility = ["//visibility:public"], -) - -maven_import( - name = "com.github.gundy.semver4j.nodeps", - classifiers = [], - jars = [ - "repository/com/github/gundy/semver4j/0.16.4/semver4j-0.16.4-nodeps.jar" - ], - original_deps = [], - pom = "repository/com/github/gundy/semver4j/0.16.4/semver4j-0.16.4.pom", - repo_root_path = "repository", - repo_path = "com/github/gundy/semver4j/0.16.4", - visibility = ["//visibility:public"], -) - -maven_artifact( name = "com.github.javaparser.javaparser-core_3.24.0", pom = "repository/com/github/javaparser/javaparser-core/3.24.0/javaparser-core-3.24.0.pom", repo_root_path = "repository", @@ -1318,6 +1294,8 @@ maven_import( ], exports = [ "org.jetbrains.kotlin.kotlin-stdlib-jdk8", + ], + deps = [ "org.jetbrains.kotlin.kotlin-gradle-plugin-api", "org.jetbrains.kotlin.kotlin-gradle-plugin", ], @@ -2910,27 +2888,6 @@ maven_import( ) maven_artifact( - name = "de.undercouch.gradle-download-task_4.1.1", - pom = "repository/de/undercouch/gradle-download-task/4.1.1/gradle-download-task-4.1.1.pom", - repo_root_path = "repository", - repo_path = "de/undercouch/gradle-download-task/4.1.1", - visibility = ["//visibility:public"], -) - -maven_import( - name = "de.undercouch.gradle-download-task", - classifiers = [], - jars = [ - "repository/de/undercouch/gradle-download-task/4.1.1/gradle-download-task-4.1.1.jar" - ], - original_deps = [], - pom = "repository/de/undercouch/gradle-download-task/4.1.1/gradle-download-task-4.1.1.pom", - repo_root_path = "repository", - repo_path = "de/undercouch/gradle-download-task/4.1.1", - visibility = ["//visibility:public"], -) - -maven_artifact( name = "gradle.plugin.org.jetbrains.gradle.plugin.idea-ext.gradle-idea-ext_0.8.1", pom = "repository/gradle/plugin/org/jetbrains/gradle/plugin/idea-ext/gradle-idea-ext/0.8.1/gradle-idea-ext-0.8.1.pom", repo_root_path = "repository", @@ -8126,12 +8083,12 @@ maven_import( ) maven_artifact( - name = "org.jetbrains.kotlin.jvm.org.jetbrains.kotlin.jvm.gradle.plugin_1.7.10", - pom = "repository/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.7.10/org.jetbrains.kotlin.jvm.gradle.plugin-1.7.10.pom", + name = "org.jetbrains.kotlin.jvm.org.jetbrains.kotlin.jvm.gradle.plugin_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.8.20-RC2/org.jetbrains.kotlin.jvm.gradle.plugin-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.7.10", + repo_path = "org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-gradle-plugin_1.7.10", + "org.jetbrains.kotlin.kotlin-gradle-plugin_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8145,21 +8102,21 @@ maven_import( "org.jetbrains.kotlin.kotlin-gradle-plugin", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-gradle-plugin_1.7.10", + "org.jetbrains.kotlin.kotlin-gradle-plugin_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.7.10/org.jetbrains.kotlin.jvm.gradle.plugin-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.8.20-RC2/org.jetbrains.kotlin.jvm.gradle.plugin-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.7.10", + repo_path = "org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-android-extensions_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-android-extensions/1.7.10/kotlin-android-extensions-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-android-extensions_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-android-extensions/1.8.20-RC2/kotlin-android-extensions-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-android-extensions/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-android-extensions/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.10", + "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8168,27 +8125,27 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-android-extensions", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-android-extensions/1.7.10/kotlin-android-extensions-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-android-extensions/1.8.20-RC2/kotlin-android-extensions-1.8.20-RC2.jar" ], deps = [ "org.jetbrains.kotlin.kotlin-compiler-embeddable", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.10", + "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-android-extensions/1.7.10/kotlin-android-extensions-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-android-extensions/1.8.20-RC2/kotlin-android-extensions-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-android-extensions/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-android-extensions/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-annotation-processing-gradle_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.7.10/kotlin-annotation-processing-gradle-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-annotation-processing-gradle_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.8.20-RC2/kotlin-annotation-processing-gradle-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.10", + "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8197,51 +8154,27 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-annotation-processing-gradle", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.7.10/kotlin-annotation-processing-gradle-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.8.20-RC2/kotlin-annotation-processing-gradle-1.8.20-RC2.jar" ], deps = [ "org.jetbrains.kotlin.kotlin-compiler-embeddable", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.10", - ], - pom = "repository/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.7.10/kotlin-annotation-processing-gradle-1.7.10.pom", - repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.7.10", - visibility = ["//visibility:public"], -) - -maven_artifact( - name = "org.jetbrains.kotlin.kotlin-build-common_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-build-common/1.7.10/kotlin-build-common-1.7.10.pom", - repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-build-common/1.7.10", - visibility = ["//visibility:public"], -) - -maven_import( - name = "org.jetbrains.kotlin.kotlin-build-common", - classifiers = [], - jars = [ - "repository/org/jetbrains/kotlin/kotlin-build-common/1.7.10/kotlin-build-common-1.7.10.jar" + "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.8.20-RC2", ], - original_deps = [], - pom = "repository/org/jetbrains/kotlin/kotlin-build-common/1.7.10/kotlin-build-common-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.8.20-RC2/kotlin-annotation-processing-gradle-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-build-common/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.10/kotlin-compiler-embeddable-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.8.20-RC2/kotlin-compiler-embeddable-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-compiler-embeddable/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", - "org.jetbrains.kotlin.kotlin-script-runtime_1.7.10", - "org.jetbrains.kotlin.kotlin-reflect_1.7.10", - "org.jetbrains.kotlin.kotlin-daemon-embeddable_1.7.10", + "org.jetbrains.kotlin.kotlin-daemon-embeddable_1.8.20-RC2", "org.jetbrains.intellij.deps.trove4j_1.0.20200330", "net.java.dev.jna.jna_5.6.0", ], @@ -8252,42 +8185,35 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-compiler-embeddable", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.10/kotlin-compiler-embeddable-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.8.20-RC2/kotlin-compiler-embeddable-1.8.20-RC2.jar" ], exports = [ - "org.jetbrains.kotlin.kotlin-script-runtime", - "org.jetbrains.kotlin.kotlin-reflect", "org.jetbrains.intellij.deps.trove4j", - "net.java.dev.jna.jna", ], deps = [ - "org.jetbrains.kotlin.kotlin-stdlib", "org.jetbrains.kotlin.kotlin-daemon-embeddable", + "net.java.dev.jna.jna", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", - "org.jetbrains.kotlin.kotlin-script-runtime_1.7.10", - "org.jetbrains.kotlin.kotlin-reflect_1.7.10", - "org.jetbrains.kotlin.kotlin-daemon-embeddable_1.7.10", + "org.jetbrains.kotlin.kotlin-daemon-embeddable_1.8.20-RC2", "org.jetbrains.intellij.deps.trove4j_1.0.20200330", "net.java.dev.jna.jna_5.6.0", ], - pom = "repository/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.10/kotlin-compiler-embeddable-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.8.20-RC2/kotlin-compiler-embeddable-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-compiler-embeddable/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-compiler-runner_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-compiler-runner/1.7.10/kotlin-compiler-runner-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-compiler-runner_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-compiler-runner/1.8.20-RC2/kotlin-compiler-runner-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-compiler-runner/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-compiler-runner/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-build-common_1.7.10", - "org.jetbrains.kotlin.kotlin-daemon-client_1.7.10", + "org.jetbrains.kotlin.kotlin-daemon-client_1.8.20-RC2", "org.jetbrains.kotlinx.kotlinx-coroutines-core-jvm_1.5.0", - "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.10", + "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8296,35 +8222,33 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-compiler-runner", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-compiler-runner/1.7.10/kotlin-compiler-runner-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-compiler-runner/1.8.20-RC2/kotlin-compiler-runner-1.8.20-RC2.jar" ], deps = [ - "org.jetbrains.kotlin.kotlin-build-common", "org.jetbrains.kotlin.kotlin-daemon-client", "org.jetbrains.kotlinx.kotlinx-coroutines-core-jvm", "org.jetbrains.kotlin.kotlin-compiler-embeddable", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-build-common_1.7.10", - "org.jetbrains.kotlin.kotlin-daemon-client_1.7.10", + "org.jetbrains.kotlin.kotlin-daemon-client_1.8.20-RC2", "org.jetbrains.kotlinx.kotlinx-coroutines-core-jvm_1.5.0", - "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.10", + "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-compiler-runner/1.7.10/kotlin-compiler-runner-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-compiler-runner/1.8.20-RC2/kotlin-compiler-runner-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-compiler-runner/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-compiler-runner/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-compiler_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-compiler/1.7.10/kotlin-compiler-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-compiler_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-compiler/1.8.20-RC2/kotlin-compiler-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-compiler/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-compiler/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", - "org.jetbrains.kotlin.kotlin-script-runtime_1.7.10", - "org.jetbrains.kotlin.kotlin-reflect_1.7.10", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-script-runtime_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-reflect_1.6.10", "org.jetbrains.intellij.deps.trove4j_1.0.20200330", ], visibility = ["//visibility:public"], @@ -8334,7 +8258,7 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-compiler", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-compiler/1.7.10/kotlin-compiler-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-compiler/1.8.20-RC2/kotlin-compiler-1.8.20-RC2.jar" ], exports = [ "org.jetbrains.kotlin.kotlin-stdlib", @@ -8343,22 +8267,22 @@ maven_import( "org.jetbrains.intellij.deps.trove4j", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", - "org.jetbrains.kotlin.kotlin-script-runtime_1.7.10", - "org.jetbrains.kotlin.kotlin-reflect_1.7.10", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-script-runtime_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-reflect_1.6.10", "org.jetbrains.intellij.deps.trove4j_1.0.20200330", ], - pom = "repository/org/jetbrains/kotlin/kotlin-compiler/1.7.10/kotlin-compiler-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-compiler/1.8.20-RC2/kotlin-compiler-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-compiler/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-compiler/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-daemon-client_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-daemon-client/1.7.10/kotlin-daemon-client-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-daemon-client_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-daemon-client/1.8.20-RC2/kotlin-daemon-client-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-daemon-client/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-daemon-client/1.8.20-RC2", deps = [ "org.jetbrains.kotlinx.kotlinx-coroutines-core-jvm_1.5.0", ], @@ -8369,7 +8293,7 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-daemon-client", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-daemon-client/1.7.10/kotlin-daemon-client-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-daemon-client/1.8.20-RC2/kotlin-daemon-client-1.8.20-RC2.jar" ], deps = [ "org.jetbrains.kotlinx.kotlinx-coroutines-core-jvm", @@ -8377,17 +8301,17 @@ maven_import( original_deps = [ "org.jetbrains.kotlinx.kotlinx-coroutines-core-jvm_1.5.0", ], - pom = "repository/org/jetbrains/kotlin/kotlin-daemon-client/1.7.10/kotlin-daemon-client-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-daemon-client/1.8.20-RC2/kotlin-daemon-client-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-daemon-client/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-daemon-client/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-daemon-embeddable_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.10/kotlin-daemon-embeddable-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-daemon-embeddable_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.8.20-RC2/kotlin-daemon-embeddable-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-daemon-embeddable/1.8.20-RC2", visibility = ["//visibility:public"], ) @@ -8395,24 +8319,52 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-daemon-embeddable", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.10/kotlin-daemon-embeddable-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.8.20-RC2/kotlin-daemon-embeddable-1.8.20-RC2.jar" ], original_deps = [], - pom = "repository/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.10/kotlin-daemon-embeddable-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.8.20-RC2/kotlin-daemon-embeddable-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-daemon-embeddable/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-gradle-plugin-api_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.10/kotlin-gradle-plugin-api-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-gradle-plugin-annotations_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-annotations/1.8.20-RC2/kotlin-gradle-plugin-annotations-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-annotations/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-native-utils_1.7.10", - "org.jetbrains.kotlin.kotlin-project-model_1.7.10", - "org.jetbrains.kotlin.kotlin-tooling-core_1.7.10", + "org.jetbrains.kotlin.kotlin-gradle-plugins-bom_1.8.20-RC2", + ], + visibility = ["//visibility:public"], +) + +maven_import( + name = "org.jetbrains.kotlin.kotlin-gradle-plugin-annotations", + classifiers = [], + jars = [ + "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-annotations/1.8.20-RC2/kotlin-gradle-plugin-annotations-1.8.20-RC2.jar" + ], + original_deps = [ + "org.jetbrains.kotlin.kotlin-gradle-plugins-bom_1.8.20-RC2", + ], + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-annotations/1.8.20-RC2/kotlin-gradle-plugin-annotations-1.8.20-RC2.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-annotations/1.8.20-RC2", + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "org.jetbrains.kotlin.kotlin-gradle-plugin-api_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.8.20-RC2/kotlin-gradle-plugin-api-1.8.20-RC2.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.8.20-RC2", + deps = [ + "org.jetbrains.kotlin.kotlin-gradle-plugin-annotations_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-native-utils_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-project-model_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-tooling-core_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-gradle-plugins-bom_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8421,9 +8373,10 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-gradle-plugin-api", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.10/kotlin-gradle-plugin-api-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.8.20-RC2/kotlin-gradle-plugin-api-1.8.20-RC2.jar" ], exports = [ + "org.jetbrains.kotlin.kotlin-gradle-plugin-annotations", "org.jetbrains.kotlin.kotlin-native-utils", "org.jetbrains.kotlin.kotlin-project-model", ], @@ -8431,21 +8384,56 @@ maven_import( "org.jetbrains.kotlin.kotlin-tooling-core", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-native-utils_1.7.10", - "org.jetbrains.kotlin.kotlin-project-model_1.7.10", - "org.jetbrains.kotlin.kotlin-tooling-core_1.7.10", + "org.jetbrains.kotlin.kotlin-gradle-plugin-annotations_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-native-utils_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-project-model_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-tooling-core_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-gradle-plugins-bom_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.10/kotlin-gradle-plugin-api-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.8.20-RC2/kotlin-gradle-plugin-api-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-gradle-plugin-idea_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.7.10/kotlin-gradle-plugin-idea-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-gradle-plugin-idea-proto_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.8.20-RC2/kotlin-gradle-plugin-idea-proto-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.8.20-RC2", + deps = [ + "org.jetbrains.kotlin.kotlin-gradle-plugin-idea_1.8.20-RC2", + ], + visibility = ["//visibility:public"], +) + +maven_import( + name = "org.jetbrains.kotlin.kotlin-gradle-plugin-idea-proto", + classifiers = [], + jars = [ + "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.8.20-RC2/kotlin-gradle-plugin-idea-proto-1.8.20-RC2.jar" + ], + deps = [ + "org.jetbrains.kotlin.kotlin-gradle-plugin-idea", + ], + original_deps = [ + "org.jetbrains.kotlin.kotlin-gradle-plugin-idea_1.8.20-RC2", + ], + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.8.20-RC2/kotlin-gradle-plugin-idea-proto-1.8.20-RC2.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-idea-proto/1.8.20-RC2", + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "org.jetbrains.kotlin.kotlin-gradle-plugin-idea_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.8.20-RC2/kotlin-gradle-plugin-idea-1.8.20-RC2.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.8.20-RC2", + deps = [ + "org.jetbrains.kotlin.kotlin-tooling-core_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-gradle-plugin-annotations_1.8.20-RC2", + ], visibility = ["//visibility:public"], ) @@ -8453,20 +8441,32 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-gradle-plugin-idea", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.7.10/kotlin-gradle-plugin-idea-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.8.20-RC2/kotlin-gradle-plugin-idea-1.8.20-RC2.jar" ], - original_deps = [], - pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.7.10/kotlin-gradle-plugin-idea-1.7.10.pom", + exports = [ + "org.jetbrains.kotlin.kotlin-gradle-plugin-annotations", + ], + deps = [ + "org.jetbrains.kotlin.kotlin-tooling-core", + ], + original_deps = [ + "org.jetbrains.kotlin.kotlin-tooling-core_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-gradle-plugin-annotations_1.8.20-RC2", + ], + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.8.20-RC2/kotlin-gradle-plugin-idea-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-gradle-plugin-model_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.7.10/kotlin-gradle-plugin-model-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-gradle-plugin-model_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.8.20-RC2/kotlin-gradle-plugin-model-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.8.20-RC2", + deps = [ + "org.jetbrains.kotlin.kotlin-gradle-plugins-bom_1.8.20-RC2", + ], visibility = ["//visibility:public"], ) @@ -8474,38 +8474,37 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-gradle-plugin-model", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.7.10/kotlin-gradle-plugin-model-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.8.20-RC2/kotlin-gradle-plugin-model-1.8.20-RC2.jar" ], - original_deps = [], - pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.7.10/kotlin-gradle-plugin-model-1.7.10.pom", + original_deps = [ + "org.jetbrains.kotlin.kotlin-gradle-plugins-bom_1.8.20-RC2", + ], + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.8.20-RC2/kotlin-gradle-plugin-model-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-gradle-plugin_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin/1.7.10/kotlin-gradle-plugin-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-gradle-plugin_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin/1.8.20-RC2/kotlin-gradle-plugin-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-gradle-plugin-model_1.7.10", - "org.jetbrains.kotlin.kotlin-tooling-core_1.7.10", - "org.jetbrains.kotlin.kotlin-gradle-plugin-idea_1.7.10", - "org.jetbrains.kotlin.kotlin-util-klib_1.7.10", - "org.jetbrains.kotlin.kotlin-klib-commonizer-api_1.7.10", - "org.jetbrains.kotlin.kotlin-tooling-metadata_1.7.10", - "org.jetbrains.kotlin.kotlin-project-model_1.7.10", - "com.google.code.gson.gson_2.8.9", - "com.google.guava.guava_29.0-jre", - "de.undercouch.gradle-download-task_4.1.1", - "com.github.gundy.semver4j_0.16.4", - "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.10", - "org.jetbrains.kotlin.kotlin-annotation-processing-gradle_1.7.10", - "org.jetbrains.kotlin.kotlin-android-extensions_1.7.10", - "org.jetbrains.kotlin.kotlin-compiler-runner_1.7.10", - "org.jetbrains.kotlin.kotlin-scripting-compiler-embeddable_1.7.10", - "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable_1.7.10", + "org.jetbrains.kotlin.kotlin-gradle-plugin-model_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-tooling-core_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-gradle-plugin-idea_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-gradle-plugin-idea-proto_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-util-klib_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-klib-commonizer-api_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-project-model_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-annotation-processing-gradle_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-android-extensions_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-compiler-runner_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-scripting-compiler-embeddable_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-gradle-plugins-bom_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8514,22 +8513,18 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-gradle-plugin", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-gradle-plugin/1.7.10/kotlin-gradle-plugin-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-gradle-plugin/1.8.20-RC2/kotlin-gradle-plugin-1.8.20-RC2.jar" ], exports = [ "org.jetbrains.kotlin.kotlin-gradle-plugin-model", "org.jetbrains.kotlin.kotlin-tooling-core", + "org.jetbrains.kotlin.kotlin-project-model", ], deps = [ "org.jetbrains.kotlin.kotlin-gradle-plugin-idea", + "org.jetbrains.kotlin.kotlin-gradle-plugin-idea-proto", "org.jetbrains.kotlin.kotlin-util-klib", "org.jetbrains.kotlin.kotlin-klib-commonizer-api", - "org.jetbrains.kotlin.kotlin-tooling-metadata", - "org.jetbrains.kotlin.kotlin-project-model", - "com.google.code.gson.gson", - "com.google.guava.guava", - "de.undercouch.gradle-download-task", - "com.github.gundy.semver4j.nodeps", "org.jetbrains.kotlin.kotlin-compiler-embeddable", "org.jetbrains.kotlin.kotlin-annotation-processing-gradle", "org.jetbrains.kotlin.kotlin-android-extensions", @@ -8538,37 +8533,54 @@ maven_import( "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-gradle-plugin-model_1.7.10", - "org.jetbrains.kotlin.kotlin-tooling-core_1.7.10", - "org.jetbrains.kotlin.kotlin-gradle-plugin-idea_1.7.10", - "org.jetbrains.kotlin.kotlin-util-klib_1.7.10", - "org.jetbrains.kotlin.kotlin-klib-commonizer-api_1.7.10", - "org.jetbrains.kotlin.kotlin-tooling-metadata_1.7.10", - "org.jetbrains.kotlin.kotlin-project-model_1.7.10", - "com.google.code.gson.gson_2.8.9", - "com.google.guava.guava_29.0-jre", - "de.undercouch.gradle-download-task_4.1.1", - "com.github.gundy.semver4j_0.16.4", - "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.10", - "org.jetbrains.kotlin.kotlin-annotation-processing-gradle_1.7.10", - "org.jetbrains.kotlin.kotlin-android-extensions_1.7.10", - "org.jetbrains.kotlin.kotlin-compiler-runner_1.7.10", - "org.jetbrains.kotlin.kotlin-scripting-compiler-embeddable_1.7.10", - "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable_1.7.10", + "org.jetbrains.kotlin.kotlin-gradle-plugin-model_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-tooling-core_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-gradle-plugin-idea_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-gradle-plugin-idea-proto_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-util-klib_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-klib-commonizer-api_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-project-model_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-annotation-processing-gradle_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-android-extensions_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-compiler-runner_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-scripting-compiler-embeddable_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-gradle-plugins-bom_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin/1.7.10/kotlin-gradle-plugin-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin/1.8.20-RC2/kotlin-gradle-plugin-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-klib-commonizer-api_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.7.10/kotlin-klib-commonizer-api-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-gradle-plugins-bom_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugins-bom/1.8.20-RC2/kotlin-gradle-plugins-bom-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugins-bom/1.8.20-RC2", + visibility = ["//visibility:public"], +) + +maven_import( + name = "org.jetbrains.kotlin.kotlin-gradle-plugins-bom", + classifiers = [], + jars = [ + ], + original_deps = [], + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugins-bom/1.8.20-RC2/kotlin-gradle-plugins-bom-1.8.20-RC2.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugins-bom/1.8.20-RC2", + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "org.jetbrains.kotlin.kotlin-klib-commonizer-api_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.8.20-RC2/kotlin-klib-commonizer-api-1.8.20-RC2.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-native-utils_1.7.10", + "org.jetbrains.kotlin.kotlin-native-utils_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8577,27 +8589,28 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-klib-commonizer-api", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.7.10/kotlin-klib-commonizer-api-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.8.20-RC2/kotlin-klib-commonizer-api-1.8.20-RC2.jar" ], - deps = [ + exports = [ "org.jetbrains.kotlin.kotlin-native-utils", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-native-utils_1.7.10", + "org.jetbrains.kotlin.kotlin-native-utils_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.7.10/kotlin-klib-commonizer-api-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.8.20-RC2/kotlin-klib-commonizer-api-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-native-utils_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-native-utils/1.7.10/kotlin-native-utils-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-native-utils_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-native-utils/1.8.20-RC2/kotlin-native-utils-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-native-utils/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-native-utils/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-util-io_1.7.10", + "org.jetbrains.kotlin.kotlin-util-io_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-gradle-plugins-bom_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8606,27 +8619,28 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-native-utils", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-native-utils/1.7.10/kotlin-native-utils-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-native-utils/1.8.20-RC2/kotlin-native-utils-1.8.20-RC2.jar" ], exports = [ "org.jetbrains.kotlin.kotlin-util-io", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-util-io_1.7.10", + "org.jetbrains.kotlin.kotlin-util-io_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-gradle-plugins-bom_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-native-utils/1.7.10/kotlin-native-utils-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-native-utils/1.8.20-RC2/kotlin-native-utils-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-native-utils/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-native-utils/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-project-model_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-project-model/1.7.10/kotlin-project-model-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-project-model_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-project-model/1.8.20-RC2/kotlin-project-model-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-project-model/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-project-model/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-tooling-core_1.7.10", + "org.jetbrains.kotlin.kotlin-tooling-core_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8635,27 +8649,27 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-project-model", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-project-model/1.7.10/kotlin-project-model-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-project-model/1.8.20-RC2/kotlin-project-model-1.8.20-RC2.jar" ], - exports = [ + deps = [ "org.jetbrains.kotlin.kotlin-tooling-core", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-tooling-core_1.7.10", + "org.jetbrains.kotlin.kotlin-tooling-core_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-project-model/1.7.10/kotlin-project-model-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-project-model/1.8.20-RC2/kotlin-project-model-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-project-model/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-project-model/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-reflect_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-reflect/1.7.10/kotlin-reflect-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-reflect_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-reflect/1.8.20-RC2/kotlin-reflect-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-reflect/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-reflect/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8664,25 +8678,25 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-reflect", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-reflect/1.7.10/kotlin-reflect-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-reflect/1.8.20-RC2/kotlin-reflect-1.8.20-RC2.jar" ], exports = [ "org.jetbrains.kotlin.kotlin-stdlib", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-reflect/1.7.10/kotlin-reflect-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-reflect/1.8.20-RC2/kotlin-reflect-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-reflect/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-reflect/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-script-runtime_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-script-runtime/1.7.10/kotlin-script-runtime-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-script-runtime_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-script-runtime/1.8.20-RC2/kotlin-script-runtime-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-script-runtime/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-script-runtime/1.8.20-RC2", visibility = ["//visibility:public"], ) @@ -8690,20 +8704,20 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-script-runtime", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-script-runtime/1.7.10/kotlin-script-runtime-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-script-runtime/1.8.20-RC2/kotlin-script-runtime-1.8.20-RC2.jar" ], original_deps = [], - pom = "repository/org/jetbrains/kotlin/kotlin-script-runtime/1.7.10/kotlin-script-runtime-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-script-runtime/1.8.20-RC2/kotlin-script-runtime-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-script-runtime/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-script-runtime/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-scripting-common_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-scripting-common/1.7.10/kotlin-scripting-common-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-scripting-common_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-scripting-common/1.8.20-RC2/kotlin-scripting-common-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-scripting-common/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-scripting-common/1.8.20-RC2", visibility = ["//visibility:public"], ) @@ -8711,22 +8725,22 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-scripting-common", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-scripting-common/1.7.10/kotlin-scripting-common-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-scripting-common/1.8.20-RC2/kotlin-scripting-common-1.8.20-RC2.jar" ], original_deps = [], - pom = "repository/org/jetbrains/kotlin/kotlin-scripting-common/1.7.10/kotlin-scripting-common-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-scripting-common/1.8.20-RC2/kotlin-scripting-common-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-scripting-common/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-scripting-common/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-scripting-compiler-embeddable_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.10/kotlin-scripting-compiler-embeddable-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-scripting-compiler-embeddable_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.8.20-RC2/kotlin-scripting-compiler-embeddable-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable_1.7.10", + "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8735,28 +8749,28 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-scripting-compiler-embeddable", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.10/kotlin-scripting-compiler-embeddable-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.8.20-RC2/kotlin-scripting-compiler-embeddable-1.8.20-RC2.jar" ], deps = [ "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable_1.7.10", + "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.10/kotlin-scripting-compiler-embeddable-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.8.20-RC2/kotlin-scripting-compiler-embeddable-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.10/kotlin-scripting-compiler-impl-embeddable-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.8.20-RC2/kotlin-scripting-compiler-impl-embeddable-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-scripting-common_1.7.10", - "org.jetbrains.kotlin.kotlin-scripting-jvm_1.7.10", + "org.jetbrains.kotlin.kotlin-scripting-common_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-scripting-jvm_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8765,29 +8779,29 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.10/kotlin-scripting-compiler-impl-embeddable-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.8.20-RC2/kotlin-scripting-compiler-impl-embeddable-1.8.20-RC2.jar" ], deps = [ "org.jetbrains.kotlin.kotlin-scripting-common", "org.jetbrains.kotlin.kotlin-scripting-jvm", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-scripting-common_1.7.10", - "org.jetbrains.kotlin.kotlin-scripting-jvm_1.7.10", + "org.jetbrains.kotlin.kotlin-scripting-common_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-scripting-jvm_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.10/kotlin-scripting-compiler-impl-embeddable-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.8.20-RC2/kotlin-scripting-compiler-impl-embeddable-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-scripting-jvm_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.10/kotlin-scripting-jvm-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-scripting-jvm_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-scripting-jvm/1.8.20-RC2/kotlin-scripting-jvm-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-scripting-jvm/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-scripting-common_1.7.10", + "org.jetbrains.kotlin.kotlin-scripting-common_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8796,25 +8810,25 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-scripting-jvm", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.10/kotlin-scripting-jvm-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-scripting-jvm/1.8.20-RC2/kotlin-scripting-jvm-1.8.20-RC2.jar" ], deps = [ "org.jetbrains.kotlin.kotlin-scripting-common", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-scripting-common_1.7.10", + "org.jetbrains.kotlin.kotlin-scripting-common_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.10/kotlin-scripting-jvm-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-scripting-jvm/1.8.20-RC2/kotlin-scripting-jvm-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-scripting-jvm/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-stdlib-common_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.10/kotlin-stdlib-common-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-stdlib-common_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-common/1.8.20-RC2/kotlin-stdlib-common-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-stdlib-common/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-stdlib-common/1.8.20-RC2", visibility = ["//visibility:public"], ) @@ -8822,22 +8836,22 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-stdlib-common", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.10/kotlin-stdlib-common-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-stdlib-common/1.8.20-RC2/kotlin-stdlib-common-1.8.20-RC2.jar" ], original_deps = [], - pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.10/kotlin-stdlib-common-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-common/1.8.20-RC2/kotlin-stdlib-common-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-stdlib-common/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-stdlib-common/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-stdlib-jdk7_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.10/kotlin-stdlib-jdk7-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-stdlib-jdk7_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.8.20-RC2/kotlin-stdlib-jdk7-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8846,28 +8860,28 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-stdlib-jdk7", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.10/kotlin-stdlib-jdk7-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.8.20-RC2/kotlin-stdlib-jdk7-1.8.20-RC2.jar" ], exports = [ "org.jetbrains.kotlin.kotlin-stdlib", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.10/kotlin-stdlib-jdk7-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.8.20-RC2/kotlin-stdlib-jdk7-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-stdlib-jdk8_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.10/kotlin-stdlib-jdk8-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-stdlib-jdk8_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.8.20-RC2/kotlin-stdlib-jdk8-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", - "org.jetbrains.kotlin.kotlin-stdlib-jdk7_1.7.10", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-stdlib-jdk7_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -8876,29 +8890,29 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-stdlib-jdk8", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.10/kotlin-stdlib-jdk8-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.8.20-RC2/kotlin-stdlib-jdk8-1.8.20-RC2.jar" ], exports = [ "org.jetbrains.kotlin.kotlin-stdlib", "org.jetbrains.kotlin.kotlin-stdlib-jdk7", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", - "org.jetbrains.kotlin.kotlin-stdlib-jdk7_1.7.10", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.20-RC2", + "org.jetbrains.kotlin.kotlin-stdlib-jdk7_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.10/kotlin-stdlib-jdk8-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.8.20-RC2/kotlin-stdlib-jdk8-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-stdlib/1.7.10/kotlin-stdlib-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-stdlib_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-stdlib/1.8.20-RC2/kotlin-stdlib-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-stdlib/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-stdlib/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-stdlib-common_1.7.10", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.8.20-RC2", "org.jetbrains.annotations_13.0", ], visibility = ["//visibility:public"], @@ -8908,106 +8922,114 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-stdlib", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-stdlib/1.7.10/kotlin-stdlib-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-stdlib/1.8.20-RC2/kotlin-stdlib-1.8.20-RC2.jar" ], exports = [ "org.jetbrains.kotlin.kotlin-stdlib-common", "org.jetbrains.annotations", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-stdlib-common_1.7.10", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.8.20-RC2", "org.jetbrains.annotations_13.0", ], - pom = "repository/org/jetbrains/kotlin/kotlin-stdlib/1.7.10/kotlin-stdlib-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-stdlib/1.8.20-RC2/kotlin-stdlib-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-stdlib/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-stdlib/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-test_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-test/1.7.10/kotlin-test-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-test-junit_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-test-junit/1.8.20-RC2/kotlin-test-junit-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-test/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-test-junit/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + "org.jetbrains.kotlin.kotlin-test_1.8.20-RC2", + "junit.junit_4.13.2", ], visibility = ["//visibility:public"], ) maven_import( - name = "org.jetbrains.kotlin.kotlin-test", + name = "org.jetbrains.kotlin.kotlin-test-junit", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-test/1.7.10/kotlin-test-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-test-junit/1.8.20-RC2/kotlin-test-junit-1.8.20-RC2.jar" ], exports = [ - "org.jetbrains.kotlin.kotlin-stdlib", + "org.jetbrains.kotlin.kotlin-test", + "junit.junit", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + "org.jetbrains.kotlin.kotlin-test_1.8.20-RC2", + "junit.junit_4.13.2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-test/1.7.10/kotlin-test-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-test-junit/1.8.20-RC2/kotlin-test-junit-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-test/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-test-junit/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-tooling-core_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-tooling-core/1.7.10/kotlin-tooling-core-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-test_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-test/1.8.20-RC2/kotlin-test-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-tooling-core/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-test/1.8.20-RC2", + deps = [ + "org.jetbrains.kotlin.kotlin-stdlib_1.8.20-RC2", + ], visibility = ["//visibility:public"], ) maven_import( - name = "org.jetbrains.kotlin.kotlin-tooling-core", + name = "org.jetbrains.kotlin.kotlin-test", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-tooling-core/1.7.10/kotlin-tooling-core-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-test/1.8.20-RC2/kotlin-test-1.8.20-RC2.jar" ], - original_deps = [], - pom = "repository/org/jetbrains/kotlin/kotlin-tooling-core/1.7.10/kotlin-tooling-core-1.7.10.pom", + exports = [ + "org.jetbrains.kotlin.kotlin-stdlib", + ], + original_deps = [ + "org.jetbrains.kotlin.kotlin-stdlib_1.8.20-RC2", + ], + pom = "repository/org/jetbrains/kotlin/kotlin-test/1.8.20-RC2/kotlin-test-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-tooling-core/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-test/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-tooling-metadata_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-tooling-metadata/1.7.10/kotlin-tooling-metadata-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-tooling-core_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-tooling-core/1.8.20-RC2/kotlin-tooling-core-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-tooling-metadata/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-tooling-core/1.8.20-RC2", deps = [ - "com.google.code.gson.gson_2.8.9", + "org.jetbrains.kotlin.kotlin-gradle-plugins-bom_1.8.20-RC2", ], visibility = ["//visibility:public"], ) maven_import( - name = "org.jetbrains.kotlin.kotlin-tooling-metadata", + name = "org.jetbrains.kotlin.kotlin-tooling-core", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-tooling-metadata/1.7.10/kotlin-tooling-metadata-1.7.10.jar" - ], - deps = [ - "com.google.code.gson.gson", + "repository/org/jetbrains/kotlin/kotlin-tooling-core/1.8.20-RC2/kotlin-tooling-core-1.8.20-RC2.jar" ], original_deps = [ - "com.google.code.gson.gson_2.8.9", + "org.jetbrains.kotlin.kotlin-gradle-plugins-bom_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-tooling-metadata/1.7.10/kotlin-tooling-metadata-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-tooling-core/1.8.20-RC2/kotlin-tooling-core-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-tooling-metadata/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-tooling-core/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-util-io_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-util-io/1.7.10/kotlin-util-io-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-util-io_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-util-io/1.8.20-RC2/kotlin-util-io-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-util-io/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-util-io/1.8.20-RC2", visibility = ["//visibility:public"], ) @@ -9015,22 +9037,22 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-util-io", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-util-io/1.7.10/kotlin-util-io-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-util-io/1.8.20-RC2/kotlin-util-io-1.8.20-RC2.jar" ], original_deps = [], - pom = "repository/org/jetbrains/kotlin/kotlin-util-io/1.7.10/kotlin-util-io-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-util-io/1.8.20-RC2/kotlin-util-io-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-util-io/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-util-io/1.8.20-RC2", visibility = ["//visibility:public"], ) maven_artifact( - name = "org.jetbrains.kotlin.kotlin-util-klib_1.7.10", - pom = "repository/org/jetbrains/kotlin/kotlin-util-klib/1.7.10/kotlin-util-klib-1.7.10.pom", + name = "org.jetbrains.kotlin.kotlin-util-klib_1.8.20-RC2", + pom = "repository/org/jetbrains/kotlin/kotlin-util-klib/1.8.20-RC2/kotlin-util-klib-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-util-klib/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-util-klib/1.8.20-RC2", deps = [ - "org.jetbrains.kotlin.kotlin-util-io_1.7.10", + "org.jetbrains.kotlin.kotlin-util-io_1.8.20-RC2", ], visibility = ["//visibility:public"], ) @@ -9039,17 +9061,17 @@ maven_import( name = "org.jetbrains.kotlin.kotlin-util-klib", classifiers = [], jars = [ - "repository/org/jetbrains/kotlin/kotlin-util-klib/1.7.10/kotlin-util-klib-1.7.10.jar" + "repository/org/jetbrains/kotlin/kotlin-util-klib/1.8.20-RC2/kotlin-util-klib-1.8.20-RC2.jar" ], - deps = [ + exports = [ "org.jetbrains.kotlin.kotlin-util-io", ], original_deps = [ - "org.jetbrains.kotlin.kotlin-util-io_1.7.10", + "org.jetbrains.kotlin.kotlin-util-io_1.8.20-RC2", ], - pom = "repository/org/jetbrains/kotlin/kotlin-util-klib/1.7.10/kotlin-util-klib-1.7.10.pom", + pom = "repository/org/jetbrains/kotlin/kotlin-util-klib/1.8.20-RC2/kotlin-util-klib-1.8.20-RC2.pom", repo_root_path = "repository", - repo_path = "org/jetbrains/kotlin/kotlin-util-klib/1.7.10", + repo_path = "org/jetbrains/kotlin/kotlin-util-klib/1.8.20-RC2", visibility = ["//visibility:public"], ) @@ -10536,6 +10558,22 @@ maven_artifact( ) maven_artifact( + name = "androidx.activity.activity-compose_1.7.0", + pom = "repository/androidx/activity/activity-compose/1.7.0/activity-compose-1.7.0.pom", + repo_root_path = "repository", + repo_path = "androidx/activity/activity-compose/1.7.0", + deps = [ + "androidx.activity.activity-ktx_1.7.0", + "androidx.compose.runtime.runtime_1.0.1", + "androidx.compose.runtime.runtime-saveable_1.0.1", + "androidx.compose.ui.ui_1.0.1", + "androidx.lifecycle.lifecycle-viewmodel_2.6.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.activity.activity-compose_1.5.1", pom = "repository/androidx/activity/activity-compose/1.5.1/activity-compose-1.5.1.pom", repo_root_path = "repository", @@ -10647,6 +10685,22 @@ maven_artifact( ) maven_artifact( + name = "androidx.activity.activity-ktx_1.7.0", + pom = "repository/androidx/activity/activity-ktx/1.7.0/activity-ktx-1.7.0.pom", + repo_root_path = "repository", + repo_path = "androidx/activity/activity-ktx/1.7.0", + deps = [ + "androidx.activity.activity_1.7.0", + "androidx.core.core-ktx_1.1.0", + "androidx.lifecycle.lifecycle-runtime-ktx_2.6.1", + "androidx.lifecycle.lifecycle-viewmodel-ktx_2.6.1", + "androidx.savedstate.savedstate-ktx_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.activity.activity-ktx_1.4.0", pom = "repository/androidx/activity/activity-ktx/1.4.0/activity-ktx-1.4.0.pom", repo_root_path = "repository", @@ -10663,6 +10717,22 @@ maven_artifact( ) maven_artifact( + name = "androidx.activity.activity-ktx_1.6.0", + pom = "repository/androidx/activity/activity-ktx/1.6.0/activity-ktx-1.6.0.pom", + repo_root_path = "repository", + repo_path = "androidx/activity/activity-ktx/1.6.0", + deps = [ + "androidx.activity.activity_1.6.0", + "androidx.core.core-ktx_1.1.0", + "androidx.lifecycle.lifecycle-runtime-ktx_2.5.1", + "androidx.lifecycle.lifecycle-viewmodel-ktx_2.5.1", + "androidx.savedstate.savedstate-ktx_1.2.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.activity.activity_1.0.0", pom = "repository/androidx/activity/activity/1.0.0/activity-1.0.0.pom", repo_root_path = "repository", @@ -10730,6 +10800,24 @@ maven_artifact( ) maven_artifact( + name = "androidx.activity.activity_1.2.1", + pom = "repository/androidx/activity/activity/1.2.1/activity-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/activity/activity/1.2.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.core.core_1.1.0", + "androidx.lifecycle.lifecycle-runtime_2.3.0", + "androidx.lifecycle.lifecycle-viewmodel_2.3.0", + "androidx.savedstate.savedstate_1.1.0", + "androidx.lifecycle.lifecycle-viewmodel-savedstate_2.3.0", + "androidx.collection.collection_1.0.0", + "androidx.tracing.tracing_1.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.activity.activity_1.2.2", pom = "repository/androidx/activity/activity/1.2.2/activity-1.2.2.pom", repo_root_path = "repository", @@ -10877,6 +10965,45 @@ maven_artifact( ) maven_artifact( + name = "androidx.activity.activity_1.6.0", + pom = "repository/androidx/activity/activity/1.6.0/activity-1.6.0.pom", + repo_root_path = "repository", + repo_path = "androidx/activity/activity/1.6.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.collection.collection_1.0.0", + "androidx.core.core_1.8.0", + "androidx.lifecycle.lifecycle-runtime_2.5.1", + "androidx.lifecycle.lifecycle-viewmodel_2.5.1", + "androidx.lifecycle.lifecycle-viewmodel-savedstate_2.5.1", + "androidx.savedstate.savedstate_1.2.0", + "androidx.tracing.tracing_1.0.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.activity.activity_1.7.0", + pom = "repository/androidx/activity/activity/1.7.0/activity-1.7.0.pom", + repo_root_path = "repository", + repo_path = "androidx/activity/activity/1.7.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.collection.collection_1.0.0", + "androidx.core.core_1.8.0", + "androidx.lifecycle.lifecycle-runtime_2.6.1", + "androidx.lifecycle.lifecycle-viewmodel_2.6.1", + "androidx.lifecycle.lifecycle-viewmodel-savedstate_2.6.1", + "androidx.profileinstaller.profileinstaller_1.3.0", + "androidx.savedstate.savedstate_1.2.1", + "androidx.tracing.tracing_1.0.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.annotation.annotation-experimental_1.0.0", pom = "repository/androidx/annotation/annotation-experimental/1.0.0/annotation-experimental-1.0.0.pom", repo_root_path = "repository", @@ -10912,6 +11039,17 @@ maven_artifact( ) maven_artifact( + name = "androidx.annotation.annotation-jvm_1.6.0", + pom = "repository/androidx/annotation/annotation-jvm/1.6.0/annotation-jvm-1.6.0.pom", + repo_root_path = "repository", + repo_path = "androidx/annotation/annotation-jvm/1.6.0", + deps = [ + "org.jetbrains.kotlin.kotlin-stdlib_1.8.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.annotation.annotation_1.0.0", pom = "repository/androidx/annotation/annotation/1.0.0/annotation-1.0.0.pom", repo_root_path = "repository", @@ -10987,6 +11125,17 @@ maven_artifact( ) maven_artifact( + name = "androidx.annotation.annotation_1.6.0", + pom = "repository/androidx/annotation/annotation/1.6.0/annotation-1.6.0.pom", + repo_root_path = "repository", + repo_path = "androidx/annotation/annotation/1.6.0", + deps = [ + "org.jetbrains.kotlin.kotlin-stdlib_1.8.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.appcompat.appcompat-resources_1.1.0", pom = "repository/androidx/appcompat/appcompat-resources/1.1.0/appcompat-resources-1.1.0.pom", repo_root_path = "repository", @@ -11077,6 +11226,21 @@ maven_artifact( ) maven_artifact( + name = "androidx.appcompat.appcompat-resources_1.6.1", + pom = "repository/androidx/appcompat/appcompat-resources/1.6.1/appcompat-resources-1.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/appcompat/appcompat-resources/1.6.1", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.collection.collection_1.0.0", + "androidx.core.core_1.6.0", + "androidx.vectordrawable.vectordrawable_1.1.0", + "androidx.vectordrawable.vectordrawable-animated_1.1.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.appcompat.appcompat_1.0.0", pom = "repository/androidx/appcompat/appcompat/1.0.0/appcompat-1.0.0.pom", repo_root_path = "repository", @@ -11239,6 +11403,32 @@ maven_artifact( ) maven_artifact( + name = "androidx.appcompat.appcompat_1.6.1", + pom = "repository/androidx/appcompat/appcompat/1.6.1/appcompat-1.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/appcompat/appcompat/1.6.1", + deps = [ + "androidx.activity.activity_1.6.0", + "androidx.annotation.annotation_1.3.0", + "androidx.appcompat.appcompat-resources_1.6.1", + "androidx.collection.collection_1.0.0", + "androidx.core.core_1.9.0", + "androidx.core.core-ktx_1.8.0", + "androidx.cursoradapter.cursoradapter_1.0.0", + "androidx.drawerlayout.drawerlayout_1.0.0", + "androidx.emoji2.emoji2_1.2.0", + "androidx.emoji2.emoji2-views-helper_1.2.0", + "androidx.fragment.fragment_1.3.6", + "androidx.lifecycle.lifecycle-runtime_2.5.1", + "androidx.lifecycle.lifecycle-viewmodel_2.5.1", + "androidx.resourceinspection.resourceinspection-annotation_1.0.1", + "androidx.savedstate.savedstate_1.2.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.arch.core.core-common_2.0.0", pom = "repository/androidx/arch/core/core-common/2.0.0/core-common-2.0.0.pom", repo_root_path = "repository", @@ -11272,6 +11462,17 @@ maven_artifact( ) maven_artifact( + name = "androidx.arch.core.core-common_2.2.0", + pom = "repository/androidx/arch/core/core-common/2.2.0/core-common-2.2.0.pom", + repo_root_path = "repository", + repo_path = "androidx/arch/core/core-common/2.2.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.arch.core.core-runtime_2.0.0", pom = "repository/androidx/arch/core/core-runtime/2.0.0/core-runtime-2.0.0.pom", repo_root_path = "repository", @@ -11308,6 +11509,18 @@ maven_artifact( ) maven_artifact( + name = "androidx.arch.core.core-runtime_2.2.0", + pom = "repository/androidx/arch/core/core-runtime/2.2.0/core-runtime-2.2.0.pom", + repo_root_path = "repository", + repo_path = "androidx/arch/core/core-runtime/2.2.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.arch.core.core-common_2.2.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.asynclayoutinflater.asynclayoutinflater_1.0.0", pom = "repository/androidx/asynclayoutinflater/asynclayoutinflater/1.0.0/asynclayoutinflater-1.0.0.pom", repo_root_path = "repository", @@ -11346,6 +11559,21 @@ maven_artifact( ) maven_artifact( + name = "androidx.benchmark.benchmark-baseline-profile-gradle-plugin_1.2.0-alpha12", + pom = "repository/androidx/benchmark/benchmark-baseline-profile-gradle-plugin/1.2.0-alpha12/benchmark-baseline-profile-gradle-plugin-1.2.0-alpha12.pom", + repo_root_path = "repository", + repo_path = "androidx/benchmark/benchmark-baseline-profile-gradle-plugin/1.2.0-alpha12", + deps = [ + "com.android.tools.build.gradle_8.0.0-beta03", + "com.google.protobuf.protobuf-java_3.21.8", + "com.google.testing.platform.core-proto_0.0.8-alpha08", + "org.jetbrains.kotlin.kotlin-gradle-plugin_1.8.10", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.benchmark.benchmark-gradle-plugin_1.1.1", pom = "repository/androidx/benchmark/benchmark-gradle-plugin/1.1.1/benchmark-gradle-plugin-1.1.1.pom", repo_root_path = "repository", @@ -11373,6 +11601,22 @@ maven_artifact( ) maven_artifact( + name = "androidx.browser.browser_1.4.0", + pom = "repository/androidx/browser/browser/1.4.0/browser-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/browser/browser/1.4.0", + deps = [ + "androidx.core.core_1.1.0", + "androidx.annotation.annotation_1.1.0", + "com.google.guava.listenablefuture_1.0", + "androidx.collection.collection_1.1.0", + "androidx.concurrent.concurrent-futures_1.0.0", + "androidx.interpolator.interpolator_1.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.cardview.cardview_1.0.0", pom = "repository/androidx/cardview/cardview/1.0.0/cardview-1.0.0.pom", repo_root_path = "repository", @@ -11559,6 +11803,23 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.animation.animation-core_1.2.1", + pom = "repository/androidx/compose/animation/animation-core/1.2.1/animation-core-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/animation/animation-core/1.2.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.runtime.runtime_1.1.1", + "androidx.compose.ui.ui_1.2.1", + "androidx.compose.ui.ui-unit_1.0.0", + "androidx.compose.ui.ui-util_1.0.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.6.21", + "org.jetbrains.kotlinx.kotlinx-coroutines-core_1.6.1", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.animation.animation-core_1.3.0", pom = "repository/androidx/compose/animation/animation-core/1.3.0/animation-core-1.3.0.pom", repo_root_path = "repository", @@ -11576,6 +11837,23 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.animation.animation-core_1.4.0", + pom = "repository/androidx/compose/animation/animation-core/1.4.0/animation-core-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/animation/animation-core/1.4.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.ui.ui_1.2.1", + "androidx.compose.ui.ui-unit_1.2.1", + "androidx.compose.ui.ui-util_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-core_1.6.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.animation.animation_1.0.0", pom = "repository/androidx/compose/animation/animation/1.0.0/animation-1.0.0.pom", repo_root_path = "repository", @@ -11666,6 +11944,24 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.animation.animation_1.2.1", + pom = "repository/androidx/compose/animation/animation/1.2.1/animation-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/animation/animation/1.2.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.animation.animation-core_1.2.1", + "androidx.compose.foundation.foundation-layout_1.0.0", + "androidx.compose.runtime.runtime_1.1.1", + "androidx.compose.ui.ui_1.0.0", + "androidx.compose.ui.ui-geometry_1.0.0", + "androidx.compose.ui.ui-util_1.0.0", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.6.21", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.animation.animation_1.3.0", pom = "repository/androidx/compose/animation/animation/1.3.0/animation-1.3.0.pom", repo_root_path = "repository", @@ -11684,6 +11980,24 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.animation.animation_1.4.0", + pom = "repository/androidx/compose/animation/animation/1.4.0/animation-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/animation/animation/1.4.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.animation.animation-core_1.4.0", + "androidx.compose.foundation.foundation-layout_1.2.1", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.ui.ui_1.2.1", + "androidx.compose.ui.ui-geometry_1.2.1", + "androidx.compose.ui.ui-util_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.animation.animation_1.2.0-alpha05", pom = "repository/androidx/compose/animation/animation/1.2.0-alpha05/animation-1.2.0-alpha05.pom", repo_root_path = "repository", @@ -11718,6 +12032,14 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.compiler.compiler_1.4.3", + pom = "repository/androidx/compose/compiler/compiler/1.4.3/compiler-1.4.3.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/compiler/compiler/1.4.3", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.foundation.foundation-layout_1.0.0", pom = "repository/androidx/compose/foundation/foundation-layout/1.0.0/foundation-layout-1.0.0.pom", repo_root_path = "repository", @@ -11815,6 +12137,24 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.foundation.foundation-layout_1.2.1", + pom = "repository/androidx/compose/foundation/foundation-layout/1.2.1/foundation-layout-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/foundation/foundation-layout/1.2.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.animation.animation-core_1.1.1", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.ui.ui_1.2.1", + "androidx.compose.ui.ui-unit_1.1.1", + "androidx.compose.ui.ui-util_1.0.0", + "androidx.core.core_1.7.0", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.6.21", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.foundation.foundation-layout_1.3.0", pom = "repository/androidx/compose/foundation/foundation-layout/1.3.0/foundation-layout-1.3.0.pom", repo_root_path = "repository", @@ -11833,6 +12173,24 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.foundation.foundation-layout_1.4.0", + pom = "repository/androidx/compose/foundation/foundation-layout/1.4.0/foundation-layout-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/foundation/foundation-layout/1.4.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.animation.animation-core_1.2.1", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.ui.ui_1.2.1", + "androidx.compose.ui.ui-unit_1.2.1", + "androidx.compose.ui.ui-util_1.2.1", + "androidx.core.core_1.7.0", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.foundation.foundation_1.0.0", pom = "repository/androidx/compose/foundation/foundation/1.0.0/foundation-1.0.0.pom", repo_root_path = "repository", @@ -11908,6 +12266,45 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.foundation.foundation_1.2.1", + pom = "repository/androidx/compose/foundation/foundation/1.2.1/foundation-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/foundation/foundation/1.2.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.animation.animation_1.1.1", + "androidx.compose.foundation.foundation-layout_1.2.1", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.ui.ui_1.2.1", + "androidx.compose.ui.ui-graphics_1.1.1", + "androidx.compose.ui.ui-text_1.0.0", + "androidx.compose.ui.ui-util_1.0.0", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.6.21", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.compose.foundation.foundation_1.4.0", + pom = "repository/androidx/compose/foundation/foundation/1.4.0/foundation-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/foundation/foundation/1.4.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.animation.animation_1.2.1", + "androidx.compose.foundation.foundation-layout_1.4.0", + "androidx.compose.runtime.runtime_1.4.0", + "androidx.compose.ui.ui_1.4.0", + "androidx.compose.ui.ui-graphics_1.2.1", + "androidx.compose.ui.ui-text_1.2.1", + "androidx.compose.ui.ui-util_1.2.1", + "androidx.emoji2.emoji2_1.3.0", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.foundation.foundation_1.2.0-alpha05", pom = "repository/androidx/compose/foundation/foundation/1.2.0-alpha05/foundation-1.2.0-alpha05.pom", repo_root_path = "repository", @@ -11991,6 +12388,30 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.material3.material3_1.0.1", + pom = "repository/androidx/compose/material3/material3/1.0.1/material3-1.0.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/material3/material3/1.0.1", + deps = [ + "androidx.compose.animation.animation-core_1.1.1", + "androidx.compose.foundation.foundation_1.2.0", + "androidx.compose.foundation.foundation-layout_1.2.0", + "androidx.compose.material.material-icons-core_1.0.2", + "androidx.compose.material.material-ripple_1.0.0", + "androidx.compose.runtime.runtime_1.0.1", + "androidx.compose.ui.ui_1.3.1", + "androidx.compose.ui.ui-graphics_1.0.1", + "androidx.compose.ui.ui-text_1.3.1", + "androidx.compose.ui.ui-util_1.0.0", + "androidx.lifecycle.lifecycle-runtime_2.3.0", + "androidx.lifecycle.lifecycle-viewmodel_2.3.0", + "androidx.savedstate.savedstate-ktx_1.2.0", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.material.material-icons-core_1.0.0", pom = "repository/androidx/compose/material/material-icons-core/1.0.0/material-icons-core-1.0.0.pom", repo_root_path = "repository", @@ -12054,6 +12475,32 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.material.material-icons-core_1.3.1", + pom = "repository/androidx/compose/material/material-icons-core/1.3.1/material-icons-core-1.3.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/material/material-icons-core/1.3.1", + deps = [ + "androidx.compose.runtime.runtime_1.1.1", + "androidx.compose.ui.ui_1.0.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.compose.material.material-icons-core_1.4.0", + pom = "repository/androidx/compose/material/material-icons-core/1.4.0/material-icons-core-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/material/material-icons-core/1.4.0", + deps = [ + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.ui.ui_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.material.material-icons-extended_1.2.0-alpha05", pom = "repository/androidx/compose/material/material-icons-extended/1.2.0-alpha05/material-icons-extended-1.2.0-alpha05.pom", repo_root_path = "repository", @@ -12080,6 +12527,19 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.material.material-icons-extended_1.4.0", + pom = "repository/androidx/compose/material/material-icons-extended/1.4.0/material-icons-extended-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/material/material-icons-extended/1.4.0", + deps = [ + "androidx.compose.material.material-icons-core_1.4.0", + "androidx.compose.runtime.runtime_1.4.0", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.material.material-ripple_1.0.0", pom = "repository/androidx/compose/material/material-ripple/1.0.0/material-ripple-1.0.0.pom", repo_root_path = "repository", @@ -12125,6 +12585,36 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.material.material-ripple_1.3.1", + pom = "repository/androidx/compose/material/material-ripple/1.3.1/material-ripple-1.3.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/material/material-ripple/1.3.1", + deps = [ + "androidx.compose.animation.animation_1.0.0", + "androidx.compose.foundation.foundation_1.1.1", + "androidx.compose.runtime.runtime_1.1.1", + "androidx.compose.ui.ui-util_1.0.0", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.compose.material.material-ripple_1.4.0", + pom = "repository/androidx/compose/material/material-ripple/1.4.0/material-ripple-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/material/material-ripple/1.4.0", + deps = [ + "androidx.compose.animation.animation_1.2.1", + "androidx.compose.foundation.foundation_1.2.1", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.ui.ui-util_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.material.material_1.0.0", pom = "repository/androidx/compose/material/material/1.0.0/material-1.0.0.pom", repo_root_path = "repository", @@ -12194,6 +12684,54 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.material.material_1.3.1", + pom = "repository/androidx/compose/material/material/1.3.1/material-1.3.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/material/material/1.3.1", + deps = [ + "androidx.compose.animation.animation_1.0.0", + "androidx.compose.animation.animation-core_1.0.0", + "androidx.compose.foundation.foundation_1.2.0", + "androidx.compose.foundation.foundation-layout_1.1.1", + "androidx.compose.material.material-icons-core_1.3.1", + "androidx.compose.material.material-ripple_1.3.1", + "androidx.compose.runtime.runtime_1.2.0", + "androidx.compose.ui.ui_1.2.0", + "androidx.compose.ui.ui-text_1.2.0", + "androidx.compose.ui.ui-util_1.0.0", + "androidx.lifecycle.lifecycle-runtime_2.3.0", + "androidx.lifecycle.lifecycle-viewmodel_2.3.0", + "androidx.savedstate.savedstate_1.1.0", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.compose.material.material_1.4.0", + pom = "repository/androidx/compose/material/material/1.4.0/material-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/material/material/1.4.0", + deps = [ + "androidx.compose.animation.animation_1.2.1", + "androidx.compose.animation.animation-core_1.2.1", + "androidx.compose.foundation.foundation_1.4.0", + "androidx.compose.foundation.foundation-layout_1.2.1", + "androidx.compose.material.material-icons-core_1.4.0", + "androidx.compose.material.material-ripple_1.4.0", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.ui.ui_1.2.1", + "androidx.compose.ui.ui-text_1.2.1", + "androidx.compose.ui.ui-util_1.2.1", + "androidx.lifecycle.lifecycle-runtime_2.6.1", + "androidx.lifecycle.lifecycle-viewmodel_2.6.1", + "androidx.savedstate.savedstate_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.runtime.runtime-livedata_1.2.0-alpha05", pom = "repository/androidx/compose/runtime/runtime-livedata/1.2.0-alpha05/runtime-livedata-1.2.0-alpha05.pom", repo_root_path = "repository", @@ -12222,6 +12760,21 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.runtime.runtime-livedata_1.4.0", + pom = "repository/androidx/compose/runtime/runtime-livedata/1.4.0/runtime-livedata-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/runtime/runtime-livedata/1.4.0", + deps = [ + "androidx.compose.runtime.runtime_1.4.0", + "androidx.compose.ui.ui_1.2.1", + "androidx.lifecycle.lifecycle-livedata_2.6.1", + "androidx.lifecycle.lifecycle-runtime_2.6.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.runtime.runtime-saveable_1.0.0", pom = "repository/androidx/compose/runtime/runtime-saveable/1.0.0/runtime-saveable-1.0.0.pom", repo_root_path = "repository", @@ -12313,6 +12866,19 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.runtime.runtime-saveable_1.2.1", + pom = "repository/androidx/compose/runtime/runtime-saveable/1.2.1/runtime-saveable-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/runtime/runtime-saveable/1.2.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.runtime.runtime_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.6.21", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.runtime.runtime-saveable_1.3.0", pom = "repository/androidx/compose/runtime/runtime-saveable/1.3.0/runtime-saveable-1.3.0.pom", repo_root_path = "repository", @@ -12326,6 +12892,32 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.runtime.runtime-saveable_1.3.1", + pom = "repository/androidx/compose/runtime/runtime-saveable/1.3.1/runtime-saveable-1.3.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/runtime/runtime-saveable/1.3.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.runtime.runtime_1.3.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.compose.runtime.runtime-saveable_1.4.0", + pom = "repository/androidx/compose/runtime/runtime-saveable/1.4.0/runtime-saveable-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/runtime/runtime-saveable/1.4.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.runtime.runtime_1.4.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.runtime.runtime_1.0.0", pom = "repository/androidx/compose/runtime/runtime/1.0.0/runtime-1.0.0.pom", repo_root_path = "repository", @@ -12430,6 +13022,19 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.runtime.runtime_1.2.1", + pom = "repository/androidx/compose/runtime/runtime/1.2.1/runtime-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/runtime/runtime/1.2.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.6.21", + "org.jetbrains.kotlinx.kotlinx-coroutines-android_1.6.1", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.runtime.runtime_1.3.0", pom = "repository/androidx/compose/runtime/runtime/1.3.0/runtime-1.3.0.pom", repo_root_path = "repository", @@ -12443,6 +13048,32 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.runtime.runtime_1.3.1", + pom = "repository/androidx/compose/runtime/runtime/1.3.1/runtime-1.3.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/runtime/runtime/1.3.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-android_1.6.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.compose.runtime.runtime_1.4.0", + pom = "repository/androidx/compose/runtime/runtime/1.4.0/runtime-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/runtime/runtime/1.4.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-android_1.6.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-geometry_1.0.0", pom = "repository/androidx/compose/ui/ui-geometry/1.0.0/ui-geometry-1.0.0.pom", repo_root_path = "repository", @@ -12555,6 +13186,20 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-geometry_1.2.1", + pom = "repository/androidx/compose/ui/ui-geometry/1.2.1/ui-geometry-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-geometry/1.2.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.runtime.runtime_1.1.1", + "androidx.compose.ui.ui-util_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.6.21", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-geometry_1.3.0", pom = "repository/androidx/compose/ui/ui-geometry/1.3.0/ui-geometry-1.3.0.pom", repo_root_path = "repository", @@ -12569,6 +13214,34 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-geometry_1.3.1", + pom = "repository/androidx/compose/ui/ui-geometry/1.3.1/ui-geometry-1.3.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-geometry/1.3.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.runtime.runtime_1.1.1", + "androidx.compose.ui.ui-util_1.3.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.compose.ui.ui-geometry_1.4.0", + pom = "repository/androidx/compose/ui/ui-geometry/1.4.0/ui-geometry-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-geometry/1.4.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.ui.ui-util_1.4.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-graphics_1.0.0", pom = "repository/androidx/compose/ui/ui-graphics/1.0.0/ui-graphics-1.0.0.pom", repo_root_path = "repository", @@ -12689,6 +13362,21 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-graphics_1.2.1", + pom = "repository/androidx/compose/ui/ui-graphics/1.2.1/ui-graphics-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-graphics/1.2.1", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.compose.runtime.runtime_1.1.1", + "androidx.compose.ui.ui-unit_1.2.1", + "androidx.compose.ui.ui-util_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.6.21", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-graphics_1.3.0", pom = "repository/androidx/compose/ui/ui-graphics/1.3.0/ui-graphics-1.3.0.pom", repo_root_path = "repository", @@ -12704,6 +13392,36 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-graphics_1.3.1", + pom = "repository/androidx/compose/ui/ui-graphics/1.3.1/ui-graphics-1.3.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-graphics/1.3.1", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.compose.runtime.runtime_1.1.1", + "androidx.compose.ui.ui-unit_1.3.1", + "androidx.compose.ui.ui-util_1.3.1", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.compose.ui.ui-graphics_1.4.0", + pom = "repository/androidx/compose/ui/ui-graphics/1.4.0/ui-graphics-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-graphics/1.4.0", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.ui.ui-unit_1.4.0", + "androidx.compose.ui.ui-util_1.4.0", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-test-junit4_1.2.0", pom = "repository/androidx/compose/ui/ui-test-junit4/1.2.0/ui-test-junit4-1.2.0.pom", repo_root_path = "repository", @@ -12758,6 +13476,33 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-test-junit4_1.4.0", + pom = "repository/androidx/compose/ui/ui-test-junit4/1.4.0/ui-test-junit4-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-test-junit4/1.4.0", + deps = [ + "androidx.activity.activity_1.2.1", + "androidx.activity.activity-compose_1.3.0", + "androidx.annotation.annotation_1.1.0", + "androidx.compose.runtime.runtime-saveable_1.2.1", + "androidx.compose.ui.ui-test_1.4.0", + "androidx.lifecycle.lifecycle-common_2.5.1", + "androidx.lifecycle.lifecycle-runtime_2.5.1", + "androidx.test.core_1.5.0", + "androidx.test.monitor_1.6.0", + "androidx.test.espresso.espresso-core_3.5.0", + "androidx.test.espresso.espresso-idling-resource_3.5.0", + "androidx.test.ext.junit_1.1.5", + "junit.junit_4.13.2", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.8.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-core_1.6.4", + "org.jetbrains.kotlinx.kotlinx-coroutines-test_1.6.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-test-manifest_1.2.0", pom = "repository/androidx/compose/ui/ui-test-manifest/1.2.0/ui-test-manifest-1.2.0.pom", repo_root_path = "repository", @@ -12780,6 +13525,17 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-test-manifest_1.4.0", + pom = "repository/androidx/compose/ui/ui-test-manifest/1.4.0/ui-test-manifest-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-test-manifest/1.4.0", + deps = [ + "androidx.activity.activity_1.2.1", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-test_1.2.0", pom = "repository/androidx/compose/ui/ui-test/1.2.0/ui-test-1.2.0.pom", repo_root_path = "repository", @@ -12828,6 +13584,30 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-test_1.4.0", + pom = "repository/androidx/compose/ui/ui-test/1.4.0/ui-test-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-test/1.4.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.ui.ui_1.4.0", + "androidx.compose.ui.ui-graphics_1.4.0", + "androidx.compose.ui.ui-text_1.4.0", + "androidx.compose.ui.ui-unit_1.4.0", + "androidx.compose.ui.ui-util_1.4.0", + "androidx.core.core-ktx_1.1.0", + "androidx.test.monitor_1.6.0", + "androidx.test.espresso.espresso-core_3.5.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.8.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-core_1.6.4", + "org.jetbrains.kotlinx.kotlinx-coroutines-test_1.6.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-text_1.0.0", pom = "repository/androidx/compose/ui/ui-text/1.0.0/ui-text-1.0.0.pom", repo_root_path = "repository", @@ -12970,6 +13750,27 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-text_1.2.1", + pom = "repository/androidx/compose/ui/ui-text/1.2.1/ui-text-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-text/1.2.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.collection.collection_1.0.0", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.runtime.runtime-saveable_1.2.1", + "androidx.compose.ui.ui-graphics_1.2.1", + "androidx.compose.ui.ui-unit_1.2.1", + "androidx.compose.ui.ui-util_1.2.1", + "androidx.core.core_1.5.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.6.21", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.6.21", + "org.jetbrains.kotlinx.kotlinx-coroutines-core_1.6.1", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-text_1.3.0", pom = "repository/androidx/compose/ui/ui-text/1.3.0/ui-text-1.3.0.pom", repo_root_path = "repository", @@ -12991,6 +13792,49 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-text_1.3.1", + pom = "repository/androidx/compose/ui/ui-text/1.3.1/ui-text-1.3.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-text/1.3.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.collection.collection_1.0.0", + "androidx.compose.runtime.runtime_1.2.0", + "androidx.compose.runtime.runtime-saveable_1.2.0", + "androidx.compose.ui.ui-graphics_1.3.1", + "androidx.compose.ui.ui-unit_1.3.1", + "androidx.compose.ui.ui-util_1.3.1", + "androidx.core.core_1.7.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.7.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-core_1.6.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.compose.ui.ui-text_1.4.0", + pom = "repository/androidx/compose/ui/ui-text/1.4.0/ui-text-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-text/1.4.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.collection.collection_1.0.0", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.runtime.runtime-saveable_1.2.1", + "androidx.compose.ui.ui-graphics_1.4.0", + "androidx.compose.ui.ui-unit_1.4.0", + "androidx.compose.ui.ui-util_1.4.0", + "androidx.core.core_1.7.0", + "androidx.emoji2.emoji2_1.2.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.8.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-core_1.6.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-tooling-data_1.2.0", pom = "repository/androidx/compose/ui/ui-tooling-data/1.2.0/ui-tooling-data-1.2.0.pom", repo_root_path = "repository", @@ -13019,6 +13863,20 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-tooling-data_1.4.0", + pom = "repository/androidx/compose/ui/ui-tooling-data/1.4.0/ui-tooling-data-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-tooling-data/1.4.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.ui.ui_1.4.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-tooling-preview_1.2.0", pom = "repository/androidx/compose/ui/ui-tooling-preview/1.2.0/ui-tooling-preview-1.2.0.pom", repo_root_path = "repository", @@ -13045,6 +13903,19 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-tooling-preview_1.4.0", + pom = "repository/androidx/compose/ui/ui-tooling-preview/1.4.0/ui-tooling-preview-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-tooling-preview/1.4.0", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.compose.runtime.runtime_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-tooling_1.2.0", pom = "repository/androidx/compose/ui/ui-tooling/1.2.0/ui-tooling-1.2.0.pom", repo_root_path = "repository", @@ -13085,6 +13956,27 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-tooling_1.4.0", + pom = "repository/androidx/compose/ui/ui-tooling/1.4.0/ui-tooling-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-tooling/1.4.0", + deps = [ + "androidx.activity.activity-compose_1.7.0", + "androidx.annotation.annotation_1.1.0", + "androidx.compose.animation.animation_1.4.0", + "androidx.compose.material.material_1.0.0", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.ui.ui_1.4.0", + "androidx.compose.ui.ui-tooling-data_1.4.0", + "androidx.compose.ui.ui-tooling-preview_1.4.0", + "androidx.lifecycle.lifecycle-common_2.6.1", + "androidx.savedstate.savedstate-ktx_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-unit_1.0.0", pom = "repository/androidx/compose/ui/ui-unit/1.0.0/ui-unit-1.0.0.pom", repo_root_path = "repository", @@ -13205,6 +14097,21 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-unit_1.2.1", + pom = "repository/androidx/compose/ui/ui-unit/1.2.1/ui-unit-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-unit/1.2.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.runtime.runtime_1.1.1", + "androidx.compose.ui.ui-geometry_1.2.1", + "androidx.compose.ui.ui-util_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.6.21", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-unit_1.3.0", pom = "repository/androidx/compose/ui/ui-unit/1.3.0/ui-unit-1.3.0.pom", repo_root_path = "repository", @@ -13220,6 +14127,36 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-unit_1.3.1", + pom = "repository/androidx/compose/ui/ui-unit/1.3.1/ui-unit-1.3.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-unit/1.3.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.runtime.runtime_1.1.1", + "androidx.compose.ui.ui-geometry_1.3.1", + "androidx.compose.ui.ui-util_1.3.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.compose.ui.ui-unit_1.4.0", + pom = "repository/androidx/compose/ui/ui-unit/1.4.0/ui-unit-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-unit/1.4.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.ui.ui-geometry_1.4.0", + "androidx.compose.ui.ui-util_1.4.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-util_1.0.0", pom = "repository/androidx/compose/ui/ui-util/1.0.0/ui-util-1.0.0.pom", repo_root_path = "repository", @@ -13308,6 +14245,17 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-util_1.2.1", + pom = "repository/androidx/compose/ui/ui-util/1.2.1/ui-util-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-util/1.2.1", + deps = [ + "org.jetbrains.kotlin.kotlin-stdlib_1.6.21", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui-util_1.3.0", pom = "repository/androidx/compose/ui/ui-util/1.3.0/ui-util-1.3.0.pom", repo_root_path = "repository", @@ -13319,6 +14267,28 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui-util_1.3.1", + pom = "repository/androidx/compose/ui/ui-util/1.3.1/ui-util-1.3.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-util/1.3.1", + deps = [ + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.compose.ui.ui-util_1.4.0", + pom = "repository/androidx/compose/ui/ui-util/1.4.0/ui-util-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui-util/1.4.0", + deps = [ + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui_1.0.0", pom = "repository/androidx/compose/ui/ui/1.0.0/ui-1.0.0.pom", repo_root_path = "repository", @@ -13520,6 +14490,37 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui_1.2.1", + pom = "repository/androidx/compose/ui/ui/1.2.1/ui-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui/1.2.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.autofill.autofill_1.0.0", + "androidx.collection.collection_1.0.0", + "androidx.compose.runtime.runtime_1.2.1", + "androidx.compose.runtime.runtime-saveable_1.2.1", + "androidx.compose.ui.ui-geometry_1.2.1", + "androidx.compose.ui.ui-graphics_1.2.1", + "androidx.compose.ui.ui-text_1.2.1", + "androidx.compose.ui.ui-unit_1.2.1", + "androidx.compose.ui.ui-util_1.2.1", + "androidx.core.core_1.5.0", + "androidx.customview.customview-poolingcontainer_1.0.0", + "androidx.lifecycle.lifecycle-common-java8_2.3.0", + "androidx.lifecycle.lifecycle-runtime_2.3.0", + "androidx.lifecycle.lifecycle-viewmodel_2.3.0", + "androidx.profileinstaller.profileinstaller_1.2.0", + "androidx.savedstate.savedstate-ktx_1.2.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.6.21", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.6.21", + "org.jetbrains.kotlinx.kotlinx-coroutines-android_1.6.1", + "org.jetbrains.kotlinx.kotlinx-coroutines-core_1.6.1", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.ui.ui_1.3.0", pom = "repository/androidx/compose/ui/ui/1.3.0/ui-1.3.0.pom", repo_root_path = "repository", @@ -13552,6 +14553,70 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.ui.ui_1.3.1", + pom = "repository/androidx/compose/ui/ui/1.3.1/ui-1.3.1.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui/1.3.1", + deps = [ + "androidx.activity.activity-ktx_1.5.1", + "androidx.annotation.annotation_1.5.0", + "androidx.autofill.autofill_1.0.0", + "androidx.collection.collection_1.0.0", + "androidx.compose.runtime.runtime_1.3.1", + "androidx.compose.runtime.runtime-saveable_1.3.1", + "androidx.compose.ui.ui-geometry_1.3.1", + "androidx.compose.ui.ui-graphics_1.3.1", + "androidx.compose.ui.ui-text_1.3.1", + "androidx.compose.ui.ui-unit_1.3.1", + "androidx.compose.ui.ui-util_1.3.1", + "androidx.core.core_1.5.0", + "androidx.customview.customview-poolingcontainer_1.0.0", + "androidx.lifecycle.lifecycle-common-java8_2.3.0", + "androidx.lifecycle.lifecycle-runtime_2.3.0", + "androidx.lifecycle.lifecycle-viewmodel_2.3.0", + "androidx.profileinstaller.profileinstaller_1.2.0", + "androidx.savedstate.savedstate-ktx_1.2.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.7.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-android_1.6.4", + "org.jetbrains.kotlinx.kotlinx-coroutines-core_1.6.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.compose.ui.ui_1.4.0", + pom = "repository/androidx/compose/ui/ui/1.4.0/ui-1.4.0.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/ui/ui/1.4.0", + deps = [ + "androidx.activity.activity-ktx_1.7.0", + "androidx.annotation.annotation_1.5.0", + "androidx.autofill.autofill_1.0.0", + "androidx.collection.collection_1.0.0", + "androidx.compose.runtime.runtime_1.4.0", + "androidx.compose.runtime.runtime-saveable_1.4.0", + "androidx.compose.ui.ui-geometry_1.4.0", + "androidx.compose.ui.ui-graphics_1.4.0", + "androidx.compose.ui.ui-text_1.4.0", + "androidx.compose.ui.ui-unit_1.4.0", + "androidx.compose.ui.ui-util_1.4.0", + "androidx.core.core_1.9.0", + "androidx.customview.customview-poolingcontainer_1.0.0", + "androidx.emoji2.emoji2_1.2.0", + "androidx.lifecycle.lifecycle-runtime_2.6.1", + "androidx.lifecycle.lifecycle-viewmodel_2.6.1", + "androidx.profileinstaller.profileinstaller_1.3.0", + "androidx.savedstate.savedstate-ktx_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + "org.jetbrains.kotlin.kotlin-stdlib-common_1.8.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-android_1.6.4", + "org.jetbrains.kotlinx.kotlinx-coroutines-core_1.6.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.compose.compose-bom_2022.10.00", pom = "repository/androidx/compose/compose-bom/2022.10.00/compose-bom-2022.10.00.pom", repo_root_path = "repository", @@ -13560,6 +14625,14 @@ maven_artifact( ) maven_artifact( + name = "androidx.compose.compose-bom_2023.03.00", + pom = "repository/androidx/compose/compose-bom/2023.03.00/compose-bom-2023.03.00.pom", + repo_root_path = "repository", + repo_path = "androidx/compose/compose-bom/2023.03.00", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.concurrent.concurrent-futures-ktx_1.1.0", pom = "repository/androidx/concurrent/concurrent-futures-ktx/1.1.0/concurrent-futures-ktx-1.1.0.pom", repo_root_path = "repository", @@ -13605,6 +14678,14 @@ maven_artifact( ) maven_artifact( + name = "androidx.constraintlayout.constraintlayout-core_1.0.4", + pom = "repository/androidx/constraintlayout/constraintlayout-core/1.0.4/constraintlayout-core-1.0.4.pom", + repo_root_path = "repository", + repo_path = "androidx/constraintlayout/constraintlayout-core/1.0.4", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.constraintlayout.constraintlayout-solver_1.1.3", pom = "repository/androidx/constraintlayout/constraintlayout-solver/1.1.3/constraintlayout-solver-1.1.3.pom", repo_root_path = "repository", @@ -13658,6 +14739,19 @@ maven_artifact( ) maven_artifact( + name = "androidx.constraintlayout.constraintlayout_2.1.4", + pom = "repository/androidx/constraintlayout/constraintlayout/2.1.4/constraintlayout-2.1.4.pom", + repo_root_path = "repository", + repo_path = "androidx/constraintlayout/constraintlayout/2.1.4", + deps = [ + "androidx.appcompat.appcompat_1.2.0", + "androidx.core.core_1.3.2", + "androidx.constraintlayout.constraintlayout-core_1.0.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.coordinatorlayout.coordinatorlayout_1.0.0", pom = "repository/androidx/coordinatorlayout/coordinatorlayout/1.0.0/coordinatorlayout-1.0.0.pom", repo_root_path = "repository", @@ -14654,6 +15748,17 @@ maven_artifact( ) maven_artifact( + name = "androidx.databinding.viewbinding_8.0.0-beta04", + pom = "repository/androidx/databinding/viewbinding/8.0.0-beta04/viewbinding-8.0.0-beta04.pom", + repo_root_path = "repository", + repo_path = "androidx/databinding/viewbinding/8.0.0-beta04", + deps = [ + "androidx.annotation.annotation_1.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.documentfile.documentfile_1.0.0", pom = "repository/androidx/documentfile/documentfile/1.0.0/documentfile-1.0.0.pom", repo_root_path = "repository", @@ -14741,6 +15846,19 @@ maven_artifact( ) maven_artifact( + name = "androidx.emoji2.emoji2-views-helper_1.3.0", + pom = "repository/androidx/emoji2/emoji2-views-helper/1.3.0/emoji2-views-helper-1.3.0.pom", + repo_root_path = "repository", + repo_path = "androidx/emoji2/emoji2-views-helper/1.3.0", + deps = [ + "androidx.collection.collection_1.1.0", + "androidx.core.core_1.3.0", + "androidx.emoji2.emoji2_1.3.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.emoji2.emoji2_1.0.0", pom = "repository/androidx/emoji2/emoji2/1.0.0/emoji2-1.0.0.pom", repo_root_path = "repository", @@ -14771,6 +15889,21 @@ maven_artifact( ) maven_artifact( + name = "androidx.emoji2.emoji2_1.3.0", + pom = "repository/androidx/emoji2/emoji2/1.3.0/emoji2-1.3.0.pom", + repo_root_path = "repository", + repo_path = "androidx/emoji2/emoji2/1.3.0", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.collection.collection_1.1.0", + "androidx.core.core_1.3.0", + "androidx.lifecycle.lifecycle-process_2.4.1", + "androidx.startup.startup-runtime_1.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.exifinterface.exifinterface_1.0.0", pom = "repository/androidx/exifinterface/exifinterface/1.0.0/exifinterface-1.0.0.pom", repo_root_path = "repository", @@ -14864,6 +15997,24 @@ maven_artifact( ) maven_artifact( + name = "androidx.fragment.fragment-ktx_1.5.4", + pom = "repository/androidx/fragment/fragment-ktx/1.5.4/fragment-ktx-1.5.4.pom", + repo_root_path = "repository", + repo_path = "androidx/fragment/fragment-ktx/1.5.4", + deps = [ + "androidx.activity.activity-ktx_1.5.1", + "androidx.collection.collection-ktx_1.1.0", + "androidx.core.core-ktx_1.2.0", + "androidx.fragment.fragment_1.5.4", + "androidx.lifecycle.lifecycle-livedata-core-ktx_2.5.1", + "androidx.lifecycle.lifecycle-viewmodel-ktx_2.5.1", + "androidx.savedstate.savedstate-ktx_1.2.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.6.21", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.fragment.fragment_1.0.0", pom = "repository/androidx/fragment/fragment/1.0.0/fragment-1.0.0.pom", repo_root_path = "repository", @@ -15042,6 +16193,28 @@ maven_artifact( ) maven_artifact( + name = "androidx.fragment.fragment_1.5.4", + pom = "repository/androidx/fragment/fragment/1.5.4/fragment-1.5.4.pom", + repo_root_path = "repository", + repo_path = "androidx/fragment/fragment/1.5.4", + deps = [ + "androidx.activity.activity_1.5.1", + "androidx.annotation.annotation_1.1.0", + "androidx.annotation.annotation-experimental_1.0.0", + "androidx.collection.collection_1.1.0", + "androidx.core.core-ktx_1.2.0", + "androidx.lifecycle.lifecycle-livedata-core_2.5.1", + "androidx.lifecycle.lifecycle-viewmodel_2.5.1", + "androidx.lifecycle.lifecycle-viewmodel-savedstate_2.5.1", + "androidx.loader.loader_1.0.0", + "androidx.savedstate.savedstate_1.2.0", + "androidx.viewpager.viewpager_1.0.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.6.21", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.fragment.fragment_1.2.5", pom = "repository/androidx/fragment/fragment/1.2.5/fragment-1.2.5.pom", repo_root_path = "repository", @@ -15232,6 +16405,18 @@ maven_artifact( ) maven_artifact( + name = "androidx.lifecycle.lifecycle-common-java8_2.6.1", + pom = "repository/androidx/lifecycle/lifecycle-common-java8/2.6.1/lifecycle-common-java8-2.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/lifecycle/lifecycle-common-java8/2.6.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.lifecycle.lifecycle-common_2.6.1", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.lifecycle.lifecycle-common_2.0.0", pom = "repository/androidx/lifecycle/lifecycle-common/2.0.0/lifecycle-common-2.0.0.pom", repo_root_path = "repository", @@ -15342,6 +16527,19 @@ maven_artifact( ) maven_artifact( + name = "androidx.lifecycle.lifecycle-common_2.6.1", + pom = "repository/androidx/lifecycle/lifecycle-common/2.6.1/lifecycle-common-2.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/lifecycle/lifecycle-common/2.6.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-android_1.6.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.lifecycle.lifecycle-extensions_2.2.0", pom = "repository/androidx/lifecycle/lifecycle-extensions/2.2.0/lifecycle-extensions-2.2.0.pom", repo_root_path = "repository", @@ -15421,6 +16619,18 @@ maven_artifact( ) maven_artifact( + name = "androidx.lifecycle.lifecycle-livedata-core-ktx_2.6.1", + pom = "repository/androidx/lifecycle/lifecycle-livedata-core-ktx/2.6.1/lifecycle-livedata-core-ktx-2.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/lifecycle/lifecycle-livedata-core-ktx/2.6.1", + deps = [ + "androidx.lifecycle.lifecycle-livedata-core_2.6.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.lifecycle.lifecycle-livedata-core_2.0.0", pom = "repository/androidx/lifecycle/lifecycle-livedata-core/2.0.0/lifecycle-livedata-core-2.0.0.pom", repo_root_path = "repository", @@ -15551,6 +16761,20 @@ maven_artifact( ) maven_artifact( + name = "androidx.lifecycle.lifecycle-livedata-core_2.6.1", + pom = "repository/androidx/lifecycle/lifecycle-livedata-core/2.6.1/lifecycle-livedata-core-2.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/lifecycle/lifecycle-livedata-core/2.6.1", + deps = [ + "androidx.arch.core.core-common_2.1.0", + "androidx.arch.core.core-runtime_2.1.0", + "androidx.lifecycle.lifecycle-common_2.6.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.lifecycle.lifecycle-livedata-ktx_2.2.0", pom = "repository/androidx/lifecycle/lifecycle-livedata-ktx/2.2.0/lifecycle-livedata-ktx-2.2.0.pom", repo_root_path = "repository", @@ -15607,6 +16831,20 @@ maven_artifact( ) maven_artifact( + name = "androidx.lifecycle.lifecycle-livedata-ktx_2.6.1", + pom = "repository/androidx/lifecycle/lifecycle-livedata-ktx/2.6.1/lifecycle-livedata-ktx-2.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/lifecycle/lifecycle-livedata-ktx/2.6.1", + deps = [ + "androidx.lifecycle.lifecycle-livedata_2.6.1", + "androidx.lifecycle.lifecycle-livedata-core-ktx_2.6.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-core_1.6.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.lifecycle.lifecycle-livedata_2.0.0", pom = "repository/androidx/lifecycle/lifecycle-livedata/2.0.0/lifecycle-livedata-2.0.0.pom", repo_root_path = "repository", @@ -15685,6 +16923,20 @@ maven_artifact( ) maven_artifact( + name = "androidx.lifecycle.lifecycle-livedata_2.6.1", + pom = "repository/androidx/lifecycle/lifecycle-livedata/2.6.1/lifecycle-livedata-2.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/lifecycle/lifecycle-livedata/2.6.1", + deps = [ + "androidx.arch.core.core-common_2.1.0", + "androidx.arch.core.core-runtime_2.1.0", + "androidx.lifecycle.lifecycle-livedata-core_2.6.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.lifecycle.lifecycle-process_2.2.0", pom = "repository/androidx/lifecycle/lifecycle-process/2.2.0/lifecycle-process-2.2.0.pom", repo_root_path = "repository", @@ -15721,6 +16973,20 @@ maven_artifact( ) maven_artifact( + name = "androidx.lifecycle.lifecycle-process_2.6.1", + pom = "repository/androidx/lifecycle/lifecycle-process/2.6.1/lifecycle-process-2.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/lifecycle/lifecycle-process/2.6.1", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.lifecycle.lifecycle-runtime_2.6.1", + "androidx.startup.startup-runtime_1.1.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.lifecycle.lifecycle-runtime-ktx_2.2.0", pom = "repository/androidx/lifecycle/lifecycle-runtime-ktx/2.2.0/lifecycle-runtime-ktx-2.2.0.pom", repo_root_path = "repository", @@ -15763,6 +17029,20 @@ maven_artifact( ) maven_artifact( + name = "androidx.lifecycle.lifecycle-runtime-ktx_2.6.1", + pom = "repository/androidx/lifecycle/lifecycle-runtime-ktx/2.6.1/lifecycle-runtime-ktx-2.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/lifecycle/lifecycle-runtime-ktx/2.6.1", + deps = [ + "androidx.annotation.annotation_1.0.0", + "androidx.lifecycle.lifecycle-runtime_2.6.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-android_1.6.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.lifecycle.lifecycle-runtime-ktx_2.4.0", pom = "repository/androidx/lifecycle/lifecycle-runtime-ktx/2.4.0/lifecycle-runtime-ktx-2.4.0.pom", repo_root_path = "repository", @@ -15914,6 +17194,22 @@ maven_artifact( ) maven_artifact( + name = "androidx.lifecycle.lifecycle-runtime_2.6.1", + pom = "repository/androidx/lifecycle/lifecycle-runtime/2.6.1/lifecycle-runtime-2.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/lifecycle/lifecycle-runtime/2.6.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.arch.core.core-common_2.2.0", + "androidx.arch.core.core-runtime_2.2.0", + "androidx.lifecycle.lifecycle-common_2.6.1", + "androidx.profileinstaller.profileinstaller_1.3.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.lifecycle.lifecycle-service_2.0.0", pom = "repository/androidx/lifecycle/lifecycle-service/2.0.0/lifecycle-service-2.0.0.pom", repo_root_path = "repository", @@ -15969,6 +17265,18 @@ maven_artifact( ) maven_artifact( + name = "androidx.lifecycle.lifecycle-service_2.6.1", + pom = "repository/androidx/lifecycle/lifecycle-service/2.6.1/lifecycle-service-2.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/lifecycle/lifecycle-service/2.6.1", + deps = [ + "androidx.lifecycle.lifecycle-runtime_2.6.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.lifecycle.lifecycle-viewmodel-compose_2.4.0", pom = "repository/androidx/lifecycle/lifecycle-viewmodel-compose/2.4.0/lifecycle-viewmodel-compose-2.4.0.pom", repo_root_path = "repository", @@ -15983,6 +17291,23 @@ maven_artifact( ) maven_artifact( + name = "androidx.lifecycle.lifecycle-viewmodel-compose_2.6.1", + pom = "repository/androidx/lifecycle/lifecycle-viewmodel-compose/2.6.1/lifecycle-viewmodel-compose-2.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/lifecycle/lifecycle-viewmodel-compose/2.6.1", + deps = [ + "androidx.annotation.annotation-experimental_1.1.0", + "androidx.compose.runtime.runtime_1.0.1", + "androidx.compose.ui.ui_1.0.1", + "androidx.lifecycle.lifecycle-common-java8_2.6.1", + "androidx.lifecycle.lifecycle-viewmodel-ktx_2.6.1", + "androidx.lifecycle.lifecycle-viewmodel-savedstate_2.6.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.lifecycle.lifecycle-viewmodel-ktx_2.2.0", pom = "repository/androidx/lifecycle/lifecycle-viewmodel-ktx/2.2.0/lifecycle-viewmodel-ktx-2.2.0.pom", repo_root_path = "repository", @@ -16035,6 +17360,19 @@ maven_artifact( ) maven_artifact( + name = "androidx.lifecycle.lifecycle-viewmodel-ktx_2.6.1", + pom = "repository/androidx/lifecycle/lifecycle-viewmodel-ktx/2.6.1/lifecycle-viewmodel-ktx-2.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/lifecycle/lifecycle-viewmodel-ktx/2.6.1", + deps = [ + "androidx.lifecycle.lifecycle-viewmodel_2.6.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-android_1.6.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.lifecycle.lifecycle-viewmodel-ktx_2.4.0", pom = "repository/androidx/lifecycle/lifecycle-viewmodel-ktx/2.4.0/lifecycle-viewmodel-ktx-2.4.0.pom", repo_root_path = "repository", @@ -16165,6 +17503,23 @@ maven_artifact( ) maven_artifact( + name = "androidx.lifecycle.lifecycle-viewmodel-savedstate_2.6.1", + pom = "repository/androidx/lifecycle/lifecycle-viewmodel-savedstate/2.6.1/lifecycle-viewmodel-savedstate-2.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/lifecycle/lifecycle-viewmodel-savedstate/2.6.1", + deps = [ + "androidx.annotation.annotation_1.0.0", + "androidx.core.core-ktx_1.2.0", + "androidx.lifecycle.lifecycle-livedata-core_2.6.1", + "androidx.lifecycle.lifecycle-viewmodel_2.6.1", + "androidx.savedstate.savedstate_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-android_1.6.4", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.lifecycle.lifecycle-viewmodel_2.0.0", pom = "repository/androidx/lifecycle/lifecycle-viewmodel/2.0.0/lifecycle-viewmodel-2.0.0.pom", repo_root_path = "repository", @@ -16279,6 +17634,18 @@ maven_artifact( ) maven_artifact( + name = "androidx.lifecycle.lifecycle-viewmodel_2.6.1", + pom = "repository/androidx/lifecycle/lifecycle-viewmodel/2.6.1/lifecycle-viewmodel-2.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/lifecycle/lifecycle-viewmodel/2.6.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.loader.loader_1.0.0", pom = "repository/androidx/loader/loader/1.0.0/loader-1.0.0.pom", repo_root_path = "repository", @@ -16353,6 +17720,19 @@ maven_artifact( ) maven_artifact( + name = "androidx.media.media_1.6.0", + pom = "repository/androidx/media/media/1.6.0/media-1.6.0.pom", + repo_root_path = "repository", + repo_path = "androidx/media/media/1.6.0", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.collection.collection_1.1.0", + "androidx.core.core_1.6.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.navigation.navigation-common-ktx_2.3.5", pom = "repository/androidx/navigation/navigation-common-ktx/2.3.5/navigation-common-ktx-2.3.5.pom", repo_root_path = "repository", @@ -16400,6 +17780,17 @@ maven_artifact( ) maven_artifact( + name = "androidx.navigation.navigation-common-ktx_2.5.3", + pom = "repository/androidx/navigation/navigation-common-ktx/2.5.3/navigation-common-ktx-2.5.3.pom", + repo_root_path = "repository", + repo_path = "androidx/navigation/navigation-common-ktx/2.5.3", + deps = [ + "androidx.navigation.navigation-common_2.5.3", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.navigation.navigation-common_2.0.0", pom = "repository/androidx/navigation/navigation-common/2.0.0/navigation-common-2.0.0.pom", repo_root_path = "repository", @@ -16479,6 +17870,24 @@ maven_artifact( ) maven_artifact( + name = "androidx.navigation.navigation-common_2.5.3", + pom = "repository/androidx/navigation/navigation-common/2.5.3/navigation-common-2.5.3.pom", + repo_root_path = "repository", + repo_path = "androidx/navigation/navigation-common/2.5.3", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.collection.collection-ktx_1.1.0", + "androidx.core.core-ktx_1.1.0", + "androidx.lifecycle.lifecycle-runtime-ktx_2.5.1", + "androidx.lifecycle.lifecycle-viewmodel-ktx_2.5.1", + "androidx.lifecycle.lifecycle-viewmodel-savedstate_2.5.1", + "androidx.savedstate.savedstate-ktx_1.2.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.6.21", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.navigation.navigation-compose_2.4.0", pom = "repository/androidx/navigation/navigation-compose/2.4.0/navigation-compose-2.4.0.pom", repo_root_path = "repository", @@ -16537,6 +17946,18 @@ maven_artifact( ) maven_artifact( + name = "androidx.navigation.navigation-fragment-ktx_2.5.3", + pom = "repository/androidx/navigation/navigation-fragment-ktx/2.5.3/navigation-fragment-ktx-2.5.3.pom", + repo_root_path = "repository", + repo_path = "androidx/navigation/navigation-fragment-ktx/2.5.3", + deps = [ + "androidx.navigation.navigation-fragment_2.5.3", + "androidx.navigation.navigation-runtime-ktx_2.5.3", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.navigation.navigation-fragment_2.3.5", pom = "repository/androidx/navigation/navigation-fragment/2.3.5/navigation-fragment-2.3.5.pom", repo_root_path = "repository", @@ -16577,6 +17998,20 @@ maven_artifact( ) maven_artifact( + name = "androidx.navigation.navigation-fragment_2.5.3", + pom = "repository/androidx/navigation/navigation-fragment/2.5.3/navigation-fragment-2.5.3.pom", + repo_root_path = "repository", + repo_path = "androidx/navigation/navigation-fragment/2.5.3", + deps = [ + "androidx.fragment.fragment-ktx_1.5.4", + "androidx.navigation.navigation-runtime_2.5.3", + "androidx.slidingpanelayout.slidingpanelayout_1.2.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.6.21", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.navigation.navigation-fragment_2.0.0", pom = "repository/androidx/navigation/navigation-fragment/2.0.0/navigation-fragment-2.0.0.pom", repo_root_path = "repository", @@ -16640,6 +18075,18 @@ maven_artifact( ) maven_artifact( + name = "androidx.navigation.navigation-runtime-ktx_2.5.3", + pom = "repository/androidx/navigation/navigation-runtime-ktx/2.5.3/navigation-runtime-ktx-2.5.3.pom", + repo_root_path = "repository", + repo_path = "androidx/navigation/navigation-runtime-ktx/2.5.3", + deps = [ + "androidx.navigation.navigation-common-ktx_2.5.3", + "androidx.navigation.navigation-runtime_2.5.3", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.navigation.navigation-runtime_2.0.0", pom = "repository/androidx/navigation/navigation-runtime/2.0.0/navigation-runtime-2.0.0.pom", repo_root_path = "repository", @@ -16716,6 +18163,23 @@ maven_artifact( ) maven_artifact( + name = "androidx.navigation.navigation-runtime_2.5.3", + pom = "repository/androidx/navigation/navigation-runtime/2.5.3/navigation-runtime-2.5.3.pom", + repo_root_path = "repository", + repo_path = "androidx/navigation/navigation-runtime/2.5.3", + deps = [ + "androidx.activity.activity-ktx_1.5.1", + "androidx.annotation.annotation-experimental_1.1.0", + "androidx.collection.collection_1.0.0", + "androidx.lifecycle.lifecycle-runtime-ktx_2.5.1", + "androidx.lifecycle.lifecycle-viewmodel-ktx_2.5.1", + "androidx.navigation.navigation-common_2.5.3", + "org.jetbrains.kotlin.kotlin-stdlib_1.6.21", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.navigation.navigation-safe-args-generator_2.3.1", pom = "repository/androidx/navigation/navigation-safe-args-generator/2.3.1/navigation-safe-args-generator-2.3.1.pom", repo_root_path = "repository", @@ -16746,6 +18210,21 @@ maven_artifact( ) maven_artifact( + name = "androidx.navigation.navigation-safe-args-generator_2.5.3", + pom = "repository/androidx/navigation/navigation-safe-args-generator/2.5.3/navigation-safe-args-generator-2.5.3.pom", + repo_root_path = "repository", + repo_path = "androidx/navigation/navigation-safe-args-generator/2.5.3", + deps = [ + "com.squareup.javapoet_1.13.0", + "com.squareup.kotlinpoet_1.8.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.6.21", + "xmlpull.xmlpull_1.1.3.1", + "xpp3.xpp3_1.1.4c", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.navigation.navigation-safe-args-gradle-plugin_2.3.1", pom = "repository/androidx/navigation/navigation-safe-args-gradle-plugin/2.3.1/navigation-safe-args-gradle-plugin-2.3.1.pom", repo_root_path = "repository", @@ -16774,6 +18253,20 @@ maven_artifact( ) maven_artifact( + name = "androidx.navigation.navigation-safe-args-gradle-plugin_2.5.3", + pom = "repository/androidx/navigation/navigation-safe-args-gradle-plugin/2.5.3/navigation-safe-args-gradle-plugin-2.5.3.pom", + repo_root_path = "repository", + repo_path = "androidx/navigation/navigation-safe-args-gradle-plugin/2.5.3", + deps = [ + "androidx.navigation.navigation-safe-args-generator_2.5.3", + "com.android.tools.build.gradle_7.0.4", + "com.google.code.gson.gson_2.9.0", + "org.jetbrains.kotlin.kotlin-gradle-plugin_1.6.21", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.navigation.navigation-ui-ktx_2.3.5", pom = "repository/androidx/navigation/navigation-ui-ktx/2.3.5/navigation-ui-ktx-2.3.5.pom", repo_root_path = "repository", @@ -16811,6 +18304,18 @@ maven_artifact( ) maven_artifact( + name = "androidx.navigation.navigation-ui-ktx_2.5.3", + pom = "repository/androidx/navigation/navigation-ui-ktx/2.5.3/navigation-ui-ktx-2.5.3.pom", + repo_root_path = "repository", + repo_path = "androidx/navigation/navigation-ui-ktx/2.5.3", + deps = [ + "androidx.navigation.navigation-runtime-ktx_2.5.3", + "androidx.navigation.navigation-ui_2.5.3", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.navigation.navigation-ui_2.3.5", pom = "repository/androidx/navigation/navigation-ui/2.3.5/navigation-ui-2.3.5.pom", repo_root_path = "repository", @@ -16858,6 +18363,22 @@ maven_artifact( ) maven_artifact( + name = "androidx.navigation.navigation-ui_2.5.3", + pom = "repository/androidx/navigation/navigation-ui/2.5.3/navigation-ui-2.5.3.pom", + repo_root_path = "repository", + repo_path = "androidx/navigation/navigation-ui/2.5.3", + deps = [ + "androidx.annotation.annotation-experimental_1.1.0", + "androidx.customview.customview_1.1.0", + "androidx.drawerlayout.drawerlayout_1.1.1", + "androidx.navigation.navigation-runtime_2.5.3", + "androidx.transition.transition_1.3.0", + "com.google.android.material.material_1.4.0-beta01", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.palette.palette-ktx_1.0.0", pom = "repository/androidx/palette/palette-ktx/1.0.0/palette-ktx-1.0.0.pom", repo_root_path = "repository", @@ -17159,6 +18680,20 @@ maven_artifact( ) maven_artifact( + name = "androidx.profileinstaller.profileinstaller_1.3.0", + pom = "repository/androidx/profileinstaller/profileinstaller/1.3.0/profileinstaller-1.3.0.pom", + repo_root_path = "repository", + repo_path = "androidx/profileinstaller/profileinstaller/1.3.0", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.concurrent.concurrent-futures_1.1.0", + "androidx.startup.startup-runtime_1.1.1", + "com.google.guava.listenablefuture_1.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.profileinstaller.profileinstaller_1.3.0-beta01", pom = "repository/androidx/profileinstaller/profileinstaller/1.3.0-beta01/profileinstaller-1.3.0-beta01.pom", repo_root_path = "repository", @@ -17214,6 +18749,21 @@ maven_artifact( ) maven_artifact( + name = "androidx.recyclerview.recyclerview_1.3.0", + pom = "repository/androidx/recyclerview/recyclerview/1.3.0/recyclerview-1.3.0.pom", + repo_root_path = "repository", + repo_path = "androidx/recyclerview/recyclerview/1.3.0", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.collection.collection_1.0.0", + "androidx.core.core_1.7.0", + "androidx.customview.customview_1.0.0", + "androidx.customview.customview-poolingcontainer_1.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.resourceinspection.resourceinspection-annotation_1.0.0", pom = "repository/androidx/resourceinspection/resourceinspection-annotation/1.0.0/resourceinspection-annotation-1.0.0.pom", repo_root_path = "repository", @@ -17370,6 +18920,18 @@ maven_artifact( ) maven_artifact( + name = "androidx.savedstate.savedstate-ktx_1.2.1", + pom = "repository/androidx/savedstate/savedstate-ktx/1.2.1/savedstate-ktx-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/savedstate/savedstate-ktx/1.2.1", + deps = [ + "androidx.savedstate.savedstate_1.2.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.savedstate.savedstate_1.0.0", pom = "repository/androidx/savedstate/savedstate/1.0.0/savedstate-1.0.0.pom", repo_root_path = "repository", @@ -17423,6 +18985,20 @@ maven_artifact( ) maven_artifact( + name = "androidx.savedstate.savedstate_1.2.1", + pom = "repository/androidx/savedstate/savedstate/1.2.1/savedstate-1.2.1.pom", + repo_root_path = "repository", + repo_path = "androidx/savedstate/savedstate/1.2.1", + deps = [ + "androidx.annotation.annotation_1.1.0", + "androidx.arch.core.core-common_2.1.0", + "androidx.lifecycle.lifecycle-common_2.6.1", + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.slice.slice-builders_1.0.0", pom = "repository/androidx/slice/slice-builders/1.0.0/slice-builders-1.0.0.pom", repo_root_path = "repository", @@ -17650,6 +19226,48 @@ maven_artifact( ) maven_artifact( + name = "androidx.test.espresso.espresso-core_3.5.0", + pom = "repository/androidx/test/espresso/espresso-core/3.5.0/espresso-core-3.5.0.pom", + repo_root_path = "repository", + repo_path = "androidx/test/espresso/espresso-core/3.5.0", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.test.core_1.5.0", + "androidx.test.runner_1.5.0", + "androidx.test.espresso.espresso-idling-resource_3.5.0", + "com.squareup.javawriter_2.1.1", + "javax.inject.javax.inject_1", + "org.hamcrest.hamcrest-library_1.3", + "org.hamcrest.hamcrest-integration_1.3", + "com.google.code.findbugs.jsr305_2.0.2", + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + "androidx.test.annotation_1.0.1", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.test.espresso.espresso-core_3.5.1", + pom = "repository/androidx/test/espresso/espresso-core/3.5.1/espresso-core-3.5.1.pom", + repo_root_path = "repository", + repo_path = "androidx/test/espresso/espresso-core/3.5.1", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.test.core_1.5.0", + "androidx.test.runner_1.5.2", + "androidx.test.espresso.espresso-idling-resource_3.5.1", + "com.squareup.javawriter_2.1.1", + "javax.inject.javax.inject_1", + "org.hamcrest.hamcrest-library_1.3", + "org.hamcrest.hamcrest-integration_1.3", + "com.google.code.findbugs.jsr305_2.0.2", + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + "androidx.test.annotation_1.0.1", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.test.espresso.espresso-idling-resource_3.1.0", pom = "repository/androidx/test/espresso/espresso-idling-resource/3.1.0/espresso-idling-resource-3.1.0.pom", repo_root_path = "repository", @@ -17682,6 +19300,22 @@ maven_artifact( ) maven_artifact( + name = "androidx.test.espresso.espresso-idling-resource_3.5.0", + pom = "repository/androidx/test/espresso/espresso-idling-resource/3.5.0/espresso-idling-resource-3.5.0.pom", + repo_root_path = "repository", + repo_path = "androidx/test/espresso/espresso-idling-resource/3.5.0", + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.test.espresso.espresso-idling-resource_3.5.1", + pom = "repository/androidx/test/espresso/espresso-idling-resource/3.5.1/espresso-idling-resource-3.5.1.pom", + repo_root_path = "repository", + repo_path = "androidx/test/espresso/espresso-idling-resource/3.5.1", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.test.ext.junit_1.1.2", pom = "repository/androidx/test/ext/junit/1.1.2/junit-1.1.2.pom", repo_root_path = "repository", @@ -17724,6 +19358,20 @@ maven_artifact( ) maven_artifact( + name = "androidx.test.ext.junit_1.1.5", + pom = "repository/androidx/test/ext/junit/1.1.5/junit-1.1.5.pom", + repo_root_path = "repository", + repo_path = "androidx/test/ext/junit/1.1.5", + deps = [ + "junit.junit_4.13.2", + "androidx.test.core_1.5.0", + "androidx.test.monitor_1.6.1", + "androidx.annotation.annotation_1.2.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.test.services.storage_1.4.0", pom = "repository/androidx/test/services/storage/1.4.0/storage-1.4.0.pom", repo_root_path = "repository", @@ -17748,6 +19396,20 @@ maven_artifact( ) maven_artifact( + name = "androidx.test.services.storage_1.4.2", + pom = "repository/androidx/test/services/storage/1.4.2/storage-1.4.2.pom", + repo_root_path = "repository", + repo_path = "androidx/test/services/storage/1.4.2", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.test.monitor_1.6.0", + "com.google.code.findbugs.jsr305_2.0.2", + "androidx.test.annotation_1.0.1", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.test.services.test-services_1.4.0-alpha06", pom = "repository/androidx/test/services/test-services/1.4.0-alpha06/test-services-1.4.0-alpha06.pom", repo_root_path = "repository", @@ -17768,6 +19430,18 @@ maven_artifact( ) maven_artifact( + name = "androidx.test.annotation_1.0.1", + pom = "repository/androidx/test/annotation/1.0.1/annotation-1.0.1.pom", + repo_root_path = "repository", + repo_path = "androidx/test/annotation/1.0.1", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.annotation.annotation-experimental_1.1.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.test.core_1.3.0", pom = "repository/androidx/test/core/1.3.0/core-1.3.0.pom", repo_root_path = "repository", @@ -17820,6 +19494,24 @@ maven_artifact( ) maven_artifact( + name = "androidx.test.core_1.5.0", + pom = "repository/androidx/test/core/1.5.0/core-1.5.0.pom", + repo_root_path = "repository", + repo_path = "androidx/test/core/1.5.0", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.test.monitor_1.6.0", + "androidx.test.services.storage_1.4.2", + "androidx.lifecycle.lifecycle-common_2.3.1", + "androidx.tracing.tracing_1.0.0", + "com.google.guava.listenablefuture_1.0", + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + "androidx.concurrent.concurrent-futures_1.1.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.test.monitor_1.4.0", pom = "repository/androidx/test/monitor/1.4.0/monitor-1.4.0.pom", repo_root_path = "repository", @@ -17895,6 +19587,32 @@ maven_artifact( ) maven_artifact( + name = "androidx.test.monitor_1.6.0", + pom = "repository/androidx/test/monitor/1.6.0/monitor-1.6.0.pom", + repo_root_path = "repository", + repo_path = "androidx/test/monitor/1.6.0", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.test.annotation_1.0.1", + "androidx.tracing.tracing_1.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.test.monitor_1.6.1", + pom = "repository/androidx/test/monitor/1.6.1/monitor-1.6.1.pom", + repo_root_path = "repository", + repo_path = "androidx/test/monitor/1.6.1", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.test.annotation_1.0.1", + "androidx.tracing.tracing_1.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.test.orchestrator_1.4.0-alpha06", pom = "repository/androidx/test/orchestrator/1.4.0-alpha06/orchestrator-1.4.0-alpha06.pom", repo_root_path = "repository", @@ -18008,6 +19726,38 @@ maven_artifact( ) maven_artifact( + name = "androidx.test.runner_1.5.0", + pom = "repository/androidx/test/runner/1.5.0/runner-1.5.0.pom", + repo_root_path = "repository", + repo_path = "androidx/test/runner/1.5.0", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.test.annotation_1.0.1", + "androidx.test.monitor_1.6.0", + "androidx.test.services.storage_1.4.2", + "androidx.tracing.tracing_1.0.0", + "junit.junit_4.13.2", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( + name = "androidx.test.runner_1.5.2", + pom = "repository/androidx/test/runner/1.5.2/runner-1.5.2.pom", + repo_root_path = "repository", + repo_path = "androidx/test/runner/1.5.2", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.test.annotation_1.0.1", + "androidx.test.monitor_1.6.1", + "androidx.test.services.storage_1.4.2", + "androidx.tracing.tracing_1.0.0", + "junit.junit_4.13.2", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "androidx.tracing.tracing-perfetto-common_1.0.0-alpha01", pom = "repository/androidx/tracing/tracing-perfetto-common/1.0.0-alpha01/tracing-perfetto-common-1.0.0-alpha01.pom", repo_root_path = "repository", @@ -31728,6 +33478,17 @@ maven_artifact( ) maven_artifact( + name = "com.github.gundy.semver4j_0.16.4", + pom = "repository/com/github/gundy/semver4j/0.16.4/semver4j-0.16.4.pom", + repo_root_path = "repository", + repo_path = "com/github/gundy/semver4j/0.16.4", + deps = [ + "org.antlr.antlr4-runtime_4.5.2-1", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.github.javaparser.javaparser-core_3.17.0", pom = "repository/com/github/javaparser/javaparser-core/3.17.0/javaparser-core-3.17.0.pom", repo_root_path = "repository", @@ -31795,6 +33556,17 @@ maven_artifact( ) maven_artifact( + name = "com.google.android.gms.play-services-ads-base_21.5.0", + pom = "repository/com/google/android/gms/play-services-ads-base/21.5.0/play-services-ads-base-21.5.0.pom", + repo_root_path = "repository", + repo_path = "com/google/android/gms/play-services-ads-base/21.5.0", + deps = [ + "com.google.android.gms.play-services-basement_18.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.android.gms.play-services-ads-identifier_17.0.0", pom = "repository/com/google/android/gms/play-services-ads-identifier/17.0.0/play-services-ads-identifier-17.0.0.pom", repo_root_path = "repository", @@ -31806,6 +33578,17 @@ maven_artifact( ) maven_artifact( + name = "com.google.android.gms.play-services-ads-identifier_18.0.0", + pom = "repository/com/google/android/gms/play-services-ads-identifier/18.0.0/play-services-ads-identifier-18.0.0.pom", + repo_root_path = "repository", + repo_path = "com/google/android/gms/play-services-ads-identifier/18.0.0", + deps = [ + "com.google.android.gms.play-services-basement_18.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.android.gms.play-services-ads-lite_20.0.0", pom = "repository/com/google/android/gms/play-services-ads-lite/20.0.0/play-services-ads-lite-20.0.0.pom", repo_root_path = "repository", @@ -31836,6 +33619,21 @@ maven_artifact( ) maven_artifact( + name = "com.google.android.gms.play-services-ads-lite_21.5.0", + pom = "repository/com/google/android/gms/play-services-ads-lite/21.5.0/play-services-ads-lite-21.5.0.pom", + repo_root_path = "repository", + repo_path = "com/google/android/gms/play-services-ads-lite/21.5.0", + deps = [ + "androidx.work.work-runtime_2.7.0", + "com.google.android.gms.play-services-ads-base_21.5.0", + "com.google.android.gms.play-services-basement_18.0.0", + "com.google.android.gms.play-services-measurement-sdk-api_20.1.2", + "com.google.android.ump.user-messaging-platform_2.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.android.gms.play-services-ads_20.6.0", pom = "repository/com/google/android/gms/play-services-ads/20.6.0/play-services-ads-20.6.0.pom", repo_root_path = "repository", @@ -31855,6 +33653,25 @@ maven_artifact( ) maven_artifact( + name = "com.google.android.gms.play-services-ads_21.5.0", + pom = "repository/com/google/android/gms/play-services-ads/21.5.0/play-services-ads-21.5.0.pom", + repo_root_path = "repository", + repo_path = "com/google/android/gms/play-services-ads/21.5.0", + deps = [ + "androidx.browser.browser_1.4.0", + "androidx.collection.collection_1.0.0", + "androidx.core.core_1.0.0", + "com.google.android.gms.play-services-ads-base_21.5.0", + "com.google.android.gms.play-services-ads-identifier_18.0.0", + "com.google.android.gms.play-services-ads-lite_21.5.0", + "com.google.android.gms.play-services-appset_16.0.1", + "com.google.android.gms.play-services-basement_18.0.0", + "com.google.android.gms.play-services-tasks_18.0.1", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.android.gms.play-services-appset_16.0.0", pom = "repository/com/google/android/gms/play-services-appset/16.0.0/play-services-appset-16.0.0.pom", repo_root_path = "repository", @@ -31868,6 +33685,19 @@ maven_artifact( ) maven_artifact( + name = "com.google.android.gms.play-services-appset_16.0.1", + pom = "repository/com/google/android/gms/play-services-appset/16.0.1/play-services-appset-16.0.1.pom", + repo_root_path = "repository", + repo_path = "com/google/android/gms/play-services-appset/16.0.1", + deps = [ + "com.google.android.gms.play-services-base_18.0.0", + "com.google.android.gms.play-services-basement_18.0.0", + "com.google.android.gms.play-services-tasks_18.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.android.gms.play-services-base_17.0.0", pom = "repository/com/google/android/gms/play-services-base/17.0.0/play-services-base-17.0.0.pom", repo_root_path = "repository", @@ -31913,6 +33743,21 @@ maven_artifact( ) maven_artifact( + name = "com.google.android.gms.play-services-base_18.0.0", + pom = "repository/com/google/android/gms/play-services-base/18.0.0/play-services-base-18.0.0.pom", + repo_root_path = "repository", + repo_path = "com/google/android/gms/play-services-base/18.0.0", + deps = [ + "androidx.collection.collection_1.0.0", + "androidx.core.core_1.2.0", + "androidx.fragment.fragment_1.0.0", + "com.google.android.gms.play-services-basement_18.0.0", + "com.google.android.gms.play-services-tasks_18.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.android.gms.play-services-base_18.0.1", pom = "repository/com/google/android/gms/play-services-base/18.0.1/play-services-base-18.0.1.pom", repo_root_path = "repository", @@ -32102,6 +33947,19 @@ maven_artifact( ) maven_artifact( + name = "com.google.android.gms.play-services-maps_18.1.0", + pom = "repository/com/google/android/gms/play-services-maps/18.1.0/play-services-maps-18.1.0.pom", + repo_root_path = "repository", + repo_path = "com/google/android/gms/play-services-maps/18.1.0", + deps = [ + "androidx.fragment.fragment_1.0.0", + "com.google.android.gms.play-services-base_18.0.1", + "com.google.android.gms.play-services-basement_18.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.android.gms.play-services-measurement-base_18.0.0", pom = "repository/com/google/android/gms/play-services-measurement-base/18.0.0/play-services-measurement-base-18.0.0.pom", repo_root_path = "repository", @@ -32124,6 +33982,17 @@ maven_artifact( ) maven_artifact( + name = "com.google.android.gms.play-services-measurement-base_20.1.2", + pom = "repository/com/google/android/gms/play-services-measurement-base/20.1.2/play-services-measurement-base-20.1.2.pom", + repo_root_path = "repository", + repo_path = "com/google/android/gms/play-services-measurement-base/20.1.2", + deps = [ + "com.google.android.gms.play-services-basement_18.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.android.gms.play-services-measurement-sdk-api_18.0.0", pom = "repository/com/google/android/gms/play-services-measurement-sdk-api/18.0.0/play-services-measurement-sdk-api-18.0.0.pom", repo_root_path = "repository", @@ -32148,6 +34017,18 @@ maven_artifact( ) maven_artifact( + name = "com.google.android.gms.play-services-measurement-sdk-api_20.1.2", + pom = "repository/com/google/android/gms/play-services-measurement-sdk-api/20.1.2/play-services-measurement-sdk-api-20.1.2.pom", + repo_root_path = "repository", + repo_path = "com/google/android/gms/play-services-measurement-sdk-api/20.1.2", + deps = [ + "com.google.android.gms.play-services-basement_18.0.0", + "com.google.android.gms.play-services-measurement-base_20.1.2", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.android.gms.play-services-pay_16.0.3", pom = "repository/com/google/android/gms/play-services-pay/16.0.3/play-services-pay-16.0.3.pom", repo_root_path = "repository", @@ -32161,6 +34042,19 @@ maven_artifact( ) maven_artifact( + name = "com.google.android.gms.play-services-pay_16.1.0", + pom = "repository/com/google/android/gms/play-services-pay/16.1.0/play-services-pay-16.1.0.pom", + repo_root_path = "repository", + repo_path = "com/google/android/gms/play-services-pay/16.1.0", + deps = [ + "com.google.android.gms.play-services-base_18.0.1", + "com.google.android.gms.play-services-basement_18.0.0", + "com.google.android.gms.play-services-tasks_18.0.1", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.android.gms.play-services-tasks-license_12.0.1", pom = "repository/com/google/android/gms/play-services-tasks-license/12.0.1/play-services-tasks-license-12.0.1.pom", repo_root_path = "repository", @@ -32236,6 +34130,17 @@ maven_artifact( ) maven_artifact( + name = "com.google.android.gms.play-services-tasks_18.0.0", + pom = "repository/com/google/android/gms/play-services-tasks/18.0.0/play-services-tasks-18.0.0.pom", + repo_root_path = "repository", + repo_path = "com/google/android/gms/play-services-tasks/18.0.0", + deps = [ + "com.google.android.gms.play-services-basement_18.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.android.gms.play-services-tasks_18.0.1", pom = "repository/com/google/android/gms/play-services-tasks/18.0.1/play-services-tasks-18.0.1.pom", repo_root_path = "repository", @@ -32277,6 +34182,20 @@ maven_artifact( ) maven_artifact( + name = "com.google.android.gms.play-services-wearable_18.0.0", + pom = "repository/com/google/android/gms/play-services-wearable/18.0.0/play-services-wearable-18.0.0.pom", + repo_root_path = "repository", + repo_path = "com/google/android/gms/play-services-wearable/18.0.0", + deps = [ + "androidx.core.core_1.0.0", + "com.google.android.gms.play-services-base_18.0.1", + "com.google.android.gms.play-services-basement_18.0.0", + "com.google.android.gms.play-services-tasks_18.0.1", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.android.horologist.horologist-compose-tools_0.1.5", pom = "repository/com/google/android/horologist/horologist-compose-tools/0.1.5/horologist-compose-tools-0.1.5.pom", repo_root_path = "repository", @@ -32514,6 +34433,32 @@ maven_artifact( ) maven_artifact( + name = "com.google.android.material.material_1.8.0", + pom = "repository/com/google/android/material/material/1.8.0/material-1.8.0.pom", + repo_root_path = "repository", + repo_path = "com/google/android/material/material/1.8.0", + deps = [ + "androidx.annotation.annotation_1.2.0", + "androidx.appcompat.appcompat_1.5.0", + "androidx.cardview.cardview_1.0.0", + "androidx.coordinatorlayout.coordinatorlayout_1.1.0", + "androidx.constraintlayout.constraintlayout_2.0.1", + "androidx.core.core_1.6.0", + "androidx.drawerlayout.drawerlayout_1.1.1", + "androidx.dynamicanimation.dynamicanimation_1.0.0", + "androidx.annotation.annotation-experimental_1.0.0", + "androidx.fragment.fragment_1.2.5", + "androidx.lifecycle.lifecycle-runtime_2.0.0", + "androidx.recyclerview.recyclerview_1.0.0", + "androidx.transition.transition_1.2.0", + "androidx.vectordrawable.vectordrawable_1.1.0", + "androidx.viewpager2.viewpager2_1.0.0", + "com.google.errorprone.error_prone_annotations_2.15.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.android.support.wearable_2.9.0", pom = "repository/com/google/android/support/wearable/2.9.0/wearable-2.9.0.pom", repo_root_path = "repository", @@ -32543,6 +34488,19 @@ maven_artifact( ) maven_artifact( + name = "com.google.android.ump.user-messaging-platform_2.0.0", + pom = "repository/com/google/android/ump/user-messaging-platform/2.0.0/user-messaging-platform-2.0.0.pom", + repo_root_path = "repository", + repo_path = "com/google/android/ump/user-messaging-platform/2.0.0", + deps = [ + "androidx.annotation.annotation_1.0.0", + "com.google.android.gms.play-services-ads-identifier_17.0.0", + "com.google.android.gms.play-services-basement_17.0.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.android.wearable.wearable_2.9.0", pom = "repository/com/google/android/wearable/wearable/2.9.0/wearable-2.9.0.pom", repo_root_path = "repository", @@ -32735,6 +34693,14 @@ maven_artifact( ) maven_artifact( + name = "com.google.code.findbugs.jsr305_2.0.2", + pom = "repository/com/google/code/findbugs/jsr305/2.0.2/jsr305-2.0.2.pom", + repo_root_path = "repository", + repo_path = "com/google/code/findbugs/jsr305/2.0.2", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.code.findbugs.jsr305_3.0.0", pom = "repository/com/google/code/findbugs/jsr305/3.0.0/jsr305-3.0.0.pom", repo_root_path = "repository", @@ -33159,6 +35125,15 @@ maven_artifact( ) maven_artifact( + name = "com.google.errorprone.error_prone_annotations_2.15.0", + pom = "repository/com/google/errorprone/error_prone_annotations/2.15.0/error_prone_annotations-2.15.0.pom", + repo_root_path = "repository", + repo_path = "com/google/errorprone/error_prone_annotations/2.15.0", + parent = "com.google.errorprone.error_prone_parent_2.15.0", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "com.google.errorprone.error_prone_annotations_2.2.0", pom = "repository/com/google/errorprone/error_prone_annotations/2.2.0/error_prone_annotations-2.2.0.pom", repo_root_path = "repository", @@ -34533,6 +36508,14 @@ maven_artifact( ) maven_artifact( + name = "de.undercouch.gradle-download-task_4.1.1", + pom = "repository/de/undercouch/gradle-download-task/4.1.1/gradle-download-task-4.1.1.pom", + repo_root_path = "repository", + repo_path = "de/undercouch/gradle-download-task/4.1.1", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "info.picocli.picocli_4.5.2", pom = "repository/info/picocli/picocli/4.5.2/picocli-4.5.2.pom", repo_root_path = "repository", @@ -37278,6 +39261,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.android.org.jetbrains.kotlin.android.gradle.plugin_1.8.10", + pom = "repository/org/jetbrains/kotlin/android/org.jetbrains.kotlin.android.gradle.plugin/1.8.10/org.jetbrains.kotlin.android.gradle.plugin-1.8.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/android/org.jetbrains.kotlin.android.gradle.plugin/1.8.10", + deps = [ + "org.jetbrains.kotlin.kotlin-gradle-plugin_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.android.org.jetbrains.kotlin.android.gradle.plugin_1.8.20-Beta", pom = "repository/org/jetbrains/kotlin/android/org.jetbrains.kotlin.android.gradle.plugin/1.8.20-Beta/org.jetbrains.kotlin.android.gradle.plugin-1.8.20-Beta.pom", repo_root_path = "repository", @@ -37322,6 +39316,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.jvm.org.jetbrains.kotlin.jvm.gradle.plugin_1.7.10", + pom = "repository/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.7.10/org.jetbrains.kotlin.jvm.gradle.plugin-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-gradle-plugin_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.jvm.org.jetbrains.kotlin.jvm.gradle.plugin_1.7.20", pom = "repository/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.7.20/org.jetbrains.kotlin.jvm.gradle.plugin-1.7.20.pom", repo_root_path = "repository", @@ -37344,6 +39349,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.jvm.org.jetbrains.kotlin.jvm.gradle.plugin_1.8.10", + pom = "repository/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.8.10/org.jetbrains.kotlin.jvm.gradle.plugin-1.8.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.8.10", + deps = [ + "org.jetbrains.kotlin.kotlin-gradle-plugin_1.8.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.jvm.org.jetbrains.kotlin.jvm.gradle.plugin_1.8.20-Beta", pom = "repository/org/jetbrains/kotlin/jvm/org.jetbrains.kotlin.jvm.gradle.plugin/1.8.20-Beta/org.jetbrains.kotlin.jvm.gradle.plugin-1.8.20-Beta.pom", repo_root_path = "repository", @@ -37382,6 +39398,14 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.jvm-abi-gen_1.8.10", + pom = "repository/org/jetbrains/kotlin/jvm-abi-gen/1.8.10/jvm-abi-gen-1.8.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/jvm-abi-gen/1.8.10", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.jvm-abi-gen_1.8.20-Beta", pom = "repository/org/jetbrains/kotlin/jvm-abi-gen/1.8.20-Beta/jvm-abi-gen-1.8.20-Beta.pom", repo_root_path = "repository", @@ -37621,6 +39645,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-android-extensions_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-android-extensions/1.7.10/kotlin-android-extensions-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-android-extensions/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-android-extensions_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-android-extensions/1.7.20/kotlin-android-extensions-1.7.20.pom", repo_root_path = "repository", @@ -37768,6 +39803,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-annotation-processing-gradle_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.7.10/kotlin-annotation-processing-gradle-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-annotation-processing-gradle_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.7.20/kotlin-annotation-processing-gradle-1.7.20.pom", repo_root_path = "repository", @@ -37823,6 +39869,14 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-bom_1.8.0", + pom = "repository/org/jetbrains/kotlin/kotlin-bom/1.8.0/kotlin-bom-1.8.0.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-bom/1.8.0", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-build-common_1.3.20", pom = "repository/org/jetbrains/kotlin/kotlin-build-common/1.3.20/kotlin-build-common-1.3.20.pom", repo_root_path = "repository", @@ -37887,6 +39941,14 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-build-common_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-build-common/1.7.10/kotlin-build-common-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-build-common/1.7.10", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-build-common_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-build-common/1.7.20/kotlin-build-common-1.7.20.pom", repo_root_path = "repository", @@ -38039,6 +40101,22 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.10/kotlin-compiler-embeddable-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + "org.jetbrains.kotlin.kotlin-script-runtime_1.7.10", + "org.jetbrains.kotlin.kotlin-reflect_1.7.10", + "org.jetbrains.kotlin.kotlin-daemon-embeddable_1.7.10", + "org.jetbrains.intellij.deps.trove4j_1.0.20200330", + "net.java.dev.jna.jna_5.6.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.20/kotlin-compiler-embeddable-1.7.20.pom", repo_root_path = "repository", @@ -38089,6 +40167,9 @@ maven_artifact( repo_root_path = "repository", repo_path = "org/jetbrains/kotlin/kotlin-compiler-embeddable/1.8.10", deps = [ + "org.jetbrains.kotlin.kotlin-stdlib_1.8.10", + "org.jetbrains.kotlin.kotlin-script-runtime_1.8.10", + "org.jetbrains.kotlin.kotlin-reflect_1.6.10", "org.jetbrains.kotlin.kotlin-daemon-embeddable_1.8.10", "org.jetbrains.intellij.deps.trove4j_1.0.20200330", "net.java.dev.jna.jna_5.6.0", @@ -38220,6 +40301,20 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-compiler-runner_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-compiler-runner/1.7.10/kotlin-compiler-runner-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-compiler-runner/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-build-common_1.7.10", + "org.jetbrains.kotlin.kotlin-daemon-client_1.7.10", + "org.jetbrains.kotlinx.kotlinx-coroutines-core-jvm_1.5.0", + "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-compiler-runner_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-compiler-runner/1.7.20/kotlin-compiler-runner-1.7.20.pom", repo_root_path = "repository", @@ -38416,6 +40511,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-daemon-client_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-daemon-client/1.7.10/kotlin-daemon-client-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-daemon-client/1.7.10", + deps = [ + "org.jetbrains.kotlinx.kotlinx-coroutines-core-jvm_1.5.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-daemon-client_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-daemon-client/1.7.20/kotlin-daemon-client-1.7.20.pom", repo_root_path = "repository", @@ -38519,6 +40625,14 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-daemon-embeddable_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.10/kotlin-daemon-embeddable-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.10", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-daemon-embeddable_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.7.20/kotlin-daemon-embeddable-1.7.20.pom", repo_root_path = "repository", @@ -38665,6 +40779,19 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-gradle-plugin-api_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.10/kotlin-gradle-plugin-api-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-native-utils_1.7.10", + "org.jetbrains.kotlin.kotlin-project-model_1.7.10", + "org.jetbrains.kotlin.kotlin-tooling-core_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-gradle-plugin-api_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.7.20/kotlin-gradle-plugin-api-1.7.20.pom", repo_root_path = "repository", @@ -38795,6 +40922,14 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-gradle-plugin-idea_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.7.10/kotlin-gradle-plugin-idea-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.7.10", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-gradle-plugin-idea_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-idea/1.7.20/kotlin-gradle-plugin-idea-1.7.20.pom", repo_root_path = "repository", @@ -38927,6 +41062,14 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-gradle-plugin-model_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.7.10/kotlin-gradle-plugin-model-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.7.10", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-gradle-plugin-model_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.7.20/kotlin-gradle-plugin-model-1.7.20.pom", repo_root_path = "repository", @@ -39165,6 +41308,33 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-gradle-plugin_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin/1.7.10/kotlin-gradle-plugin-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-gradle-plugin/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-gradle-plugin-model_1.7.10", + "org.jetbrains.kotlin.kotlin-tooling-core_1.7.10", + "org.jetbrains.kotlin.kotlin-gradle-plugin-idea_1.7.10", + "org.jetbrains.kotlin.kotlin-util-klib_1.7.10", + "org.jetbrains.kotlin.kotlin-klib-commonizer-api_1.7.10", + "org.jetbrains.kotlin.kotlin-tooling-metadata_1.7.10", + "org.jetbrains.kotlin.kotlin-project-model_1.7.10", + "com.google.code.gson.gson_2.8.9", + "com.google.guava.guava_29.0-jre", + "de.undercouch.gradle-download-task_4.1.1", + "com.github.gundy.semver4j_0.16.4", + "org.jetbrains.kotlin.kotlin-compiler-embeddable_1.7.10", + "org.jetbrains.kotlin.kotlin-annotation-processing-gradle_1.7.10", + "org.jetbrains.kotlin.kotlin-android-extensions_1.7.10", + "org.jetbrains.kotlin.kotlin-compiler-runner_1.7.10", + "org.jetbrains.kotlin.kotlin-scripting-compiler-embeddable_1.7.10", + "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-gradle-plugin_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-gradle-plugin/1.7.20/kotlin-gradle-plugin-1.7.20.pom", repo_root_path = "repository", @@ -39333,6 +41503,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-klib-commonizer-api_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.7.10/kotlin-klib-commonizer-api-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-native-utils_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-klib-commonizer-api_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-klib-commonizer-api/1.7.20/kotlin-klib-commonizer-api-1.7.20.pom", repo_root_path = "repository", @@ -39455,6 +41636,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-native-utils_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-native-utils/1.7.10/kotlin-native-utils-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-native-utils/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-util-io_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-native-utils_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-native-utils/1.7.20/kotlin-native-utils-1.7.20.pom", repo_root_path = "repository", @@ -39558,6 +41750,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-project-model_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-project-model/1.7.10/kotlin-project-model-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-project-model/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-tooling-core_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-project-model_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-project-model/1.7.20/kotlin-project-model-1.7.20.pom", repo_root_path = "repository", @@ -39789,6 +41992,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-reflect_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-reflect/1.7.10/kotlin-reflect-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-reflect/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-reflect_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-reflect/1.7.20/kotlin-reflect-1.7.20.pom", repo_root_path = "repository", @@ -39908,6 +42122,14 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-script-runtime_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-script-runtime/1.7.10/kotlin-script-runtime-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-script-runtime/1.7.10", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-script-runtime_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-script-runtime/1.7.20/kotlin-script-runtime-1.7.20.pom", repo_root_path = "repository", @@ -40020,6 +42242,14 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-scripting-common_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-scripting-common/1.7.10/kotlin-scripting-common-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-scripting-common/1.7.10", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-scripting-common_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-scripting-common/1.7.20/kotlin-scripting-common-1.7.20.pom", repo_root_path = "repository", @@ -40148,6 +42378,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-scripting-compiler-embeddable_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.10/kotlin-scripting-compiler-embeddable-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-scripting-compiler-embeddable_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.7.20/kotlin-scripting-compiler-embeddable-1.7.20.pom", repo_root_path = "repository", @@ -40294,6 +42535,18 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.10/kotlin-scripting-compiler-impl-embeddable-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-scripting-common_1.7.10", + "org.jetbrains.kotlin.kotlin-scripting-jvm_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-scripting-compiler-impl-embeddable_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.7.20/kotlin-scripting-compiler-impl-embeddable-1.7.20.pom", repo_root_path = "repository", @@ -40437,6 +42690,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-scripting-jvm_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.10/kotlin-scripting-jvm-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-scripting-common_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-scripting-jvm_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-scripting-jvm/1.7.20/kotlin-scripting-jvm-1.7.20.pom", repo_root_path = "repository", @@ -40716,6 +42980,14 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-stdlib-common_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.10/kotlin-stdlib-common-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-stdlib-common/1.7.10", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-stdlib-common_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.20/kotlin-stdlib-common-1.7.20.pom", repo_root_path = "repository", @@ -40943,6 +43215,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-stdlib-jdk7_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.10/kotlin-stdlib-jdk7-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-stdlib-jdk7_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.20/kotlin-stdlib-jdk7-1.7.20.pom", repo_root_path = "repository", @@ -41202,6 +43485,18 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-stdlib-jdk8_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.10/kotlin-stdlib-jdk8-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + "org.jetbrains.kotlin.kotlin-stdlib-jdk7_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-stdlib-jdk8_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.20/kotlin-stdlib-jdk8-1.7.20.pom", repo_root_path = "repository", @@ -41709,6 +44004,18 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-stdlib/1.7.10/kotlin-stdlib-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-stdlib/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-stdlib-common_1.7.10", + "org.jetbrains.annotations_13.0", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-stdlib_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-stdlib/1.7.20/kotlin-stdlib-1.7.20.pom", repo_root_path = "repository", @@ -41781,6 +44088,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-test_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-test/1.7.10/kotlin-test-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-test/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-stdlib_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-tooling-core_1.7.0", pom = "repository/org/jetbrains/kotlin/kotlin-tooling-core/1.7.0/kotlin-tooling-core-1.7.0.pom", repo_root_path = "repository", @@ -41789,6 +44107,14 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-tooling-core_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-tooling-core/1.7.10/kotlin-tooling-core-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-tooling-core/1.7.10", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-tooling-core_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-tooling-core/1.7.20/kotlin-tooling-core-1.7.20.pom", repo_root_path = "repository", @@ -41876,6 +44202,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-tooling-metadata_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-tooling-metadata/1.7.10/kotlin-tooling-metadata-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-tooling-metadata/1.7.10", + deps = [ + "com.google.code.gson.gson_2.8.9", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-util-io_1.3.72", pom = "repository/org/jetbrains/kotlin/kotlin-util-io/1.3.72/kotlin-util-io-1.3.72.pom", repo_root_path = "repository", @@ -41930,6 +44267,14 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-util-io_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-util-io/1.7.10/kotlin-util-io-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-util-io/1.7.10", + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-util-io_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-util-io/1.7.20/kotlin-util-io-1.7.20.pom", repo_root_path = "repository", @@ -42038,6 +44383,17 @@ maven_artifact( ) maven_artifact( + name = "org.jetbrains.kotlin.kotlin-util-klib_1.7.10", + pom = "repository/org/jetbrains/kotlin/kotlin-util-klib/1.7.10/kotlin-util-klib-1.7.10.pom", + repo_root_path = "repository", + repo_path = "org/jetbrains/kotlin/kotlin-util-klib/1.7.10", + deps = [ + "org.jetbrains.kotlin.kotlin-util-io_1.7.10", + ], + visibility = ["//visibility:public"], +) + +maven_artifact( name = "org.jetbrains.kotlin.kotlin-util-klib_1.7.20", pom = "repository/org/jetbrains/kotlin/kotlin-util-klib/1.7.20/kotlin-util-klib-1.7.20.pom", repo_root_path = "repository", @@ -43880,6 +46236,13 @@ maven_artifact( ) maven_artifact( + name = "com.google.errorprone.error_prone_parent_2.15.0", + pom = "repository/com/google/errorprone/error_prone_parent/2.15.0/error_prone_parent-2.15.0.pom", + repo_root_path = "repository", + repo_path = "com/google/errorprone/error_prone_parent/2.15.0", +) + +maven_artifact( name = "com.google.errorprone.error_prone_parent_2.2.0", pom = "repository/com/google/errorprone/error_prone_parent/2.2.0/error_prone_parent-2.2.0.pom", repo_root_path = "repository", diff --git a/bazel/maven/artifacts.bzl b/bazel/maven/artifacts.bzl index 3a6aab3e02..48e51b6414 100644 --- a/bazel/maven/artifacts.bzl +++ b/bazel/maven/artifacts.bzl @@ -142,11 +142,13 @@ ARTIFACTS = [ "org.jetbrains.dokka:dokka-core:1.4.32", "org.jetbrains.intellij.deps:asm-all:8.0.1", "org.jetbrains.intellij.deps:trove4j:1.0.20181211", - "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.7.10", - "org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.7.10", - "org.jetbrains.kotlin:kotlin-compiler:1.7.10", - "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10", - "org.jetbrains.kotlin:kotlin-test:1.7.10", + "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.8.20-RC2", + "org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.8.20-RC2", + "org.jetbrains.kotlin:kotlin-compiler:1.8.20-RC2", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.20-RC2", + "org.jetbrains.kotlin:kotlin-test:1.8.20-RC2", + "org.jetbrains.kotlin:kotlin-test-junit:1.8.20-RC2", + "org.jetbrains.kotlin:kotlin-reflect:1.8.20-RC2", "org.jetbrains.kotlinx:kotlinx-cli-jvm:0.3.1", "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.3", "org.jetbrains:markdown:0.2.1", @@ -184,14 +186,20 @@ DATA = [ "android.arch.navigation:navigation-fragment:1.0.0", "android.arch.navigation:navigation-ui:1.0.0", "android.arch.persistence.room:runtime:1.0.0", - "androidx.activity:activity-compose:1.5.1", + "androidx.activity:activity-compose:1.5.1", # Needed for com.android.tools.idea.wizard.template.impl.activities.composeWearActivity.commonComposeRecipe + "androidx.activity:activity-compose:1.7.0", "androidx.activity:activity-ktx:1.4.0", + "androidx.activity:activity-ktx:1.6.0", # Still needed from navigation-fragment-ktx:2.5.3 + "androidx.activity:activity-ktx:1.7.0", "androidx.annotation:annotation:1.2.0", "androidx.annotation:annotation:1.2.0-beta01", + "androidx.annotation:annotation:1.6.0", + "androidx.annotation:annotation-jvm:1.6.0", "androidx.appcompat:appcompat:1.0.2", "androidx.appcompat:appcompat:1.3.0", "androidx.appcompat:appcompat:1.3.0-beta01", "androidx.appcompat:appcompat:1.4.1", + "androidx.appcompat:appcompat:1.6.1", "androidx.privacysandbox.sdkruntime:sdkruntime-client:1.0.0-SNAPSHOT", # built locally from androidx-platform-dev "androidx.privacysandbox.sdkruntime:sdkruntime-core:1.0.0-SNAPSHOT", # built locally from androidx-platform-dev "androidx.privacysandbox.tools:tools:1.0.0-alpha02", @@ -200,29 +208,45 @@ DATA = [ "androidx.privacysandbox.tools:tools-apipackager:1.0.0-alpha02", "androidx.privacysandbox.tools:tools-core:1.0.0-alpha02", "androidx.benchmark:benchmark-baseline-profile-gradle-plugin:1.2.0-SNAPSHOT", + "androidx.benchmark:benchmark-baseline-profile-gradle-plugin:1.2.0-alpha12", "androidx.benchmark:benchmark-gradle-plugin:1.1.1", "androidx.compose.animation:animation:1.2.0-alpha05", "androidx.compose.animation:animation:1.3.0", + "androidx.compose.animation:animation:1.4.0", "androidx.compose.foundation:foundation:1.2.0-alpha05", "androidx.compose.foundation:foundation:1.3.0", + "androidx.compose.foundation:foundation:1.4.0", "androidx.compose.compiler:compiler:1.2.0", "androidx.compose.compiler:compiler:1.3.2", + "androidx.compose.compiler:compiler:1.4.3", "androidx.compose:compose-bom:pom:2022.10.00", + "androidx.compose:compose-bom:pom:2023.03.00", "androidx.compose.material:material:1.3.0", + "androidx.compose.material:material:1.3.1", # Needed for activities.composeWearActivityRecipe + "androidx.compose.material:material:1.4.0", "androidx.compose.material3:material3:1.0.0-alpha02", "androidx.compose.material3:material3:1.0.0", + "androidx.compose.material3:material3:1.0.1", "androidx.compose.material:material-icons-extended:1.2.0-alpha05", "androidx.compose.material:material-icons-extended:1.3.0", + "androidx.compose.material:material-icons-extended:1.4.0", "androidx.compose.runtime:runtime-livedata:1.2.0-alpha05", "androidx.compose.runtime:runtime-livedata:1.3.0", + "androidx.compose.runtime:runtime-livedata:1.4.0", "androidx.compose.ui:ui-test-junit4:1.2.0", "androidx.compose.ui:ui-test-junit4:1.3.0", + "androidx.compose.ui:ui-test-junit4:1.4.0", "androidx.compose.ui:ui-test-manifest:1.2.0", "androidx.compose.ui:ui-test-manifest:1.3.0", + "androidx.compose.ui:ui-test-manifest:1.4.0", + "androidx.compose.ui:ui:1.3.0", + "androidx.compose.ui:ui:1.4.0", "androidx.compose.ui:ui-tooling:1.2.0", - "androidx.compose.ui:ui-tooling:1.3.0", + "androidx.compose.ui:ui-tooling:1.3.0", # Needed for ComposeHelloWorldTest#appAndTestsBuildSuccessfully + "androidx.compose.ui:ui-tooling:1.4.0", "androidx.constraintlayout:constraintlayout:1.1.3", "androidx.constraintlayout:constraintlayout:2.1.3", + "androidx.constraintlayout:constraintlayout:2.1.4", "androidx.core:core:1.5.0-beta01", "androidx.core:core:1.5.0-rc02", "androidx.core:core-ktx:1.0.1", @@ -236,50 +260,74 @@ DATA = [ "androidx.customview:customview-poolingcontainer:1.0.0-beta01", "androidx.databinding:viewbinding:7.2.0", "androidx.databinding:viewbinding:7.4.1", + "androidx.databinding:viewbinding:8.0.0-beta04", + "androidx.emoji2:emoji2-views-helper:1.3.0", "androidx.fragment:fragment:1.3.0", "androidx.fragment:fragment:1.3.0-rc01", "androidx.games:games-activity:1.2.2", "androidx.leanback:leanback:1.0.0", "androidx.legacy:legacy-support-v13:1.0.0", "androidx.legacy:legacy-support-v4:1.0.0", + "androidx.lifecycle:lifecycle-common-java8:2.4.0", + "androidx.lifecycle:lifecycle-common-java8:2.6.1", "androidx.lifecycle:lifecycle-extensions:2.2.0", "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0", "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1", + "androidx.lifecycle:lifecycle-livedata-ktx:2.4.0", # Needed for tools/data-binding:runtimeLibrariesAndroidX "androidx.lifecycle:lifecycle-livedata-ktx:2.4.1", - "androidx.lifecycle:lifecycle-common-java8:2.4.0", - "androidx.lifecycle:lifecycle-process:2.4.0", - "androidx.lifecycle:lifecycle-service:2.4.0", - "androidx.lifecycle:lifecycle-livedata-ktx:2.4.0", - "androidx.lifecycle:lifecycle-runtime:2.4.0", - "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0", - "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0", + "androidx.lifecycle:lifecycle-livedata-ktx:2.6.1", + "androidx.lifecycle:lifecycle-process:2.4.0", # Needed for tools/data-binding:runtimeLibrariesAndroidX + "androidx.lifecycle:lifecycle-process:2.6.1", + "androidx.lifecycle:lifecycle-service:2.4.0", # Needed for tools/data-binding:runtimeLibrariesAndroidX + "androidx.lifecycle:lifecycle-service:2.6.1", + "androidx.lifecycle:lifecycle-runtime:2.4.0", # Needed for tools/data-binding:runtimeLibrariesAndroidX + "androidx.lifecycle:lifecycle-runtime:2.6.1", + "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0", # Needed for tools/data-binding:runtimeLibrariesAndroidX + "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1", # Needed for com.android.tools.idea.wizard.template.impl.activities.composeWearActivity.commonComposeRecipe + "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1", + "androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1", + "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1", # Needed for AndroidTestRunConfigurationTest#testCanRunLibTestsInDebugBuildWithNoAndroidManifest + "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0", # Needed for tools/data-binding:runtimeLibrariesAndroidX "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1", + "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1", + "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1", "androidx.media:media:1.5.0", + "androidx.media:media:1.6.0", "androidx.navigation:navigation-fragment:2.0.0", "androidx.navigation:navigation-fragment:2.5.2", + "androidx.navigation:navigation-fragment:2.5.3", "androidx.navigation:navigation-fragment-ktx:2.3.5", "androidx.navigation:navigation-fragment-ktx:2.4.1", "androidx.navigation:navigation-fragment-ktx:2.5.2", + "androidx.navigation:navigation-fragment-ktx:2.5.3", "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.1", "androidx.navigation:navigation-safe-args-gradle-plugin:2.5.2", + "androidx.navigation:navigation-safe-args-gradle-plugin:2.5.3", "androidx.navigation:navigation-ui:2.5.2", + "androidx.navigation:navigation-ui:2.5.3", "androidx.navigation:navigation-ui-ktx:2.3.5", "androidx.navigation:navigation-ui-ktx:2.4.1", "androidx.navigation:navigation-ui-ktx:2.5.2", + "androidx.navigation:navigation-ui-ktx:2.5.3", "androidx.palette:palette-ktx:1.0.0", "androidx.preference:preference:1.0.0", "androidx.preference:preference:1.2.0", "androidx.profileinstaller:profileinstaller:1.3.0-beta01", "androidx.recyclerview:recyclerview:1.2.1", + "androidx.recyclerview:recyclerview:1.3.0", "androidx.room:room-compiler:2.0.0", "androidx.room:room-runtime:2.0.0", "androidx.slice:slice-builders:1.0.0", "androidx.startup:startup-runtime:1.1.1", + "androidx.test:core:1.3.0", # TODO: To be removed once dependent tests pass b/273872043 "androidx.test:core:1.4.0-alpha06", + "androidx.test:core:1.5.0", "androidx.test.espresso:espresso-core:3.1.0", "androidx.test.espresso:espresso-core:3.2.0", "androidx.test.espresso:espresso-core:3.4.0", - "androidx.test.ext:junit:1.1.2", + "androidx.test.espresso:espresso-core:3.5.1", + "androidx.test.ext:junit:1.1.2", # TODO: To be removed once dependent tests pass b/273872043 + "androidx.test.ext:junit:1.1.5", "androidx.test.ext:junit:1.1.3-alpha02", "androidx.test:orchestrator:1.4.0-alpha06", "androidx.test:rules:1.1.0", @@ -381,14 +429,18 @@ DATA = [ "com.github.bumptech.glide:glide:4.11.0", "com.google.android:android:4.1.1.4", "com.google.android.gms:play-services-ads:20.6.0", + "com.google.android.gms:play-services-ads:21.5.0", "com.google.android.gms:play-services-base:15.0.1", "com.google.android.gms:play-services-base:17.6.0", "com.google.android.gms:play-services-gass:20.0.0", "com.google.android.gms:play-services-maps:17.0.1", "com.google.android.gms:play-services-maps:18.0.2", + "com.google.android.gms:play-services-maps:18.1.0", "com.google.android.gms:play-services-pay:16.0.3", + "com.google.android.gms:play-services-pay:16.1.0", "com.google.android.gms:play-services-wallet:19.1.0", "com.google.android.gms:play-services-wearable:17.1.0", + "com.google.android.gms:play-services-wearable:18.0.0", "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1", "com.google.android.material:material:1.1.0", "com.google.android.material:material:1.3.0", @@ -396,6 +448,7 @@ DATA = [ "com.google.android.material:material:1.5.0-alpha04", "com.google.android.material:material:1.5.0", "com.google.android.material:material:1.7.0", + "com.google.android.material:material:1.8.0", "com.google.android.support:wearable:2.9.0", "com.google.android.wearable:wearable:2.9.0", "com.google.auto.service:auto-service:1.0-rc2", @@ -490,16 +543,21 @@ DATA = [ "org.jetbrains.kotlin.kapt:org.jetbrains.kotlin.kapt.gradle.plugin:1.8.20-Beta", "org.jetbrains.kotlin.android:org.jetbrains.kotlin.android.gradle.plugin:1.7.20", "org.jetbrains.kotlin.android:org.jetbrains.kotlin.android.gradle.plugin:1.7.21", + "org.jetbrains.kotlin.android:org.jetbrains.kotlin.android.gradle.plugin:1.8.10", "org.jetbrains.kotlin.android:org.jetbrains.kotlin.android.gradle.plugin:1.8.20-Beta", "org.jetbrains.kotlin.android:org.jetbrains.kotlin.android.gradle.plugin:1.8.0", + "org.jetbrains.kotlin.android:org.jetbrains.kotlin.android.gradle.plugin:1.8.10", "org.jetbrains.kotlin:jvm-abi-gen:1.7.0", "org.jetbrains.kotlin:jvm-abi-gen:1.7.20", + "org.jetbrains.kotlin:jvm-abi-gen:1.8.10", "org.jetbrains.kotlin:jvm-abi-gen:1.8.20-Beta", "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.6.10", "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.6.21", "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.7.0", + "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.7.10", "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.7.20", "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.7.21", + "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.8.10", "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.8.20-Beta", "org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.3.41", "org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.3.72", @@ -514,12 +572,14 @@ DATA = [ "org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.8.20-Beta", "org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.8.0", "org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.8.10", + "org.jetbrains.kotlin:kotlin-bom:1.8.0", "org.jetbrains.kotlin:kotlin-compiler:1.7.0", "org.jetbrains.kotlin:kotlin-compiler:1.7.20", "org.jetbrains.kotlin:kotlin-compiler:1.8.20-Beta", "org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.0", "org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.20", "org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.21", + "org.jetbrains.kotlin:kotlin-compiler-embeddable:1.8.10", "org.jetbrains.kotlin:kotlin-compiler-embeddable:1.8.20-Beta", "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.41", "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72", @@ -531,6 +591,7 @@ DATA = [ "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10", "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20", "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.21", + "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10", "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20-Beta", "org.jetbrains.kotlin:kotlin-gradle-plugin:jar:gradle70:1.7.0", "org.jetbrains.kotlin:kotlin-gradle-plugin:jar:gradle70:1.7.10", @@ -546,6 +607,7 @@ DATA = [ "org.jetbrains.kotlin:kotlin-gradle-plugin:jar:gradle76:1.8.0", "org.jetbrains.kotlin:kotlin-gradle-plugin:jar:gradle76:1.8.10", "org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.7.0", + "org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.7.10", "org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.7.20", "org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.7.21", "org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.8.20-Beta", @@ -603,6 +665,7 @@ DATA = [ "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.6", "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.6", "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1", + "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4", "org.jetbrains.skiko:skiko-awt-runtime-linux-x64:0.7.16", "org.jetbrains.skiko:skiko-awt-runtime-macos-arm64:0.7.16", "org.jetbrains.skiko:skiko-awt-runtime-macos-x64:0.7.16", diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index d349e7cb5d..4f67e80c8c 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -30,6 +30,10 @@ _git = [ }, }, { + "name": "skia_user_config", + "path": "tools/base/dynamic-layout-inspector/external/skia-user-config", + }, + { "name": "libpng_repo", "build_file": "tools/base/dynamic-layout-inspector/external/libpng.BUILD", "path": "external/libpng", diff --git a/bazel/src/com/android/tools/bazel/IrToBazel.java b/bazel/src/com/android/tools/bazel/IrToBazel.java index 0be726368e..fe5090d851 100644 --- a/bazel/src/com/android/tools/bazel/IrToBazel.java +++ b/bazel/src/com/android/tools/bazel/IrToBazel.java @@ -169,9 +169,21 @@ public class IrToBazel { unmanagedEntry.getValue()); UnmanagedRule rule = unmanaged.get(newName); if (rule == null) { - rule = new UnmanagedRule( - bazel.findPackage("prebuilts/studio/intellij-sdk"), - newName); + if (newName.equals("studio-sdk-plugin-rust")) { + // Rust is not currently part of IntelliJ SDK so treat as a + // special case. + rule = + new UnmanagedRule( + bazel.findPackage( + "prebuilts/tools/common/rust-plugin"), + "rust-plugin"); + } else { + rule = + new UnmanagedRule( + bazel.findPackage( + "prebuilts/studio/intellij-sdk"), + newName); + } unmanaged.put(newName, rule); } imlModule.addDependency(rule, dependency.exported, scopes); diff --git a/bazel/studio_coverage.sh b/bazel/studio_coverage.sh index eb0787f4c5..b8efd1a9a4 100755 --- a/bazel/studio_coverage.sh +++ b/bazel/studio_coverage.sh @@ -103,18 +103,15 @@ fi --jobs=HOST_CPUS*.5 \ ${auth_options} \ -- \ - @cov//:comps.lcov_all \ - @cov//:comps.list_all \ + @cov//:all.lcov \ || exit $? -readonly lcov_path="./bazel-bin/external/cov/comps/lcov" -readonly comp_list_path="./bazel-bin/external/cov/comps/list" +readonly lcov_path="./bazel-bin/external/cov/all/lcov" if [[ -d "${dist_dir}" ]]; then # Copy the report to ab/ outputs mkdir "${dist_dir}/coverage" || exit $? cp -pv ${lcov_path} "${dist_dir}/coverage" || exit $? - cp -pv ${comp_list_path} "${dist_dir}/coverage" || exit $? fi collect_and_exit 0 diff --git a/build-system/BUILD b/build-system/BUILD index 6c4d73f8a8..e60a08f82e 100644 --- a/build-system/BUILD +++ b/build-system/BUILD @@ -271,8 +271,8 @@ filegroup( "manifest-merger/src/main/resources/**", ]) + [ "docs/build.gradle", - "manifest-merger/build.gradle", "manifest-merger/NOTICE", + "manifest-merger/build.gradle", ], visibility = ["//tools/base/build-system:__pkg__"], ) @@ -317,6 +317,24 @@ gradle_build( visibility = ["//visibility:public"], ) +gradle_build( + name = "kmp_prototype", + build_file = "//tools:agp_gradle_build_root_build_file", + data = [ + "//prebuilts/studio/jdk:jdk11", + "//tools/base/build-system/kmp-android-prototype:agp_gradle_build_files", + ] + ANDROID_GRADLE_PLUGIN_SOURCE_FILES, + gradle_properties = GRADLE_PROPERTIES, + output_file = "kmp_prototype.zip", + output_file_source = "dist/kmp_prototype.zip", + repos = [ + "//tools/base:agp_dependencies", + "//tools/base:agp_artifacts", + ], + tasks = [":base:build-system:kmp-android-prototype:zipKmpJar"], + visibility = ["//visibility:public"], +) + maven_repository( name = "android_gradle_plugin_runtime_dependencies", # keep sorted @@ -420,13 +438,13 @@ maven_repository( visibility = ["//visibility:public"], ) -# org.jetbrains.kotlin:kotlin-test-junit:1.5.3 +# org.jetbrains.kotlin:kotlin-test-junit:1.8.20-RC maven_repository( name = "android_gradle_plugin_gradle_api_test_repository", # keep sorted artifacts = [ "//tools/base/testutils:tools.testutils", - "@maven//:org.jetbrains.kotlin.kotlin-test-junit_1.7.10", + "@maven//:org.jetbrains.kotlin.kotlin-test-junit_1.8.20-RC2", ], ) @@ -533,6 +551,35 @@ gradle_test( visibility = ["//visibility:public"], ) +gradle_test( + name = "android_gradle_plugin_gradle_settings_api_metalava_test", + build_file = "//tools:agp_gradle_build_root_build_file", + # keep sorted + data = [ + ":agp_gradle_build_files", + "//prebuilts/studio/jdk:jdk11", + "//tools:agp_gradle_build_files", + "//tools/base/build-system/builder-model:agp_gradle_build_files", + "//tools/base/build-system/builder-test-api:agp_gradle_build_files", + "//tools/base/build-system/gradle-settings-api:agp_gradle_build_files", + "//tools/base/build-system/gradle-settings-api:agp_gradle_metalava_test_files", + "//tools/base/common:agp_gradle_build_files", + "//tools/buildSrc:agp_gradle_build_files", + "//tools/buildSrc/base:agp_gradle_build_files", + ], + gradle_properties = GRADLE_PROPERTIES, + # keep sorted + repos = [ + ":android_gradle_plugin_gradle_api_test_repository", + ":metalava_tool", + "//tools/base:agp_artifacts", + "//tools/base:agp_dependencies", + ], + tasks = [":base:build-system:gradle-settings-api:metalavaTest"], + test_output_dir = "build/base/build-system/gradle-settings-api/build/test-results/metalavaTest", + visibility = ["//visibility:public"], +) + # This should be kept in sync with # tools/base/testutils/src/main/java/com/android/testutils/TestUtils.ANDROID_PLATFORM_FOR_AGP_UNIT_TESTS filegroup( diff --git a/build-system/builder-model/src/main/java/com/android/builder/model/v2/models/Versions.kt b/build-system/builder-model/src/main/java/com/android/builder/model/v2/models/Versions.kt index 5aa043690b..debfb48c72 100644 --- a/build-system/builder-model/src/main/java/com/android/builder/model/v2/models/Versions.kt +++ b/build-system/builder-model/src/main/java/com/android/builder/model/v2/models/Versions.kt @@ -27,6 +27,13 @@ interface Versions: AndroidModel { interface Version { val major: Int val minor: Int + /** + * An optional, human-readable, representation of this version + * + * For example, minimum model consumer version 64.1 might correspond to + * Android Studio Giraffe patch 1. + */ + val humanReadable: String? } val versions: Map<String, Version> @@ -37,6 +44,15 @@ interface Versions: AndroidModel { const val ANDROID_DSL = "android_dsl" const val VARIANT_DEPENDENCIES = "variant_dependencies" const val NATIVE_MODULE = "native_module" + /** + * The minimum required model consumer version, to allow AGP to drop support for older versions + * of Android Studio. + * + * (Android Studio's model consumer version will be incremented after each release branching) + * + * If not present, a future version of AGP will not be considered compatible + */ + const val MINIMUM_MODEL_CONSUMER = "minimum_model_consumer" } /** diff --git a/build-system/builder-model/src/test/resources/com/android/builder/model/tooling-api-model-api.txt b/build-system/builder-model/src/test/resources/com/android/builder/model/tooling-api-model-api.txt index 3474f87b9d..ae750813dc 100644 --- a/build-system/builder-model/src/test/resources/com/android/builder/model/tooling-api-model-api.txt +++ b/build-system/builder-model/src/test/resources/com/android/builder/model/tooling-api-model-api.txt @@ -4,7 +4,7 @@ ATTENTION REVIEWER: If this needs to be changed, please make sure changes below are backwards compatible. ------------------------------------------------------------------------- Sha256 of below classes: -4eb1cd2430dbd55ef27047768f4e89011466207c49290cd83f242bd70ef1095c +aca20f34d5d7628a7015fb9638d2914e5683460d3d1506e09dc3aba9754bab86 ------------------------------------------------------------------------- com.android.builder.model.AaptOptions com.android.builder.model.AaptOptions$Namespacing extends java.lang.Enum @@ -833,6 +833,7 @@ com.android.builder.model.v2.models.VariantDependencies.getUnitTestArtifact: com com.android.builder.model.v2.models.Versions implements com.android.builder.model.v2.AndroidModel com.android.builder.model.v2.models.Versions$Companion com.android.builder.model.v2.models.Versions$Version +com.android.builder.model.v2.models.Versions$Version.getHumanReadable: java.lang.String () com.android.builder.model.v2.models.Versions$Version.getMajor: int () com.android.builder.model.v2.models.Versions$Version.getMinor: int () com.android.builder.model.v2.models.Versions.getAgp: java.lang.String () diff --git a/build-system/builder/src/main/java/com/android/builder/core/ComponentType.kt b/build-system/builder/src/main/java/com/android/builder/core/ComponentType.kt index 08e8e696f0..9d721b95c0 100644 --- a/build-system/builder/src/main/java/com/android/builder/core/ComponentType.kt +++ b/build-system/builder/src/main/java/com/android/builder/core/ComponentType.kt @@ -142,6 +142,8 @@ interface ComponentType { const val UNIT_TEST_SUFFIX = "UnitTest" const val TEST_FIXTURES_PREFIX = "testFixtures" const val TEST_FIXTURES_SUFFIX = "TestFixtures" + const val SCREENSHOT_TEST_PREFIX = "screenshotTest" + const val SCREENSHOT_TEST_SUFFIX = "ScreenshotTest" val testComponents: ImmutableList<ComponentType> get() { diff --git a/build-system/builder/src/main/java/com/android/builder/dexing/D8DexArchiveBuilder.java b/build-system/builder/src/main/java/com/android/builder/dexing/D8DexArchiveBuilder.java index a4d4596603..0cfe3121fa 100644 --- a/build-system/builder/src/main/java/com/android/builder/dexing/D8DexArchiveBuilder.java +++ b/build-system/builder/src/main/java/com/android/builder/dexing/D8DexArchiveBuilder.java @@ -87,7 +87,7 @@ final class D8DexArchiveBuilder extends DexArchiveBuilder { (dexParams.getDexPerClass() ? DexFilePerClassFile.INSTANCE : DexIndexed.INSTANCE) - .getR8OutputMode()) + .getOutputMode()) .setIncludeClassesChecksum(dexParams.getDebuggable()); if (dexParams.getDebuggable()) { diff --git a/build-system/builder/src/main/java/com/android/builder/dexing/D8GlobalSyntheticsConsumer.kt b/build-system/builder/src/main/java/com/android/builder/dexing/D8GlobalSyntheticsConsumer.kt index 7210f5048e..7fdfbaf078 100644 --- a/build-system/builder/src/main/java/com/android/builder/dexing/D8GlobalSyntheticsConsumer.kt +++ b/build-system/builder/src/main/java/com/android/builder/dexing/D8GlobalSyntheticsConsumer.kt @@ -43,7 +43,8 @@ class D8GlobalSyntheticsConsumer(val globalSyntheticsOutput: Path) : GlobalSynth globalSyntheticsOutput.resolve( // context.binaryName + .class is guaranteed to be the same as classFileRelativePath DexFilePerClassFile - .getGlobalOutputRelativePathOfClassFile(context.binaryName + ".class")) + .getGlobalSyntheticOutputRelativePath(context.binaryName + ".class") + ) } else { // when context doesn't exist, globals are output to a single file under // globalSyntheticsOutput directory diff --git a/build-system/builder/src/main/java/com/android/builder/dexing/DexOutputMode.kt b/build-system/builder/src/main/java/com/android/builder/dexing/DexOutputMode.kt index be017c58b9..de5aa4a2ac 100644 --- a/build-system/builder/src/main/java/com/android/builder/dexing/DexOutputMode.kt +++ b/build-system/builder/src/main/java/com/android/builder/dexing/DexOutputMode.kt @@ -20,63 +20,60 @@ import com.android.SdkConstants import com.android.tools.r8.OutputMode import java.io.File -/** - * Output mode for dexing. - * - * Each mode should map to [com.android.tools.r8.OutputMode]. It may also provide additional - * information (e.g., [DexFilePerClassFile.getDexOutputRelativePathsOfClassFile] is needed for - * incremental dexing). - */ +/** Output mode for dexing. */ interface DexOutputMode { - val r8OutputMode: OutputMode + val outputMode: OutputMode } +/** + * Given a class file, [OutputMode.DexFilePerClassFile] will produce 1 dex file + 1 additional + * global synthetic file if necessary. + * + * For example, given `com/example/InterfaceWithDefaultMethod.class`, it will produce + * - `com/example/InterfaceWithDefaultMethod.dex` (this + * dex file contains the `com/example/InterfaceWithDefaultMethod` class and possibly the synthetic + * `com/example/InterfaceWithDefaultMethod$-CC` class if desugaring requires it) + * - 1 additional global synthetic file if necessary + * + * Note that for incremental dexing purposes, [OutputMode.DexFilePerClassFile] is better than + * [OutputMode.DexFilePerClass] because in the above example the latter may produce 2 separate dex + * files `com/example/InterfaceWithDefaultMethod.dex` and + * `com/example/InterfaceWithDefaultMethod$-CC.dex` given 1 class file. + */ object DexFilePerClassFile : DexOutputMode { - override val r8OutputMode + override val outputMode get() = OutputMode.DexFilePerClassFile /** - * Returns the Unix-style relative paths of all the possible dex outputs under the dex output - * directory or jar when D8 processes the class file with the given relative path. + * Returns the Unix-style relative path of the *dex* output file under the output directory or + * jar after D8 processes the class file with the given relative path. * * (If the given relative path is not in Unix style, it will be converted to that first.) */ - fun getDexOutputRelativePathsOfClassFile(classFileRelativePath: String): Set<String> { - // Given a class file, `OutputMode.DexFilePerClassFile` will produce 1 dex file + additional - // synthetic files if necessary. - // For example, given the following class files: - // - com/example/NormalClass.class - // - com/example/NormalClass$InnerClass.class - // - com/example/InterfaceWithDefaultMethod.class - // `OutputMode.DexFilePerClassFile` will produce the following output files: - // - com/example/NormalClass.dex - // - com/example/NormalClass$InnerClass.dex - // - com/example/InterfaceWithDefaultMethod.dex (this dex file contains the - // `com/example/InterfaceWithDefaultMethod` class and possibly the synthetic - // `com/example/InterfaceWithDefaultMethod$-CC` class if desugaring requires it) - // - Additional synthetic files if necessary - // Note that `OutputMode.DexFilePerClass` (`*PerClass`, not `*PerClassFile`) will produce 2 - // separate dex files for `com/example/InterfaceWithDefaultMethod` and - // `com/example/InterfaceWithDefaultMethod$-CC`. That's why it's simpler to use - // `OutputMode.DexFilePerClassFile`. - return setOf( - // There is currently 1 output file / class file, but there may be more in the future. - ClassFileEntry.withDexExtension(File(classFileRelativePath).invariantSeparatorsPath) - ) + fun getDexOutputRelativePath(classFileRelativePath: String): String { + check(classFileRelativePath.endsWith(SdkConstants.DOT_CLASS)) { + "Expected .class file but found: $classFileRelativePath" + } + return File(classFileRelativePath).invariantSeparatorsPath.removeSuffix(SdkConstants.DOT_CLASS) + SdkConstants.DOT_DEX } /** - * Returns the global synthetics output relative path of a class file. + * Returns the Unix-style relative path of the *global synthetic* output file under the output + * directory or jar after D8 processes the class file with the given relative path. + * + * (If the given relative path is not in Unix style, it will be converted to that first.) */ - fun getGlobalOutputRelativePathOfClassFile(classFileRelativePath: String): String { - return classFileRelativePath.substring( - 0, classFileRelativePath.length - SdkConstants.DOT_CLASS.length) + globalSyntheticsFileExtension + fun getGlobalSyntheticOutputRelativePath(classFileRelativePath: String): String { + check(classFileRelativePath.endsWith(SdkConstants.DOT_CLASS)) { + "Expected .class file but found: $classFileRelativePath" + } + return File(classFileRelativePath).invariantSeparatorsPath.removeSuffix(SdkConstants.DOT_CLASS) + globalSyntheticsFileExtension } } object DexIndexed : DexOutputMode { - override val r8OutputMode + override val outputMode get() = OutputMode.DexIndexed } diff --git a/build-system/builder/src/main/java/com/android/builder/dexing/DexUtils.kt b/build-system/builder/src/main/java/com/android/builder/dexing/DexUtils.kt index aa26e6189b..2edc88f52d 100644 --- a/build-system/builder/src/main/java/com/android/builder/dexing/DexUtils.kt +++ b/build-system/builder/src/main/java/com/android/builder/dexing/DexUtils.kt @@ -29,7 +29,7 @@ import kotlin.streams.toList /** * Returns `true` if the given file's extension is `.jar`, ignoring case. It may or may not exist. */ -val isJarFile: (File) -> Boolean = { it.extension.equals(SdkConstants.EXT_JAR, ignoreCase = true) } +val isJarFile: (File) -> Boolean = { it.path.endsWith(SdkConstants.DOT_JAR, ignoreCase = true) } /** * Returns a sorted list of files in the given directory whose relative paths satisfy the given diff --git a/build-system/builder/src/main/java/com/android/builder/dexing/MutableDependencyGraph.kt b/build-system/builder/src/main/java/com/android/builder/dexing/MutableDependencyGraph.kt index 7081d95d0d..61bec3e169 100644 --- a/build-system/builder/src/main/java/com/android/builder/dexing/MutableDependencyGraph.kt +++ b/build-system/builder/src/main/java/com/android/builder/dexing/MutableDependencyGraph.kt @@ -65,21 +65,21 @@ class MutableDependencyGraph<T> : DependencyGraphUpdater<T>, Serializable { * * Any nodes in the given set that do not exist are ignored. */ - fun getAllDependents(nodes: Set<T>): Set<T> { - val visitedSet: MutableSet<T> = mutableSetOf() - val toVisitSet: MutableSet<T> = nodes.toMutableSet() + fun getAllDependents(nodes: Collection<T>): Set<T> { + // Standard Breadth-First Search + val visitedNodes = nodes.toMutableSet() + val queue = ArrayDeque(nodes) - while (toVisitSet.isNotEmpty()) { - val toVisitNextSet = mutableSetOf<T>() - for (toVisitNode in toVisitSet) { - dependentsMap[toVisitNode]?.let { toVisitNextSet.addAll(it) } + while (queue.isNotEmpty()) { + val node = queue.removeFirst() + dependentsMap[node]?.forEach { + if (it !in visitedNodes) { + visitedNodes.add(it) + queue.add(it) + } } - visitedSet.addAll(toVisitSet) - toVisitSet.clear() - toVisitSet.addAll(toVisitNextSet - visitedSet) } - - return visitedSet - nodes + return visitedNodes - nodes.toSet() } companion object { @@ -96,4 +96,4 @@ interface DependencyGraphUpdater<T> { * If any of the given nodes does not yet exist, it will be added. */ fun addEdge(dependent: T, dependency: T) -}
\ No newline at end of file +} diff --git a/build-system/builder/src/main/java/com/android/builder/dexing/r8Tool.kt b/build-system/builder/src/main/java/com/android/builder/dexing/r8Tool.kt index 061c093283..2b50622eee 100644 --- a/build-system/builder/src/main/java/com/android/builder/dexing/r8Tool.kt +++ b/build-system/builder/src/main/java/com/android/builder/dexing/r8Tool.kt @@ -65,6 +65,7 @@ import java.util.logging.Level import java.util.logging.Logger import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream +import kotlin.io.path.exists fun isProguardRule(name: String): Boolean { val lowerCaseName = name.toLowerCase(Locale.US) @@ -310,8 +311,10 @@ fun runR8( } } // handle art-profile rewriting if enabled - if (outputArtProfile != null) { - wireArtProfileRewriting(r8CommandBuilder, inputArtProfile, outputArtProfile) + inputArtProfile?.let {input -> + if (input.exists() && outputArtProfile != null) { + wireArtProfileRewriting(r8CommandBuilder, input, outputArtProfile) + } } if (enableMinimalStartupOptimization) { check(inputProfileForDexStartupOptimization != null) { diff --git a/build-system/gradle-api/api/current.txt b/build-system/gradle-api/api/current.txt index cd33b45cbb..e51a2db32c 100644 --- a/build-system/gradle-api/api/current.txt +++ b/build-system/gradle-api/api/current.txt @@ -1398,9 +1398,11 @@ package com.android.build.api.dsl { method public org.gradle.api.ExtensiblePolymorphicDomainObjectContainer<com.android.build.api.dsl.Device> getAllDevices(); method public org.gradle.api.ExtensiblePolymorphicDomainObjectContainer<com.android.build.api.dsl.Device> getDevices(); method public org.gradle.api.NamedDomainObjectContainer<com.android.build.api.dsl.DeviceGroup> getGroups(); + method @org.gradle.api.Incubating public org.gradle.api.NamedDomainObjectContainer<com.android.build.api.dsl.ManagedVirtualDevice> getLocalDevices(); property public abstract org.gradle.api.ExtensiblePolymorphicDomainObjectContainer<com.android.build.api.dsl.Device> allDevices; property public abstract org.gradle.api.ExtensiblePolymorphicDomainObjectContainer<com.android.build.api.dsl.Device> devices; property public abstract org.gradle.api.NamedDomainObjectContainer<com.android.build.api.dsl.DeviceGroup> groups; + property @org.gradle.api.Incubating public abstract org.gradle.api.NamedDomainObjectContainer<com.android.build.api.dsl.ManagedVirtualDevice> localDevices; } @org.gradle.api.Incubating public interface ManagedVirtualDevice extends com.android.build.api.dsl.Device { @@ -1627,10 +1629,12 @@ package com.android.build.api.dsl { public interface SdkComponents { method public org.gradle.api.provider.Provider<org.gradle.api.file.RegularFile> getAdb(); + method @org.gradle.api.Incubating public org.gradle.api.provider.Provider<com.android.build.api.variant.Aidl> getAidl(); method public org.gradle.api.provider.Provider<java.util.List<org.gradle.api.file.RegularFile>> getBootClasspath(); method public org.gradle.api.provider.Provider<org.gradle.api.file.Directory> getNdkDirectory(); method public org.gradle.api.provider.Provider<org.gradle.api.file.Directory> getSdkDirectory(); property public abstract org.gradle.api.provider.Provider<org.gradle.api.file.RegularFile> adb; + property @org.gradle.api.Incubating public abstract org.gradle.api.provider.Provider<com.android.build.api.variant.Aidl> aidl; property public abstract org.gradle.api.provider.Provider<java.util.List<org.gradle.api.file.RegularFile>> bootClasspath; property public abstract org.gradle.api.provider.Provider<org.gradle.api.file.Directory> ndkDirectory; property public abstract org.gradle.api.provider.Provider<org.gradle.api.file.Directory> sdkDirectory; @@ -2067,19 +2071,28 @@ package com.android.build.api.variant { property @org.gradle.api.Incubating public abstract org.gradle.api.provider.Property<java.lang.Integer> minCompileSdkExtension; } + @org.gradle.api.Incubating public interface Aidl { + method @org.gradle.api.tasks.Internal public org.gradle.api.provider.Provider<org.gradle.api.file.RegularFile> getExecutable(); + method @org.gradle.api.tasks.InputFile @org.gradle.api.tasks.PathSensitive(org.gradle.api.tasks.PathSensitivity.NAME_ONLY) public org.gradle.api.provider.Provider<org.gradle.api.file.RegularFile> getFramework(); + method @org.gradle.api.tasks.Input public org.gradle.api.provider.Provider<java.lang.String> getVersion(); + property @org.gradle.api.tasks.Internal public abstract org.gradle.api.provider.Provider<org.gradle.api.file.RegularFile> executable; + property @org.gradle.api.tasks.InputFile @org.gradle.api.tasks.PathSensitive(org.gradle.api.tasks.PathSensitivity.NAME_ONLY) public abstract org.gradle.api.provider.Provider<org.gradle.api.file.RegularFile> framework; + property @org.gradle.api.tasks.Input public abstract org.gradle.api.provider.Provider<java.lang.String> version; + } + public interface AndroidComponentsExtension<DslExtensionT extends com.android.build.api.dsl.CommonExtension<?, ?, ?, ?, ?>, VariantBuilderT extends com.android.build.api.variant.VariantBuilder, VariantT extends com.android.build.api.variant.Variant> extends com.android.build.api.variant.DslLifecycle<DslExtensionT> { method public void beforeVariants(optional com.android.build.api.variant.VariantSelector selector, kotlin.jvm.functions.Function1<? super VariantBuilderT,kotlin.Unit> callback); method public void beforeVariants(optional com.android.build.api.variant.VariantSelector selector, org.gradle.api.Action<VariantBuilderT> callback); method @Deprecated public void finalizeDSl(org.gradle.api.Action<DslExtensionT> callback); method public com.android.build.api.AndroidPluginVersion getPluginVersion(); - method @org.gradle.api.Incubating public com.android.build.api.dsl.SdkComponents getSdkComponents(); + method public com.android.build.api.dsl.SdkComponents getSdkComponents(); method public void onVariants(optional com.android.build.api.variant.VariantSelector selector, kotlin.jvm.functions.Function1<? super VariantT,kotlin.Unit> callback); method public void onVariants(optional com.android.build.api.variant.VariantSelector selector, org.gradle.api.Action<VariantT> callback); method @org.gradle.api.Incubating public void registerExtension(com.android.build.api.variant.DslExtension dslExtension, kotlin.jvm.functions.Function1<? super com.android.build.api.variant.VariantExtensionConfig<VariantT>,? extends com.android.build.api.variant.VariantExtension> configurator); method @org.gradle.api.Incubating public void registerSourceType(String name); method public com.android.build.api.variant.VariantSelector selector(); property public abstract com.android.build.api.AndroidPluginVersion pluginVersion; - property @org.gradle.api.Incubating public abstract com.android.build.api.dsl.SdkComponents sdkComponents; + property public abstract com.android.build.api.dsl.SdkComponents sdkComponents; } public interface AndroidResources { @@ -2128,7 +2141,7 @@ package com.android.build.api.variant { public interface ApplicationAndroidComponentsExtension extends com.android.build.api.variant.AndroidComponentsExtension<com.android.build.api.dsl.ApplicationExtension,com.android.build.api.variant.ApplicationVariantBuilder,com.android.build.api.variant.ApplicationVariant> { } - public interface ApplicationVariant extends com.android.build.api.variant.GeneratesApk com.android.build.api.variant.CanMinifyAndroidResources com.android.build.api.variant.CanMinifyCode com.android.build.api.variant.HasAndroidTest com.android.build.api.variant.HasTestFixtures com.android.build.api.variant.Variant { + public interface ApplicationVariant extends com.android.build.api.variant.GeneratesApk com.android.build.api.variant.CanMinifyAndroidResources com.android.build.api.variant.CanMinifyCode com.android.build.api.variant.HasAndroidTest com.android.build.api.variant.HasTestFixtures com.android.build.api.variant.HasUnitTest com.android.build.api.variant.Variant { method public org.gradle.api.provider.Property<java.lang.String> getApplicationId(); method @org.gradle.api.Incubating public com.android.build.api.variant.BundleConfig getBundleConfig(); method public com.android.build.api.variant.DependenciesInfo getDependenciesInfo(); @@ -2141,7 +2154,7 @@ package com.android.build.api.variant { property public abstract com.android.build.api.variant.SigningConfig signingConfig; } - public interface ApplicationVariantBuilder extends com.android.build.api.variant.VariantBuilder com.android.build.api.variant.CanMinifyAndroidResourcesBuilder com.android.build.api.variant.CanMinifyCodeBuilder com.android.build.api.variant.GeneratesApkBuilder com.android.build.api.variant.HasAndroidTestBuilder com.android.build.api.variant.HasTestFixturesBuilder { + public interface ApplicationVariantBuilder extends com.android.build.api.variant.VariantBuilder com.android.build.api.variant.CanMinifyAndroidResourcesBuilder com.android.build.api.variant.CanMinifyCodeBuilder com.android.build.api.variant.GeneratesApkBuilder com.android.build.api.variant.HasAndroidTestBuilder com.android.build.api.variant.HasTestFixturesBuilder com.android.build.api.variant.HasUnitTestBuilder { method public boolean getDebuggable(); method public com.android.build.api.variant.DependenciesInfoBuilder getDependenciesInfo(); property public abstract boolean debuggable; @@ -2228,26 +2241,26 @@ package com.android.build.api.variant { } public interface Component extends com.android.build.api.variant.ComponentIdentity { - method @org.gradle.api.Incubating public org.gradle.api.artifacts.Configuration getAnnotationProcessorConfiguration(); + method public org.gradle.api.artifacts.Configuration getAnnotationProcessorConfiguration(); method public com.android.build.api.artifact.Artifacts getArtifacts(); method @org.gradle.api.Incubating public org.gradle.api.file.FileCollection getCompileClasspath(); - method @org.gradle.api.Incubating public org.gradle.api.artifacts.Configuration getCompileConfiguration(); + method public org.gradle.api.artifacts.Configuration getCompileConfiguration(); method public com.android.build.api.variant.Instrumentation getInstrumentation(); method @org.gradle.api.Incubating public com.android.build.api.variant.JavaCompilation getJavaCompilation(); method public org.gradle.api.provider.Provider<java.lang.String> getNamespace(); - method @org.gradle.api.Incubating public org.gradle.api.artifacts.Configuration getRuntimeConfiguration(); - method @org.gradle.api.Incubating public com.android.build.api.variant.Sources getSources(); + method public org.gradle.api.artifacts.Configuration getRuntimeConfiguration(); + method public com.android.build.api.variant.Sources getSources(); method @Deprecated public void setAsmFramesComputationMode(com.android.build.api.instrumentation.FramesComputationMode mode); method @Deprecated public <ParamT extends com.android.build.api.instrumentation.InstrumentationParameters> void transformClassesWith(Class<? extends com.android.build.api.instrumentation.AsmClassVisitorFactory<ParamT>> classVisitorFactoryImplClass, com.android.build.api.instrumentation.InstrumentationScope scope, kotlin.jvm.functions.Function1<? super ParamT,kotlin.Unit> instrumentationParamsConfig); - property @org.gradle.api.Incubating public abstract org.gradle.api.artifacts.Configuration annotationProcessorConfiguration; + property public abstract org.gradle.api.artifacts.Configuration annotationProcessorConfiguration; property public abstract com.android.build.api.artifact.Artifacts artifacts; property @org.gradle.api.Incubating public abstract org.gradle.api.file.FileCollection compileClasspath; - property @org.gradle.api.Incubating public abstract org.gradle.api.artifacts.Configuration compileConfiguration; + property public abstract org.gradle.api.artifacts.Configuration compileConfiguration; property public abstract com.android.build.api.variant.Instrumentation instrumentation; property @org.gradle.api.Incubating public abstract com.android.build.api.variant.JavaCompilation javaCompilation; property public abstract org.gradle.api.provider.Provider<java.lang.String> namespace; - property @org.gradle.api.Incubating public abstract org.gradle.api.artifacts.Configuration runtimeConfiguration; - property @org.gradle.api.Incubating public abstract com.android.build.api.variant.Sources sources; + property public abstract org.gradle.api.artifacts.Configuration runtimeConfiguration; + property public abstract com.android.build.api.variant.Sources sources; } public interface ComponentBuilder extends com.android.build.api.variant.ComponentIdentity { @@ -2278,12 +2291,18 @@ package com.android.build.api.variant { } public interface DependenciesInfoBuilder { - method public boolean getIncludedInApk(); - method public boolean getIncludedInBundle(); - method public void setIncludedInApk(boolean includedInApk); - method public void setIncludedInBundle(boolean includedInBundle); - property public abstract boolean includedInApk; - property public abstract boolean includedInBundle; + method public boolean getIncludeInApk(); + method public boolean getIncludeInBundle(); + method @Deprecated public boolean getIncludedInApk(); + method @Deprecated public boolean getIncludedInBundle(); + method public void setIncludeInApk(boolean includeInApk); + method public void setIncludeInBundle(boolean includeInBundle); + method @Deprecated public void setIncludedInApk(boolean includedInApk); + method @Deprecated public void setIncludedInBundle(boolean includedInBundle); + property public abstract boolean includeInApk; + property public abstract boolean includeInBundle; + property @Deprecated public abstract boolean includedInApk; + property @Deprecated public abstract boolean includedInBundle; } public interface DexPackagingOptions { @@ -2318,10 +2337,10 @@ package com.android.build.api.variant { public interface DynamicFeatureAndroidComponentsExtension extends com.android.build.api.variant.AndroidComponentsExtension<com.android.build.api.dsl.DynamicFeatureExtension,com.android.build.api.variant.DynamicFeatureVariantBuilder,com.android.build.api.variant.DynamicFeatureVariant> { } - public interface DynamicFeatureVariant extends com.android.build.api.variant.Variant com.android.build.api.variant.GeneratesApk com.android.build.api.variant.HasAndroidTest com.android.build.api.variant.HasTestFixtures { + public interface DynamicFeatureVariant extends com.android.build.api.variant.Variant com.android.build.api.variant.GeneratesApk com.android.build.api.variant.HasAndroidTest com.android.build.api.variant.HasTestFixtures com.android.build.api.variant.HasUnitTest { } - public interface DynamicFeatureVariantBuilder extends com.android.build.api.variant.VariantBuilder com.android.build.api.variant.GeneratesApkBuilder com.android.build.api.variant.HasAndroidTestBuilder com.android.build.api.variant.HasTestFixturesBuilder { + public interface DynamicFeatureVariantBuilder extends com.android.build.api.variant.VariantBuilder com.android.build.api.variant.GeneratesApkBuilder com.android.build.api.variant.HasAndroidTestBuilder com.android.build.api.variant.HasTestFixturesBuilder com.android.build.api.variant.HasUnitTestBuilder { } public interface ExternalNativeBuild { @@ -2426,6 +2445,17 @@ package com.android.build.api.variant { property public abstract boolean enableTestFixtures; } + public interface HasUnitTest { + method public com.android.build.api.variant.UnitTest? getUnitTest(); + property public abstract com.android.build.api.variant.UnitTest? unitTest; + } + + public interface HasUnitTestBuilder { + method public boolean getEnableUnitTest(); + method public void setEnableUnitTest(boolean enableUnitTest); + property public abstract boolean enableUnitTest; + } + public interface Instrumentation { method public org.gradle.api.provider.SetProperty<java.lang.String> getExcludes(); method public void setAsmFramesComputationMode(com.android.build.api.instrumentation.FramesComputationMode mode); @@ -2457,12 +2487,12 @@ package com.android.build.api.variant { public interface LibraryAndroidComponentsExtension extends com.android.build.api.variant.AndroidComponentsExtension<com.android.build.api.dsl.LibraryExtension,com.android.build.api.variant.LibraryVariantBuilder,com.android.build.api.variant.LibraryVariant> { } - public interface LibraryVariant extends com.android.build.api.variant.Variant com.android.build.api.variant.CanMinifyCode com.android.build.api.variant.GeneratesAar com.android.build.api.variant.HasAndroidTest com.android.build.api.variant.HasTestFixtures { + public interface LibraryVariant extends com.android.build.api.variant.Variant com.android.build.api.variant.CanMinifyCode com.android.build.api.variant.GeneratesAar com.android.build.api.variant.HasAndroidTest com.android.build.api.variant.HasTestFixtures com.android.build.api.variant.HasUnitTest { method public com.android.build.api.variant.Renderscript? getRenderscript(); property public abstract com.android.build.api.variant.Renderscript? renderscript; } - public interface LibraryVariantBuilder extends com.android.build.api.variant.VariantBuilder com.android.build.api.variant.CanMinifyCodeBuilder com.android.build.api.variant.HasAndroidTestBuilder com.android.build.api.variant.HasTestFixturesBuilder { + public interface LibraryVariantBuilder extends com.android.build.api.variant.VariantBuilder com.android.build.api.variant.CanMinifyCodeBuilder com.android.build.api.variant.HasAndroidTestBuilder com.android.build.api.variant.HasTestFixturesBuilder com.android.build.api.variant.HasUnitTestBuilder { } @org.gradle.api.Incubating public interface LintLifecycleExtension extends com.android.build.api.variant.DslLifecycle<com.android.build.api.dsl.Lint> { @@ -2618,7 +2648,7 @@ package com.android.build.api.variant { method public com.android.build.api.variant.Packaging getPackaging(); method public org.gradle.api.provider.ListProperty<org.gradle.api.file.RegularFile> getProguardFiles(); method @Deprecated public com.android.build.api.variant.AndroidVersion getTargetSdkVersion(); - method public com.android.build.api.component.UnitTest? getUnitTest(); + method @Deprecated public com.android.build.api.component.UnitTest? getUnitTest(); property public abstract org.gradle.api.provider.MapProperty<java.lang.String,com.android.build.api.variant.BuildConfigField<? extends java.io.Serializable>> buildConfigFields; property @org.gradle.api.Incubating public abstract java.util.List<com.android.build.api.variant.Component> components; property @org.gradle.api.Incubating public abstract org.gradle.api.provider.MapProperty<java.lang.String,java.lang.Object> experimentalProperties; @@ -2632,11 +2662,11 @@ package com.android.build.api.variant { property public abstract com.android.build.api.variant.Packaging packaging; property public abstract org.gradle.api.provider.ListProperty<org.gradle.api.file.RegularFile> proguardFiles; property @Deprecated public abstract com.android.build.api.variant.AndroidVersion targetSdkVersion; - property public abstract com.android.build.api.component.UnitTest? unitTest; + property @Deprecated public abstract com.android.build.api.component.UnitTest? unitTest; } public interface VariantBuilder extends com.android.build.api.variant.ComponentBuilder { - method public boolean getEnableUnitTest(); + method @Deprecated public boolean getEnableUnitTest(); method public Integer? getMaxSdk(); method public Integer? getMinSdk(); method public String? getMinSdkPreview(); @@ -2645,7 +2675,7 @@ package com.android.build.api.variant { method @Deprecated public String? getTargetSdkPreview(); method @Deprecated public boolean getUnitTestEnabled(); method public <T> void registerExtension(Class<? extends T> type, T instance); - method public void setEnableUnitTest(boolean enableUnitTest); + method @Deprecated public void setEnableUnitTest(boolean enableUnitTest); method public void setMaxSdk(Integer? maxSdk); method public void setMinSdk(Integer? minSdk); method public void setMinSdkPreview(String? minSdkPreview); @@ -2653,7 +2683,7 @@ package com.android.build.api.variant { method @Deprecated public void setTargetSdk(Integer? targetSdk); method @Deprecated public void setTargetSdkPreview(String? targetSdkPreview); method @Deprecated public void setUnitTestEnabled(boolean unitTestEnabled); - property public abstract boolean enableUnitTest; + property @Deprecated public abstract boolean enableUnitTest; property public abstract Integer? maxSdk; property public abstract Integer? minSdk; property public abstract String? minSdkPreview; @@ -2724,6 +2754,7 @@ package com.android.build.api.variant { method public com.android.build.api.variant.VariantSelector all(); method public com.android.build.api.variant.VariantSelector withBuildType(String buildType); method public com.android.build.api.variant.VariantSelector withFlavor(kotlin.Pair<java.lang.String,java.lang.String> flavorToDimension); + method public com.android.build.api.variant.VariantSelector withFlavor(String dimension, String flavorName); method public com.android.build.api.variant.VariantSelector withName(java.util.regex.Pattern pattern); method public com.android.build.api.variant.VariantSelector withName(String name); } diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/dsl/ManagedDevices.kt b/build-system/gradle-api/src/main/java/com/android/build/api/dsl/ManagedDevices.kt index 4f0112f16e..51558d7247 100644 --- a/build-system/gradle-api/src/main/java/com/android/build/api/dsl/ManagedDevices.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/dsl/ManagedDevices.kt @@ -17,6 +17,7 @@ package com.android.build.api.dsl import org.gradle.api.ExtensiblePolymorphicDomainObjectContainer +import org.gradle.api.Incubating import org.gradle.api.NamedDomainObjectContainer /** Options for Managed Devices */ @@ -37,6 +38,15 @@ interface ManagedDevices { val devices: ExtensiblePolymorphicDomainObjectContainer<Device> /** + * Convenience container for specifying managed devices of type [ManagedVirtualDevice]. + * + * This list is managed in sync with [allDevices]. [ManagedVirtualDevice] definitions added or + * removed in this container are correspondingly handled in [allDevices], and vice versa. + */ + @get: Incubating + val localDevices: NamedDomainObjectContainer<ManagedVirtualDevice> + + /** * List of DeviceGroups to create tasks for. * * These APIs are experimental and may change without notice. diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/dsl/SdkComponents.kt b/build-system/gradle-api/src/main/java/com/android/build/api/dsl/SdkComponents.kt index c8ca521458..4719742b4e 100644 --- a/build-system/gradle-api/src/main/java/com/android/build/api/dsl/SdkComponents.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/dsl/SdkComponents.kt @@ -16,6 +16,8 @@ package com.android.build.api.dsl +import com.android.build.api.variant.Aidl +import org.gradle.api.Incubating import org.gradle.api.file.Directory import org.gradle.api.file.RegularFile import org.gradle.api.provider.Provider @@ -53,4 +55,13 @@ interface SdkComponents { * a [org.gradle.api.Task] input to do so. */ val bootClasspath: Provider<List<RegularFile>> + + /** + * Provides access to aidl tools + * + * The returned [Provider] can be used by tasks requiring aidl tools as input + * with [org.gradle.api.tasks.Nested] + */ + @get:Incubating + val aidl: Provider<Aidl> } diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/Aidl.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/Aidl.kt new file mode 100644 index 0000000000..d981dc75e1 --- /dev/null +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/Aidl.kt @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2023 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.build.api.variant + +import org.gradle.api.Incubating +import org.gradle.api.file.RegularFile +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity + +/** + * Provides structured access to various AIDL tools such as + * the aidl compiler executable and aidl framework. + * + * An instance of [Aidl] can be obtained via [AndroidComponentsExtension.sdkComponents] + * + * As an example , let's take a [Task] that runs aidl compiler: + * + * ```kotlin + * abstract class MyTask: DefaultTask() { + * @get:Nested + * abstract val aidlInput: Property<com.android.build.api.variant.Aidl> + * + * @get:Inject + * abstract val execOperations: ExecOperations + * + * @TaskAction + * fun execute() { + * val aidlExecutable = aidlInput.get().executable.get().asFile + * val aidlFramework = aidlInput.get().framework.get().asFile + * + * // execute aidl binary with --help argument + * execOperations.exec { spec -> + * spec.commandLine(aidlExecutable) + * spec.args("--help") + * } + * } + * } + * + * tasks.register<MyTask>("myTaskName") { + * // get an instance of Aidl + * this.aidlInput.set(androidComponents.sdkComponents.aidl) + * } + * ``` + */ +@Incubating +interface Aidl { + + /** + * Path to the [AIDL](https://developer.android.com/guide/components/aidl) + * executable file from the Android SDK + */ + @get:Internal + val executable: Provider<RegularFile> + + /** + * Path to the [AIDL](https://developer.android.com/guide/components/aidl) + * framework file from the Android SDK + */ + @get:PathSensitive(PathSensitivity.NAME_ONLY) + @get:InputFile + val framework: Provider<RegularFile> + + /** + * Version of build tools. + * It is used as an input to allow correct build cache behaviour across different platforms + */ + @get:Input + val version: Provider<String> +} + diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/AndroidComponentsExtension.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/AndroidComponentsExtension.kt index d1ca1d03fa..7f3df79ab0 100644 --- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/AndroidComponentsExtension.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/AndroidComponentsExtension.kt @@ -55,7 +55,6 @@ interface AndroidComponentsExtension< * * @return [SdkComponents] to access Android SDK used by Gradle. */ - @get:Incubating val sdkComponents: SdkComponents /** diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/ApplicationVariant.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/ApplicationVariant.kt index 000ab6f257..a4f0c75fd3 100644 --- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/ApplicationVariant.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/ApplicationVariant.kt @@ -25,6 +25,7 @@ import org.gradle.api.provider.Property interface ApplicationVariant : GeneratesApk, Variant, HasAndroidTest, + HasUnitTest, HasTestFixtures, CanMinifyCode, CanMinifyAndroidResources { diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/ApplicationVariantBuilder.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/ApplicationVariantBuilder.kt index fa8ec6a6e8..efe57f8d13 100644 --- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/ApplicationVariantBuilder.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/ApplicationVariantBuilder.kt @@ -28,6 +28,7 @@ package com.android.build.api.variant */ interface ApplicationVariantBuilder : VariantBuilder, HasAndroidTestBuilder, + HasUnitTestBuilder, HasTestFixturesBuilder, GeneratesApkBuilder, CanMinifyCodeBuilder, diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/Component.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/Component.kt index 7e28fe664e..3b9f06da0e 100644 --- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/Component.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/Component.kt @@ -36,7 +36,6 @@ interface Component: ComponentIdentity { /** * Access to variant's source files. */ - @get:Incubating val sources: Sources /** @@ -80,7 +79,6 @@ interface Component: ComponentIdentity { * * The returned [Configuration] should not be resolved until execution time. */ - @get:Incubating val compileConfiguration: Configuration /** @@ -89,7 +87,6 @@ interface Component: ComponentIdentity { * * The returned [Configuration] should not be resolved until execution time. */ - @get:Incubating val runtimeConfiguration: Configuration /** @@ -98,6 +95,5 @@ interface Component: ComponentIdentity { * * The returned [Configuration] should not be resolved until execution time. */ - @get:Incubating val annotationProcessorConfiguration: Configuration } diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/DependenciesInfoBuilder.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/DependenciesInfoBuilder.kt index 677d27e8c2..46979b26bb 100644 --- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/DependenciesInfoBuilder.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/DependenciesInfoBuilder.kt @@ -16,7 +16,39 @@ package com.android.build.api.variant +/** + * Interface for component builder that specifies whether to include SDK dependency information + * in APKs and Bundles for the variant + * + * Including dependency information in your APK or Bundle allows Google Play to ensure that + * any third-party software your app uses complies with + * [Google Play's Developer Program Policies](https://support.google.com/googleplay/android-developer/topic/9858052). + * For more information, see the Play Console support page + * [Using third-party SDKs in your app](https://support.google.com/googleplay/android-developer/answer/10358880). + */ interface DependenciesInfoBuilder { + @Deprecated("This property is renamed to includeInApk", replaceWith = ReplaceWith("includeInApk")) var includedInApk: Boolean + @Deprecated("This property is renamed to includeInBundle", replaceWith = ReplaceWith("includeInBundle")) var includedInBundle: Boolean + + /** + * Set to `true` if information about SDK dependencies of an APK should be added to its signature + * block, `false` otherwise. + * + * Default value will match [com.android.build.api.dsl.DependenciesInfo.includeInApk] + */ + var includeInApk: Boolean + + /** + * Whether information about SDK dependencies of an App Bundle will be added to it. + */ + + /** + * Set to `true` if information about SDK dependencies of an App Bundle should be added to it, + * `false` otherwise. + * + * Default value will match [com.android.build.api.dsl.DependenciesInfo.includeInBundle] + */ + var includeInBundle: Boolean } diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/DynamicFeatureVariant.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/DynamicFeatureVariant.kt index d68f7d38eb..ca06d6523f 100644 --- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/DynamicFeatureVariant.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/DynamicFeatureVariant.kt @@ -15,5 +15,9 @@ */ package com.android.build.api.variant -interface DynamicFeatureVariant : Variant, GeneratesApk, HasAndroidTest, HasTestFixtures { +interface DynamicFeatureVariant : Variant, + GeneratesApk, + HasAndroidTest, + HasUnitTest, + HasTestFixtures { } diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/DynamicFeatureVariantBuilder.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/DynamicFeatureVariantBuilder.kt index de37d69ff5..9559743416 100644 --- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/DynamicFeatureVariantBuilder.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/DynamicFeatureVariantBuilder.kt @@ -17,5 +17,6 @@ package com.android.build.api.variant interface DynamicFeatureVariantBuilder : VariantBuilder, HasAndroidTestBuilder, + HasUnitTestBuilder, HasTestFixturesBuilder, GeneratesApkBuilder diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/Orientation.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/HasUnitTest.kt index 553bb571a0..e0bb36318d 100644 --- a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/Orientation.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/HasUnitTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,16 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.google.firebase.testlab.gradle + +package com.android.build.api.variant /** - * Specifies the Orientation that tests should be run on the [ManagedDevice] + * Variants that optionally have unit test component */ -enum class Orientation { - /** The default orientation for that device. */ - DEFAULT, - /** Explicitly set the orientation to portrait. */ - PORTRAIT, - /** Explicitly set the orientation to landscape. */ - LANDSCAPE, +interface HasUnitTest { + /** + * Variant's [UnitTest], or null if the unit tests for this variant are disabled. + */ + val unitTest: UnitTest? } diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/HasUnitTestBuilder.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/HasUnitTestBuilder.kt new file mode 100644 index 0000000000..7366ecad22 --- /dev/null +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/HasUnitTestBuilder.kt @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2023 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.build.api.variant + +/** + * Interface that mark the potential existence of unit tests associated with a variant. + */ +interface HasUnitTestBuilder { + /** + * Set to `true` if the variant's has any unit tests, false otherwise. Value is [Boolean#True] + * by default. + */ + var enableUnitTest: Boolean +} diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/LibraryVariant.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/LibraryVariant.kt index f862d83cf5..57accfc046 100644 --- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/LibraryVariant.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/LibraryVariant.kt @@ -16,7 +16,12 @@ package com.android.build.api.variant /** [Variant] for Library projects */ -interface LibraryVariant : Variant, GeneratesAar, HasAndroidTest, HasTestFixtures, CanMinifyCode { +interface LibraryVariant : Variant, + GeneratesAar, + HasAndroidTest, + HasUnitTest, + HasTestFixtures, + CanMinifyCode { /** * Variant specific settings for the renderscript compiler. This will return null when diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/LibraryVariantBuilder.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/LibraryVariantBuilder.kt index a3c2459a3c..44df3b4bb3 100644 --- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/LibraryVariantBuilder.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/LibraryVariantBuilder.kt @@ -20,5 +20,6 @@ package com.android.build.api.variant */ interface LibraryVariantBuilder : VariantBuilder, HasAndroidTestBuilder, + HasUnitTestBuilder, HasTestFixturesBuilder, CanMinifyCodeBuilder diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/Variant.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/Variant.kt index 9a8aa11e04..7c319a9425 100644 --- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/Variant.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/Variant.kt @@ -22,7 +22,6 @@ import org.gradle.api.Incubating import org.gradle.api.file.RegularFile import org.gradle.api.provider.ListProperty import org.gradle.api.provider.MapProperty -import org.gradle.api.provider.Provider import java.io.Serializable /** @@ -90,6 +89,10 @@ interface Variant : Component, HasAndroidResources { /** * Variant's [UnitTest], or null if the unit tests for this variant are disabled. */ + @Deprecated( + "Will be removed in v9.0", + replaceWith = ReplaceWith("(Variant.Subtype).unitTest where available") + ) val unitTest: UnitTest? /** diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/VariantBuilder.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/VariantBuilder.kt index 4817543df4..432dd4e8b7 100644 --- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/VariantBuilder.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/VariantBuilder.kt @@ -89,16 +89,22 @@ interface VariantBuilder: ComponentBuilder { * Set to `true` if the variant's has any unit tests, false otherwise. Value is [Boolean#True] * by default. */ - @Deprecated("Use enableUnitTest", replaceWith=ReplaceWith("enableUnitTest")) + @Deprecated( + "Will be removed in AGP 9.0.", + replaceWith=ReplaceWith("(VariantBuilder.Subtype).enableUnitTest where available") + ) var unitTestEnabled: Boolean /** * Set to `true` if the variant's has any unit tests, false otherwise. Value is [Boolean#True] * by default. */ + @Deprecated( + "Will be removed in AGP 9.0.", + replaceWith=ReplaceWith("(VariantBuilder.Subtype).enableUnitTest where available") + ) var enableUnitTest: Boolean - /** * Registers an extension object to the variant object. Extension objects can be looked up * during the [AndroidComponentsExtension.onVariants] callbacks diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/VariantSelector.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/VariantSelector.kt index efba0488c8..ee601ede41 100644 --- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/VariantSelector.kt +++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/VariantSelector.kt @@ -48,6 +48,15 @@ interface VariantSelector { fun withFlavor(flavorToDimension: Pair<String, String>): VariantSelector /** + * Returns a new selector for [ComponentIdentity] objects with a given (flavorName). + * + * @param dimension dimension name + * @param flavorName flavor name to filter [ComponentIdentity] on. + * @return [VariantSelector] instance to further filter instances of [ComponentIdentity] + */ + fun withFlavor(dimension: String, flavorName: String): VariantSelector + + /** * Returns a new selector for [ComponentIdentity] objects with a given name pattern. * * @param pattern [Pattern] to apply on the [org.gradle.api.Named.getName] to filter [ComponentIdentity] diff --git a/build-system/gradle-api/src/test/resources/com/android/build/api/deprecated-api.txt b/build-system/gradle-api/src/test/resources/com/android/build/api/deprecated-api.txt index 267a56f6ce..6ee1484be3 100644 --- a/build-system/gradle-api/src/test/resources/com/android/build/api/deprecated-api.txt +++ b/build-system/gradle-api/src/test/resources/com/android/build/api/deprecated-api.txt @@ -227,7 +227,6 @@ Deprecated from AGP UNKNOWN_VERSION * com.android.build.api.variant.ComponentBuilder.setEnabled: void (boolean) * com.android.build.api.variant.HasAndroidTestBuilder.getAndroidTestEnabled: boolean () * com.android.build.api.variant.HasAndroidTestBuilder.setAndroidTestEnabled: void (boolean) - * com.android.build.api.variant.VariantBuilder.getUnitTestEnabled: boolean () * com.android.build.api.variant.VariantInfo * com.android.build.api.variant.VariantInfo.getBuildTypeName: java.lang.String () * com.android.build.api.variant.VariantInfo.getFlavorNames: com.google.common.collect.ImmutableList<java.lang.String> () @@ -255,7 +254,6 @@ Deprecated from AGP 7.2.0 * com.android.build.api.dsl.BuildType.setTestCoverageEnabled: void (boolean) * com.android.build.api.variant.Component.setAsmFramesComputationMode: void (com.android.build.api.instrumentation.FramesComputationMode) * com.android.build.api.variant.Component.transformClassesWith: void (java.lang.Class<? extends com.android.build.api.instrumentation.AsmClassVisitorFactory<ParamT>>, com.android.build.api.instrumentation.InstrumentationScope, kotlin.jvm.functions.Function1<? super ParamT, kotlin.Unit>) - * com.android.build.api.variant.VariantBuilder.setUnitTestEnabled: void (boolean) Deprecated from AGP 7.3.0 * com.android.build.api.dsl.DataBinding.isEnabled: boolean () * com.android.build.api.dsl.DataBinding.isEnabledForTests: boolean () @@ -276,9 +274,18 @@ Deprecated from AGP 8.1.0 * com.android.build.api.dsl.DensitySplit.getCompatibleScreens: java.util.Set<java.lang.String> () * com.android.build.api.dsl.DensitySplit.isStrict: boolean () * com.android.build.api.dsl.DensitySplit.setStrict: void (boolean) + * com.android.build.api.variant.DependenciesInfoBuilder.getIncludedInApk: boolean () + * com.android.build.api.variant.DependenciesInfoBuilder.getIncludedInBundle: boolean () + * com.android.build.api.variant.DependenciesInfoBuilder.setIncludedInApk: void (boolean) + * com.android.build.api.variant.DependenciesInfoBuilder.setIncludedInBundle: void (boolean) * com.android.build.api.variant.GeneratesApk.getTargetSdkVersion: com.android.build.api.variant.AndroidVersion () * com.android.build.api.variant.Variant.getMaxSdkVersion: java.lang.Integer () * com.android.build.api.variant.Variant.getMinSdkVersion: com.android.build.api.variant.AndroidVersion () + * com.android.build.api.variant.Variant.getUnitTest: com.android.build.api.component.UnitTest () + * com.android.build.api.variant.VariantBuilder.getEnableUnitTest: boolean () + * com.android.build.api.variant.VariantBuilder.getUnitTestEnabled: boolean () + * com.android.build.api.variant.VariantBuilder.setEnableUnitTest: void (boolean) + * com.android.build.api.variant.VariantBuilder.setUnitTestEnabled: void (boolean) Deprecated from AGP 7.4.0 * com.android.build.api.dsl.LibraryBaseFlavor.getTargetSdk: java.lang.Integer () * com.android.build.api.dsl.LibraryBaseFlavor.getTargetSdkPreview: java.lang.String () diff --git a/build-system/gradle-core/BUILD b/build-system/gradle-core/BUILD index 0043a20cec..0255134c77 100644 --- a/build-system/gradle-core/BUILD +++ b/build-system/gradle-core/BUILD @@ -127,7 +127,10 @@ java_library( java_library( name = "jetbrains.kotlin-gradle-plugin_neverlink", #neverlink = 1, - exports = ["@maven//:org.jetbrains.kotlin.kotlin-gradle-plugin"], + exports = [ + "@maven//:org.jetbrains.kotlin.kotlin-gradle-plugin", + "@maven//:org.jetbrains.kotlin.kotlin-gradle-plugin-api", + ], ) fileset( diff --git a/build-system/gradle-core/build.gradle b/build-system/gradle-core/build.gradle index 56a192a619..751df3dba6 100644 --- a/build-system/gradle-core/build.gradle +++ b/build-system/gradle-core/build.gradle @@ -342,6 +342,10 @@ tasks.jar { }) } +tasks.named("kotlinSourcesJar").configure { + it.dependsOn(tasks.named("generateProto")) +} + tasks.sourcesJar { dependsOn configurations.includeInJarSources from { diff --git a/build-system/gradle-core/lint_baseline.xml b/build-system/gradle-core/lint_baseline.xml index aadb2c39ec..b024564544 100644 --- a/build-system/gradle-core/lint_baseline.xml +++ b/build-system/gradle-core/lint_baseline.xml @@ -25,7 +25,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/test/AbstractTestDataImpl.kt" - line="74"/> + line="100"/> </issue> <issue @@ -297,7 +297,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt" - line="178"/> + line="182"/> </issue> <issue @@ -305,7 +305,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt" - line="186"/> + line="190"/> </issue> <issue @@ -313,7 +313,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt" - line="201"/> + line="205"/> </issue> <issue @@ -321,7 +321,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt" - line="211"/> + line="215"/> </issue> <issue @@ -329,7 +329,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt" - line="233"/> + line="237"/> </issue> <issue @@ -337,7 +337,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt" - line="252"/> + line="256"/> </issue> <issue @@ -345,7 +345,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt" - line="266"/> + line="270"/> </issue> <issue @@ -353,7 +353,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt" - line="273"/> + line="277"/> </issue> <issue @@ -361,7 +361,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt" - line="282"/> + line="286"/> </issue> <issue @@ -369,7 +369,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt" - line="286"/> + line="290"/> </issue> <issue @@ -377,7 +377,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt" - line="307"/> + line="311"/> </issue> <issue @@ -409,7 +409,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/dsl/CommonExtensionImpl.kt" - line="66"/> + line="69"/> </issue> <issue @@ -433,7 +433,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/api/component/impl/ComponentImpl.kt" - line="153"/> + line="140"/> </issue> <issue @@ -441,7 +441,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/api/component/impl/ComponentImpl.kt" - line="208"/> + line="195"/> </issue> <issue @@ -449,7 +449,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/api/component/impl/ComponentImpl.kt" - line="270"/> + line="220"/> </issue> <issue @@ -457,7 +457,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/api/component/impl/ComponentImpl.kt" - line="280"/> + line="230"/> </issue> <issue @@ -465,7 +465,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/api/component/impl/ComponentImpl.kt" - line="311"/> + line="261"/> </issue> <issue @@ -585,7 +585,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/tasks/factory/GlobalTaskCreationConfigImpl.kt" - line="97"/> + line="98"/> </issue> <issue @@ -593,7 +593,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/tasks/factory/GlobalTaskCreationConfigImpl.kt" - line="183"/> + line="184"/> </issue> <issue @@ -601,7 +601,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/tasks/factory/GlobalTaskCreationConfigImpl.kt" - line="226"/> + line="227"/> </issue> <issue @@ -609,7 +609,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/tasks/factory/GlobalTaskCreationConfigImpl.kt" - line="233"/> + line="234"/> </issue> <issue @@ -632,6 +632,46 @@ id="AvoidByLazy" message="Avoid `by lazy` for simple lazy initialization"> <location + file="src/main/java/com/android/build/api/component/impl/KmpAndroidTestImpl.kt" + line="110"/> + </issue> + + <issue + id="AvoidByLazy" + message="Avoid `by lazy` for simple lazy initialization"> + <location + file="src/main/java/com/android/build/api/component/impl/KmpAndroidTestImpl.kt" + line="154"/> + </issue> + + <issue + id="AvoidByLazy" + message="Avoid `by lazy` for simple lazy initialization"> + <location + file="src/main/java/com/android/build/api/component/impl/KmpAndroidTestImpl.kt" + line="165"/> + </issue> + + <issue + id="AvoidByLazy" + message="Avoid `by lazy` for simple lazy initialization"> + <location + file="src/main/java/com/android/build/api/component/impl/KmpAndroidTestImpl.kt" + line="195"/> + </issue> + + <issue + id="AvoidByLazy" + message="Avoid `by lazy` for simple lazy initialization"> + <location + file="src/main/java/com/android/build/api/component/impl/KmpAndroidTestImpl.kt" + line="203"/> + </issue> + + <issue + id="AvoidByLazy" + message="Avoid `by lazy` for simple lazy initialization"> + <location file="src/main/java/com/android/build/gradle/internal/core/dsl/impl/KmpComponentDslInfoImpl.kt" line="36"/> </issue> @@ -641,7 +681,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/tasks/factory/KmpGlobalTaskCreationConfigImpl.kt" - line="78"/> + line="79"/> </issue> <issue @@ -649,7 +689,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/tasks/factory/KmpGlobalTaskCreationConfigImpl.kt" - line="81"/> + line="82"/> </issue> <issue @@ -657,7 +697,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/tasks/factory/KmpGlobalTaskCreationConfigImpl.kt" - line="152"/> + line="153"/> </issue> <issue @@ -857,7 +897,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestProjectVariantDslInfoImpl.kt" - line="82"/> + line="80"/> </issue> <issue @@ -865,7 +905,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestProjectVariantDslInfoImpl.kt" - line="95"/> + line="93"/> </issue> <issue @@ -873,7 +913,7 @@ message="Avoid `by lazy` for simple lazy initialization"> <location file="src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestProjectVariantDslInfoImpl.kt" - line="119"/> + line="117"/> </issue> <issue diff --git a/build-system/gradle-core/src/apiTest/kotlin/com/android/build/api/apiTest/kotlin/AddCustomSourceTest.kt b/build-system/gradle-core/src/apiTest/kotlin/com/android/build/api/apiTest/kotlin/AddCustomSourceTest.kt index 4e995cd38d..bf94d3cd47 100644 --- a/build-system/gradle-core/src/apiTest/kotlin/com/android/build/api/apiTest/kotlin/AddCustomSourceTest.kt +++ b/build-system/gradle-core/src/apiTest/kotlin/com/android/build/api/apiTest/kotlin/AddCustomSourceTest.kt @@ -48,6 +48,25 @@ class AddCustomSourceTest: VariantApiBaseTest(TestType.Script) { minSdkVersion(21) targetSdkVersion(29) } + + flavorDimensions += listOf("dim1", "dim2") + productFlavors { + create("a1") { + dimension = "dim1" + } + create("b1") { + dimension = "dim1" + } + create("a2") { + dimension = "dim2" + } + create("b2") { + dimension = "dim2" + } + create("c2") { + dimension = "dim2" + } + } } androidComponents { @@ -64,7 +83,7 @@ class AddCustomSourceTest: VariantApiBaseTest(TestType.Script) { """ # Add custom source folders in Kotlin This sample shows how to add a new custom source folders to all source sets. The source folder will -not be used by any AGP tasks (since we do no know about it), however, it can be used by plugins and +not be used by any AGP tasks (since we do not know about it), however, it can be used by plugins and tasks participating into the Variant API callbacks. To register the custom sources, you just need to use @@ -82,6 +101,32 @@ To register the custom sources, you just need to use Truth.assertThat(output).contains("Custom sources: [app/src/debug/toml]") Truth.assertThat(output).contains("Custom sources: [app/src/main/toml]") Truth.assertThat(output).contains("Custom sources: [app/src/release/toml]") + // Check all single flavors: + Truth.assertThat(output).contains("Custom sources: [app/src/a1/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/b1/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/a2/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/b2/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/c2/toml]") + // Check all combined flavors: + Truth.assertThat(output).contains("Custom sources: [app/src/a1A2/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/a1B2/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/a1C2/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/b1A2/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/b1B2/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/b1C2/toml]") + // Check all variants: + Truth.assertThat(output).contains("Custom sources: [app/src/a1A2Debug/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/a1B2Debug/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/a1C2Debug/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/b1A2Debug/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/b1B2Debug/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/b1C2Debug/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/a1A2Release/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/a1B2Release/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/a1C2Release/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/b1A2Release/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/b1B2Release/toml]") + Truth.assertThat(output).contains("Custom sources: [app/src/b1C2Release/toml]") } } diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledKotlinMultiplatformAndroidVariant.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledKotlinMultiplatformAndroidVariant.kt index 97480a70ea..c149285d60 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledKotlinMultiplatformAndroidVariant.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledKotlinMultiplatformAndroidVariant.kt @@ -95,6 +95,7 @@ open class AnalyticsEnabledKotlinMultiplatformAndroidVariant @Inject constructor VariantPropertiesMethodType.RUNTIME_CONFIGURATION_VALUE return delegate.runtimeConfiguration } + private val userVisibleUnitTest: AnalyticsEnabledUnitTest? by lazy { delegate.unitTest?.let { objectFactory.newInstance( @@ -107,6 +108,7 @@ open class AnalyticsEnabledKotlinMultiplatformAndroidVariant @Inject constructor override val unitTest: com.android.build.api.component.UnitTest? get() = userVisibleUnitTest + private val userVisibleAarMetadata: AarMetadata by lazy { objectFactory.newInstance( AnalyticsEnabledAarMetadata::class.java, diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/AndroidTestImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/AndroidTestImpl.kt index 053dd16953..db28daf7c9 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/AndroidTestImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/AndroidTestImpl.kt @@ -179,7 +179,7 @@ open class AndroidTestImpl @Inject constructor( it, variantServices, minSdk.apiLevel, - services.projectOptions.get(IntegerOption.IDE_TARGET_DEVICE_API) + global.targetDeployApiFromIDE ) } } diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ComponentImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ComponentImpl.kt index 91f37912a7..3148b11377 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ComponentImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ComponentImpl.kt @@ -45,34 +45,21 @@ import com.android.build.gradle.internal.core.ProductFlavor import com.android.build.gradle.internal.core.VariantSources import com.android.build.gradle.internal.core.dsl.ComponentDslInfo import com.android.build.gradle.internal.core.dsl.PublishableComponentDslInfo -import com.android.build.gradle.internal.dependency.AndroidAttributes import com.android.build.gradle.internal.dependency.VariantDependencies import com.android.build.gradle.internal.dependency.getProvidedClasspath import com.android.build.gradle.internal.publishing.AndroidArtifacts import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope import com.android.build.gradle.internal.publishing.AndroidArtifacts.ConsumedConfigType -import com.android.build.gradle.internal.publishing.AndroidArtifacts.PublishedConfigType -import com.android.build.gradle.internal.publishing.PublishedConfigSpec -import com.android.build.gradle.internal.publishing.PublishingSpecs.Companion.getVariantPublishingSpec -import com.android.build.gradle.internal.scope.BuildArtifactSpec.Companion.get -import com.android.build.gradle.internal.scope.BuildArtifactSpec.Companion.has import com.android.build.gradle.internal.scope.BuildFeatureValues import com.android.build.gradle.internal.scope.MutableTaskContainer -import com.android.build.gradle.internal.scope.publishArtifactToConfiguration -import com.android.build.gradle.internal.scope.publishArtifactToDefaultVariant import com.android.build.gradle.internal.services.TaskCreationServices import com.android.build.gradle.internal.services.VariantServices import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfig -import com.android.build.gradle.internal.testFixtures.testFixturesClassifier import com.android.build.gradle.internal.variant.BaseVariantData import com.android.build.gradle.internal.variant.VariantPathHelper import com.android.builder.core.ComponentType import com.android.utils.appendCapitalized -import com.google.common.base.Preconditions -import org.gradle.api.attributes.DocsType -import org.gradle.api.attributes.LibraryElements import org.gradle.api.file.FileCollection -import org.gradle.api.file.FileSystemLocation import org.gradle.api.provider.Provider import java.io.File import java.util.Locale @@ -163,7 +150,7 @@ abstract class ComponentImpl<DslInfoT: ComponentDslInfo>( override val runtimeConfiguration = variantDependencies.runtimeClasspath override val annotationProcessorConfiguration = - variantDependencies.annotationProcessorConfiguration + variantDependencies.annotationProcessorConfiguration!! // --------------------------------------------------------------------------------------------- // INTERNAL API @@ -222,47 +209,10 @@ abstract class ComponentImpl<DslInfoT: ComponentDslInfo>( /** Publish intermediate artifacts in the BuildArtifactsHolder based on PublishingSpecs. */ override fun publishBuildArtifacts() { - for (outputSpec in getVariantPublishingSpec(componentType).outputs) { - val buildArtifactType = outputSpec.outputType - // Gradle only support publishing single file. Therefore, unless Gradle starts - // supporting publishing multiple files, PublishingSpecs should not contain any - // OutputSpec with an appendable ArtifactType. - if (has(buildArtifactType) && get(buildArtifactType).appendable) { - throw RuntimeException( - "Appendable ArtifactType '${buildArtifactType.name()}' cannot be published." - ) - } - val artifactProvider = artifacts.get(buildArtifactType) - val artifactContainer = artifacts.getArtifactContainer(buildArtifactType) - if (!artifactContainer.needInitialProducer().get()) { - val isPublicationConfigs = - outputSpec.publishedConfigTypes.any { it.isPublicationConfig } - - if (isPublicationConfigs) { - val components = (dslInfo as PublishableComponentDslInfo).publishInfo.components - for(component in components) { - publishIntermediateArtifact( - artifactProvider, - outputSpec.artifactType, - outputSpec.publishedConfigTypes.map { - PublishedConfigSpec(it, component) }.toSet(), - outputSpec.libraryElements?.let { - internalServices.named(LibraryElements::class.java, it) - } - ) - } - } else { - publishIntermediateArtifact( - artifactProvider, - outputSpec.artifactType, - outputSpec.publishedConfigTypes.map { PublishedConfigSpec(it) }.toSet(), - outputSpec.libraryElements?.let { - internalServices.named(LibraryElements::class.java, it) - } - ) - } - } - } + com.android.build.gradle.internal.scope.publishBuildArtifacts( + this, + (dslInfo as? PublishableComponentDslInfo)?.publishInfo + ) } override val modelV1LegacySupport = ModelV1LegacySupportImpl(dslInfo, variantSources) @@ -353,56 +303,4 @@ abstract class ComponentImpl<DslInfoT: ComponentDslInfo>( internalServices ) } - - /** - * Publish an intermediate artifact. - * - * @param artifact Provider of File or FileSystemLocation to be published. - * @param artifactType the artifact type. - * @param configSpecs the PublishedConfigSpec. - * @param libraryElements the artifact's library elements - */ - private fun publishIntermediateArtifact( - artifact: Provider<out FileSystemLocation>, - artifactType: AndroidArtifacts.ArtifactType, - configSpecs: Set<PublishedConfigSpec>, - libraryElements: LibraryElements? - ) { - Preconditions.checkState(configSpecs.isNotEmpty()) - for (configSpec in configSpecs) { - val config = variantDependencies.getElements(configSpec) - val configType = configSpec.configType - if (config != null) { - if (configType.isPublicationConfig) { - var classifier: String? = null - val isSourcePublication = configType == PublishedConfigType.SOURCE_PUBLICATION - val isJavaDocPublication = - configType == PublishedConfigType.JAVA_DOC_PUBLICATION - if (configSpec.isClassifierRequired) { - classifier = if (isSourcePublication) { - componentIdentity.name + "-" + DocsType.SOURCES - } else if (isJavaDocPublication) { - componentIdentity.name + "-" + DocsType.JAVADOC - } else { - componentIdentity.name - } - } else if (componentType.isTestFixturesComponent) { - classifier = testFixturesClassifier - } else if (isSourcePublication) { - classifier = DocsType.SOURCES - } else if (isJavaDocPublication) { - classifier = DocsType.JAVADOC - } - publishArtifactToDefaultVariant(config, artifact, artifactType, classifier) - } else { - publishArtifactToConfiguration( - config, - artifact, - artifactType, - AndroidAttributes(null, libraryElements) - ) - } - } - } - } } diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ComponentUtils.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ComponentUtils.kt index 76025c38aa..69c002e213 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ComponentUtils.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ComponentUtils.kt @@ -71,7 +71,7 @@ internal fun ApkCreationConfig.isTestApk(): Boolean { return projectOptions.get(OptionalBooleanOption.IDE_TEST_ONLY) ?: ( !Strings.isNullOrEmpty(projectOptions.get(StringOption.IDE_BUILD_TARGET_ABI)) - || projectOptions.get(IntegerOption.IDE_TARGET_DEVICE_API) != null + || global.targetDeployApiFromIDE != null || AndroidTargetHash.getVersionFromHash(global.compileSdkHashString)?.isPreview == true || minSdk.codename != null || targetSdk.codename != null) diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/KmpAndroidTestImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/KmpAndroidTestImpl.kt new file mode 100644 index 0000000000..0adb7e6514 --- /dev/null +++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/KmpAndroidTestImpl.kt @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2022 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.build.api.component.impl + +import com.android.build.api.artifact.impl.ArtifactsImpl +import com.android.build.api.component.impl.features.AndroidResourcesCreationConfigImpl +import com.android.build.api.component.impl.features.AssetsCreationConfigImpl +import com.android.build.api.component.impl.features.DexingCreationConfigImpl +import com.android.build.api.component.impl.features.ManifestPlaceholdersCreationConfigImpl +import com.android.build.api.component.impl.features.OptimizationCreationConfigImpl +import com.android.build.api.instrumentation.AsmClassVisitorFactory +import com.android.build.api.instrumentation.FramesComputationMode +import com.android.build.api.instrumentation.InstrumentationParameters +import com.android.build.api.instrumentation.InstrumentationScope +import com.android.build.api.variant.AndroidResources +import com.android.build.api.variant.AndroidTest +import com.android.build.api.variant.AndroidVersion +import com.android.build.api.variant.ApkPackaging +import com.android.build.api.variant.BuildConfigField +import com.android.build.api.variant.Renderscript +import com.android.build.api.variant.ResValue +import com.android.build.api.variant.SigningConfig +import com.android.build.api.variant.impl.ApkPackagingImpl +import com.android.build.api.variant.impl.KmpVariantImpl +import com.android.build.api.variant.impl.KotlinMultiplatformAndroidCompilation +import com.android.build.api.variant.impl.ResValueKeyImpl +import com.android.build.api.variant.impl.SigningConfigImpl +import com.android.build.gradle.internal.component.AndroidTestCreationConfig +import com.android.build.gradle.internal.component.VariantCreationConfig +import com.android.build.gradle.internal.component.features.AndroidResourcesCreationConfig +import com.android.build.gradle.internal.component.features.AssetsCreationConfig +import com.android.build.gradle.internal.component.features.DexingCreationConfig +import com.android.build.gradle.internal.component.features.FeatureNames +import com.android.build.gradle.internal.component.features.ManifestPlaceholdersCreationConfig +import com.android.build.gradle.internal.component.features.NativeBuildCreationConfig +import com.android.build.gradle.internal.component.features.OptimizationCreationConfig +import com.android.build.gradle.internal.component.features.RenderscriptCreationConfig +import com.android.build.gradle.internal.component.features.ShadersCreationConfig +import com.android.build.gradle.internal.core.dsl.impl.KmpAndroidTestDslInfoImpl +import com.android.build.gradle.internal.dependency.VariantDependencies +import com.android.build.gradle.internal.scope.BuildFeatureValues +import com.android.build.gradle.internal.scope.MutableTaskContainer +import com.android.build.gradle.internal.services.TaskCreationServices +import com.android.build.gradle.internal.services.VariantServices +import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfig +import com.android.build.gradle.internal.variant.VariantPathHelper +import org.gradle.api.file.RegularFile +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.MapProperty +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import java.io.File +import java.io.Serializable +import javax.inject.Inject + +open class KmpAndroidTestImpl @Inject constructor( + dslInfo: KmpAndroidTestDslInfoImpl, + internalServices: VariantServices, + buildFeatures: BuildFeatureValues, + variantDependencies: VariantDependencies, + paths: VariantPathHelper, + artifacts: ArtifactsImpl, + taskContainer: MutableTaskContainer, + services: TaskCreationServices, + global: GlobalTaskCreationConfig, + androidKotlinCompilation: KotlinMultiplatformAndroidCompilation, + override val mainVariant: KmpVariantImpl, + manifestFile: File +): KmpComponentImpl<KmpAndroidTestDslInfoImpl>( + dslInfo, + internalServices, + buildFeatures, + variantDependencies, + paths, + artifacts, + taskContainer, + services, + global, + androidKotlinCompilation, + manifestFile +), AndroidTestCreationConfig, AndroidTest { + + override val testOnlyApk: Boolean + get() = true + + override val debuggable: Boolean + get() = true + + override fun <T> onTestedVariant(action: (VariantCreationConfig) -> T): T { + return action.invoke(mainVariant) + } + + override val targetSdkVersion: AndroidVersion + get() = targetSdk + override val targetSdk: AndroidVersion + get() = dslInfo.targetSdkVersion ?: minSdk + override val targetSdkOverride: AndroidVersion? + get() = dslInfo.targetSdkVersion + override val testedApplicationId: Provider<String> + get() = applicationId + override val instrumentationRunner: Property<String> by lazy { + internalServices.propertyOf( + String::class.java, + dslInfo.getInstrumentationRunner(dexingCreationConfig.dexingType) + ) + } + + override val isAndroidTestCoverageEnabled: Boolean + get() = dslInfo.isAndroidTestCoverageEnabled + override val useJacocoTransformInstrumentation: Boolean + get() = dslInfo.isAndroidTestCoverageEnabled + override val packageJacocoRuntime: Boolean + get() = dslInfo.isAndroidTestCoverageEnabled + + override val applicationId: Property<String> + get() = dslInfo.applicationId + override val instrumentationRunnerArguments: Map<String, String> + get() = dslInfo.instrumentationRunnerArguments + override val handleProfiling: Property<Boolean> = + internalServices.propertyOf(Boolean::class.java, dslInfo.handleProfiling) + override val functionalTest: Property<Boolean> = + internalServices.propertyOf(Boolean::class.java, dslInfo.functionalTest) + override val testLabel: Property<String?> = + internalServices.nullablePropertyOf(String::class.java, dslInfo.testLabel) + + // Even if android resources is not enabled, we still need to merge and link external resources + // to create the test apk. + override val androidResourcesCreationConfig: AndroidResourcesCreationConfig by lazy(LazyThreadSafetyMode.NONE) { + AndroidResourcesCreationConfigImpl( + this, + dslInfo, + dslInfo.androidResourcesDsl, + internalServices + ) + } + + override val assetsCreationConfig: AssetsCreationConfig + get() = AssetsCreationConfigImpl( + dslInfo.androidResourcesDsl, + internalServices, + ) { + androidResourcesCreationConfig + } + + override val dexingCreationConfig: DexingCreationConfig by lazy { + DexingCreationConfigImpl( + this, + dslInfo.dexingDslInfo, + internalServices + ) + } + + override val isCoreLibraryDesugaringEnabledLintCheck: Boolean + get() = dexingCreationConfig.isCoreLibraryDesugaringEnabled + + override val signingConfigImpl: SigningConfigImpl? by lazy { + SigningConfigImpl( + dslInfo.signingConfig, + internalServices, + minSdk.apiLevel, + global.targetDeployApiFromIDE + ) + } + + override val signingConfig: SigningConfig? + get() = signingConfigImpl + + override val optimizationCreationConfig: OptimizationCreationConfig by lazy(LazyThreadSafetyMode.NONE) { + OptimizationCreationConfigImpl( + this, + dslInfo.optimizationDslInfo, + null, + null, + internalServices + ) + } + + override val manifestPlaceholdersCreationConfig: ManifestPlaceholdersCreationConfig by lazy(LazyThreadSafetyMode.NONE) { + ManifestPlaceholdersCreationConfigImpl( + // no dsl for this + emptyMap(), + internalServices + ) + } + + override val packaging: ApkPackaging by lazy { + ApkPackagingImpl( + dslInfo.mainVariantDslInfo.packaging, + internalServices, + minSdk.apiLevel + ) + } + + override val buildConfigFields: MapProperty<String, out BuildConfigField<out Serializable>> by lazy { + warnAboutAccessingVariantApiValueForDisabledFeature( + featureName = FeatureNames.BUILD_CONFIG, + apiName = "buildConfigFields", + value = internalServices.mapPropertyOf( + String::class.java, + BuildConfigField::class.java, + emptyMap() + ) + ) + } + override val manifestPlaceholders: MapProperty<String, String> + get() = manifestPlaceholdersCreationConfig.placeholders + override val proguardFiles: ListProperty<RegularFile> + get() = optimizationCreationConfig.proguardFiles + + override val androidResources: AndroidResources + get() = androidResourcesCreationConfig.androidResources + + override fun makeResValueKey(type: String, name: String): ResValue.Key = + ResValueKeyImpl(type, name) + + override val resValues: MapProperty<ResValue.Key, ResValue> by lazy { + resValuesCreationConfig?.resValues + ?: warnAboutAccessingVariantApiValueForDisabledFeature( + featureName = FeatureNames.RES_VALUES, + apiName = "resValues", + value = internalServices.mapPropertyOf( + ResValue.Key::class.java, + ResValue::class.java, + dslInfo.androidResourcesDsl.getResValues() + ) + ) + } + override val pseudoLocalesEnabled: Property<Boolean> by lazy { + androidResourcesCreationConfig.pseudoLocalesEnabled + } + + override fun <ParamT : InstrumentationParameters> transformClassesWith( + classVisitorFactoryImplClass: Class<out AsmClassVisitorFactory<ParamT>>, + scope: InstrumentationScope, + instrumentationParamsConfig: (ParamT) -> Unit + ) { + instrumentation.transformClassesWith( + classVisitorFactoryImplClass, + scope, + instrumentationParamsConfig + ) + } + + override fun setAsmFramesComputationMode(mode: FramesComputationMode) { + instrumentation.setAsmFramesComputationMode(mode) + } + + // unsupported features + override val shouldPackageProfilerDependencies: Boolean = false + override val embedsMicroApp: Boolean = false + override val advancedProfilingTransforms: List<String> = emptyList() + override val renderscript: Renderscript? = null + override val renderscriptCreationConfig: RenderscriptCreationConfig? = null + override val shadersCreationConfig: ShadersCreationConfig? = null + override val nativeBuildCreationConfig: NativeBuildCreationConfig? = null +} diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/KmpComponentImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/KmpComponentImpl.kt index 7793d55833..e42a9a0309 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/KmpComponentImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/KmpComponentImpl.kt @@ -17,6 +17,7 @@ package com.android.build.api.component.impl import com.android.SdkConstants +import com.android.build.api.artifact.ScopedArtifact import com.android.build.api.artifact.impl.ArtifactsImpl import com.android.build.api.component.impl.features.InstrumentationCreationConfigImpl import com.android.build.api.variant.AndroidVersion @@ -24,8 +25,11 @@ import com.android.build.api.variant.ComponentIdentity import com.android.build.api.variant.Instrumentation import com.android.build.api.variant.InternalSources import com.android.build.api.variant.JavaCompilation +import com.android.build.api.variant.ScopedArtifacts import com.android.build.api.variant.SourceDirectories +import com.android.build.api.variant.impl.FileBasedDirectoryEntryImpl import com.android.build.api.variant.impl.FlatSourceDirectoriesImpl +import com.android.build.api.variant.impl.KotlinMultiplatformAndroidCompilation import com.android.build.api.variant.impl.LayeredSourceDirectoriesImpl import com.android.build.api.variant.impl.SourceType import com.android.build.api.variant.impl.SourcesImpl @@ -42,7 +46,10 @@ import com.android.build.gradle.internal.core.ProductFlavor import com.android.build.gradle.internal.core.dsl.KmpComponentDslInfo import com.android.build.gradle.internal.dependency.VariantDependencies import com.android.build.gradle.internal.dependency.getProvidedClasspath +import com.android.build.gradle.internal.dsl.AbstractPublishing import com.android.build.gradle.internal.publishing.AndroidArtifacts +import com.android.build.gradle.internal.publishing.ComponentPublishingInfo +import com.android.build.gradle.internal.publishing.VariantPublishingInfo import com.android.build.gradle.internal.scope.BuildFeatureValues import com.android.build.gradle.internal.scope.MutableTaskContainer import com.android.build.gradle.internal.services.TaskCreationServices @@ -69,6 +76,7 @@ abstract class KmpComponentImpl<DslInfoT: KmpComponentDslInfo>( override val taskContainer: MutableTaskContainer, override val services: TaskCreationServices, override val global: GlobalTaskCreationConfig, + override val androidKotlinCompilation: KotlinMultiplatformAndroidCompilation, manifestFile: File ): KmpComponentCreationConfig, ComponentIdentity by dslInfo.componentIdentity { @@ -162,7 +170,17 @@ abstract class KmpComponentImpl<DslInfoT: KmpComponentDslInfo>( } override fun publishBuildArtifacts() { - // TODO(b/243387425): implement + com.android.build.gradle.internal.scope.publishBuildArtifacts( + creationConfig = this, + publishInfo = VariantPublishingInfo( + components = listOf( + ComponentPublishingInfo( + componentName = name, + type = AbstractPublishing.Type.AAR + ) + ) + ) + ) } // Unsupported features @@ -267,4 +285,47 @@ abstract class KmpComponentImpl<DslInfoT: KmpComponentDslInfo>( override val multiFlavorSourceProvider: DefaultAndroidSourceSet? = null override val variantSourceProvider: DefaultAndroidSourceSet? = null } + + open fun syncAndroidAndKmpClasspathAndSources() { + artifacts + .forScope(ScopedArtifacts.Scope.PROJECT) + .getScopedArtifactsContainer(ScopedArtifact.CLASSES) + .initialScopedContent + .from(androidKotlinCompilation.output.classesDirs) + + androidKotlinCompilation.compileDependencyFiles = services.fileCollection( + global.bootClasspath, + getJavaClasspath( + AndroidArtifacts.ConsumedConfigType.COMPILE_CLASSPATH, + AndroidArtifacts.ArtifactType.CLASSES_JAR + ) + ) + + // Include all kotlin sourceSets (the ones added directly to the compilation and the ones + // that added transitively through a dependsOn dependency). + androidKotlinCompilation.allKotlinSourceSets.forEach { sourceSet -> + sources.kotlin { kotlin -> + sourceSet.kotlin.srcDirs.forEach { srcDir -> + kotlin.addSource( + FileBasedDirectoryEntryImpl( + name = "Kotlin", + directory = srcDir + ) + ) + } + } + + sources.resources { resources -> + sourceSet.resources.srcDirs.forEach { srcDir -> + resources.addSource( + FileBasedDirectoryEntryImpl( + name = "Java resources", + directory = srcDir, + filter = PatternSet().exclude("**/*.java", "**/*.kt"), + ) + ) + } + } + } + } } diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/KmpUnitTestImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/KmpUnitTestImpl.kt new file mode 100644 index 0000000000..718a5c113c --- /dev/null +++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/KmpUnitTestImpl.kt @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2022 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.build.api.component.impl + +import com.android.build.api.artifact.impl.ArtifactsImpl +import com.android.build.api.component.impl.features.ManifestPlaceholdersCreationConfigImpl +import com.android.build.api.instrumentation.AsmClassVisitorFactory +import com.android.build.api.instrumentation.FramesComputationMode +import com.android.build.api.instrumentation.InstrumentationParameters +import com.android.build.api.instrumentation.InstrumentationScope +import com.android.build.api.variant.AndroidVersion +import com.android.build.api.variant.UnitTest +import com.android.build.api.variant.impl.KmpVariantImpl +import com.android.build.api.variant.impl.KotlinMultiplatformAndroidCompilation +import com.android.build.gradle.internal.component.UnitTestCreationConfig +import com.android.build.gradle.internal.component.VariantCreationConfig +import com.android.build.gradle.internal.component.features.ManifestPlaceholdersCreationConfig +import com.android.build.gradle.internal.core.dsl.impl.DEFAULT_TEST_RUNNER +import com.android.build.gradle.internal.core.dsl.impl.KmpUnitTestDslInfoImpl +import com.android.build.gradle.internal.dependency.VariantDependencies +import com.android.build.gradle.internal.scope.BuildFeatureValues +import com.android.build.gradle.internal.scope.MutableTaskContainer +import com.android.build.gradle.internal.services.TaskCreationServices +import com.android.build.gradle.internal.services.VariantServices +import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfig +import com.android.build.gradle.internal.variant.VariantPathHelper +import org.gradle.api.provider.MapProperty +import org.gradle.api.provider.Provider +import java.io.File +import javax.inject.Inject + +open class KmpUnitTestImpl @Inject constructor( + dslInfo: KmpUnitTestDslInfoImpl, + internalServices: VariantServices, + buildFeatures: BuildFeatureValues, + variantDependencies: VariantDependencies, + paths: VariantPathHelper, + artifacts: ArtifactsImpl, + taskContainer: MutableTaskContainer, + services: TaskCreationServices, + global: GlobalTaskCreationConfig, + androidKotlinCompilation: KotlinMultiplatformAndroidCompilation, + override val mainVariant: KmpVariantImpl, + manifestFile: File +): KmpComponentImpl<KmpUnitTestDslInfoImpl>( + dslInfo, + internalServices, + buildFeatures, + variantDependencies, + paths, + artifacts, + taskContainer, + services, + global, + androidKotlinCompilation, + manifestFile +), UnitTestCreationConfig, UnitTest { + + override fun <T> onTestedVariant(action: (VariantCreationConfig) -> T): T { + return action.invoke(mainVariant) + } + + override val instrumentationRunner: Provider<String> + get() = services.provider { DEFAULT_TEST_RUNNER } + override val testedApplicationId: Provider<String> + get() = mainVariant.applicationId + override val targetSdkVersion: AndroidVersion + get() = minSdk + + override val manifestPlaceholdersCreationConfig: ManifestPlaceholdersCreationConfig by lazy(LazyThreadSafetyMode.NONE) { + ManifestPlaceholdersCreationConfigImpl( + // no dsl for this + emptyMap(), + internalServices + ) + } + + override val manifestPlaceholders: MapProperty<String, String> + get() = manifestPlaceholdersCreationConfig.placeholders + + override val isUnitTestCoverageEnabled: Boolean + get() = dslInfo.isUnitTestCoverageEnabled + + override fun <ParamT : InstrumentationParameters> transformClassesWith( + classVisitorFactoryImplClass: Class<out AsmClassVisitorFactory<ParamT>>, + scope: InstrumentationScope, + instrumentationParamsConfig: (ParamT) -> Unit + ) { + instrumentation.transformClassesWith( + classVisitorFactoryImplClass, + scope, + instrumentationParamsConfig + ) + } + + override fun setAsmFramesComputationMode(mode: FramesComputationMode) { + instrumentation.setAsmFramesComputationMode(mode) + } +} diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/OldVariantApiLegacySupportImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/OldVariantApiLegacySupportImpl.kt index d834eb1315..c092aedb12 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/OldVariantApiLegacySupportImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/OldVariantApiLegacySupportImpl.kt @@ -347,7 +347,7 @@ class OldVariantApiLegacySupportImpl( component.variantDependencies.compileClasspath.attributes.attribute(attributeKey, attributeValue) component.variantDependencies.runtimeClasspath.attributes.attribute(attributeKey, attributeValue) component.variantDependencies - .annotationProcessorConfiguration + .annotationProcessorConfiguration!! .attributes .attribute(attributeKey, attributeValue) diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/features/DexingCreationConfigImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/features/DexingCreationConfigImpl.kt index 493a420281..8dfe05be5e 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/features/DexingCreationConfigImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/features/DexingCreationConfigImpl.kt @@ -85,7 +85,7 @@ class DexingCreationConfigImpl( DexingType.NATIVE_MULTIDEX } else if (isMultiDexEnabled) { if (component.minSdk.getFeatureLevel() >= 21 || - dslInfo.targetDeployApiFromIDE?.let { it >= 21 } == true + component.global.targetDeployApiFromIDE?.let { it >= 21 } == true ) { // if minSdkVersion is 21+ or we are deploying to 21+ device, use native multidex DexingType.NATIVE_MULTIDEX @@ -167,7 +167,7 @@ class DexingCreationConfigImpl( */ override val minSdkVersionForDexing: AndroidVersion get() { - val targetDeployApiFromIDE = dslInfo.targetDeployApiFromIDE ?: 1 + val targetDeployApiFromIDE = component.global.targetDeployApiFromIDE ?: 1 val minForDexing = if (targetDeployApiFromIDE >= com.android.sdklib.AndroidVersion.VersionCodes.N) { max(24, component.minSdk.getFeatureLevel()) diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/extension/impl/AndroidComponentsExtensionImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/extension/impl/AndroidComponentsExtensionImpl.kt index f8c065f800..3baa665779 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/extension/impl/AndroidComponentsExtensionImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/extension/impl/AndroidComponentsExtensionImpl.kt @@ -29,6 +29,7 @@ import com.android.build.api.variant.VariantBuilder import com.android.build.api.variant.VariantExtension import com.android.build.gradle.internal.services.DslServices import org.gradle.api.Action +import org.gradle.api.plugins.ExtensionAware abstract class AndroidComponentsExtensionImpl< DslExtensionT: CommonExtension<*, *, *, *, *>, @@ -97,9 +98,15 @@ abstract class AndroidComponentsExtensionImpl< configurator = configurator )) + dslExtension.projectExtensionType?.let { + (commonExtension as ExtensionAware).extensions.add( + dslExtension.dslName, + it + ) + } + dslExtension.buildTypeExtensionType?.let { - commonExtension.buildTypes.forEach { - buildType -> + commonExtension.buildTypes.all { buildType -> buildType.extensions.add( dslExtension.dslName, it @@ -107,7 +114,7 @@ abstract class AndroidComponentsExtensionImpl< } } dslExtension.productFlavorExtensionType?.let { - commonExtension.productFlavors.forEach { + commonExtension.productFlavors.all { productFlavor -> productFlavor.extensions.add( dslExtension.dslName, it diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/extension/impl/VariantSelectorImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/extension/impl/VariantSelectorImpl.kt index 589b04f844..a76ea9fbd7 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/extension/impl/VariantSelectorImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/extension/impl/VariantSelectorImpl.kt @@ -45,6 +45,10 @@ open class VariantSelectorImpl : VariantSelector { } } + override fun withFlavor(dimension: String, flavorName: String): VariantSelectorImpl { + return withFlavor(dimension to flavorName) + } + override fun withName(pattern: Pattern): VariantSelectorImpl { return object : VariantSelectorImpl() { override fun appliesTo(variant: ComponentIdentity): Boolean { diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/ApplicationVariantImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/ApplicationVariantImpl.kt index eb0c588206..2ba81d7fef 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/ApplicationVariantImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/ApplicationVariantImpl.kt @@ -90,8 +90,8 @@ open class ApplicationVariantImpl @Inject constructor( override val dependenciesInfo: DependenciesInfo by lazy { DependenciesInfoImpl( - dependenciesInfoBuilder.includedInApk, - dependenciesInfoBuilder.includedInBundle + dependenciesInfoBuilder.includeInApk, + dependenciesInfoBuilder.includeInBundle ) } @@ -108,7 +108,7 @@ open class ApplicationVariantImpl @Inject constructor( dslInfo.signingConfig, internalServices, minSdk.apiLevel, - internalServices.projectOptions.get(IntegerOption.IDE_TARGET_DEVICE_API) + global.targetDeployApiFromIDE ) } diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/DependenciesInfoBuilderImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/DependenciesInfoBuilderImpl.kt index dc8d66de92..da794763ce 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/DependenciesInfoBuilderImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/DependenciesInfoBuilderImpl.kt @@ -23,16 +23,31 @@ import javax.inject.Inject open class DependenciesInfoBuilderImpl @Inject constructor( variantBuilderServices: VariantBuilderServices, - dslDependencyInfo: DependenciesInfo + dslDependencyInfo: DependenciesInfo, ): DependenciesInfoBuilder { + private val includeInApkValue = variantBuilderServices.valueOf(dslDependencyInfo.includeInApk) private val includeInBundleValue = variantBuilderServices.valueOf(dslDependencyInfo.includeInBundle) + @Deprecated( + "This property is renamed to includeInApk", + replaceWith = ReplaceWith("includeInApk") + ) override var includedInApk: Boolean set(value) = includeInApkValue.set(value) get() = includeInApkValue.get() + @Deprecated( + "This property is renamed to includeInBundle", + replaceWith = ReplaceWith("includeInBundle") + ) override var includedInBundle: Boolean set(value) = includeInBundleValue.set(value) get() = includeInBundleValue.get() + override var includeInApk: Boolean + set(value) = includeInApkValue.set(value) + get() = includeInApkValue.get() + override var includeInBundle: Boolean + set(value) = includeInBundleValue.set(value) + get() = includeInBundleValue.get() } diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/KmpVariantImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/KmpVariantImpl.kt index bbb9bc649e..7322b3beff 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/KmpVariantImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/KmpVariantImpl.kt @@ -18,11 +18,16 @@ package com.android.build.api.variant.impl import com.android.SdkConstants.DOT_AAR import com.android.build.api.artifact.impl.ArtifactsImpl +import com.android.build.api.component.impl.KmpAndroidTestImpl import com.android.build.api.component.impl.KmpComponentImpl +import com.android.build.api.component.impl.KmpUnitTestImpl import com.android.build.api.component.impl.features.OptimizationCreationConfigImpl import com.android.build.api.variant.AarMetadata +import com.android.build.api.variant.CanMinifyAndroidResourcesBuilder +import com.android.build.api.variant.CanMinifyCodeBuilder import com.android.build.api.variant.Component import com.android.build.api.variant.Packaging +import com.android.build.gradle.internal.KotlinMultiplatformCompileOptionsImpl import com.android.build.gradle.internal.component.ComponentCreationConfig import com.android.build.gradle.internal.component.KmpCreationConfig import com.android.build.gradle.internal.component.features.NativeBuildCreationConfig @@ -53,7 +58,8 @@ open class KmpVariantImpl @Inject constructor( taskContainer: MutableTaskContainer, services: TaskCreationServices, global: GlobalTaskCreationConfig, - manifestFile: File + androidKotlinCompilation: KotlinMultiplatformAndroidCompilation, + manifestFile: File, ): KmpComponentImpl<KmpVariantDslInfo>( dslInfo, internalServices, @@ -64,7 +70,8 @@ open class KmpVariantImpl @Inject constructor( taskContainer, services, global, - manifestFile + androidKotlinCompilation, + manifestFile, ), KotlinMultiplatformAndroidVariant, KmpCreationConfig { override val aarOutputFileName: Property<String> = @@ -90,15 +97,24 @@ open class KmpVariantImpl @Inject constructor( OptimizationCreationConfigImpl( this, dslInfo.optimizationDslInfo, - null, - null, + object : CanMinifyCodeBuilder { + override var isMinifyEnabled = + dslInfo.optimizationDslInfo.postProcessingOptions.codeShrinkerEnabled() + }, + object : CanMinifyAndroidResourcesBuilder { + override var shrinkResources = + dslInfo.optimizationDslInfo.postProcessingOptions.codeShrinkerEnabled() + }, internalServices ) } - override var unitTest = null + override var unitTest: KmpUnitTestImpl? = null - override var androidTest = null + override var androidTest: KmpAndroidTestImpl? = null + + override val isAndroidTestCoverageEnabled: Boolean + get() = androidTest?.isAndroidTestCoverageEnabled ?: false override val nestedComponents: List<ComponentCreationConfig> get() = listOfNotNull(unitTest, androidTest) @@ -117,6 +133,16 @@ open class KmpVariantImpl @Inject constructor( PackagingImpl(dslInfo.packaging, internalServices) } + override val isCoreLibraryDesugaringEnabledLintCheck: Boolean + get() = global.compileOptions.isCoreLibraryDesugaringEnabled + + override fun syncAndroidAndKmpClasspathAndSources() { + super.syncAndroidAndKmpClasspathAndSources() + + (global.compileOptions as KotlinMultiplatformCompileOptionsImpl) + .initFromCompilation(androidKotlinCompilation) + } + override fun <T : Component> createUserVisibleVariantObject( stats: GradleBuildVariant.Builder? ): T { @@ -128,11 +154,4 @@ open class KmpVariantImpl @Inject constructor( override val renderscriptCreationConfig: RenderscriptCreationConfig? = null override val shadersCreationConfig: ShadersCreationConfig? = null override val nativeBuildCreationConfig: NativeBuildCreationConfig? = null - - // TODO(b/243387425): Figure out coverage - override val isAndroidTestCoverageEnabled: Boolean - get() = false - - override val isCoreLibraryDesugaringEnabledLintCheck: Boolean - get() = false } diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/KotlinMultiplatformAndroidCompilation.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/KotlinMultiplatformAndroidCompilation.kt new file mode 100644 index 0000000000..69d54ec0c5 --- /dev/null +++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/KotlinMultiplatformAndroidCompilation.kt @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2023 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.build.api.variant.impl + +import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions +import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation + +interface KotlinMultiplatformAndroidCompilation: KotlinCompilation<KotlinCommonOptions> { + + override val compilerOptions: HasCompilerOptions<KotlinJvmCompilerOptions> +} diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/KotlinMultiplatformAndroidTarget.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/KotlinMultiplatformAndroidTarget.kt new file mode 100644 index 0000000000..3b988814e0 --- /dev/null +++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/KotlinMultiplatformAndroidTarget.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 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.build.api.variant.impl + +import com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinTarget + +/** + * Temporary interface to develop the kotlin multiplatform android plugin. + * + * TODO(b/267309622): Move to gradle-api + */ +interface KotlinMultiplatformAndroidTarget: KotlinTarget { + val options: KotlinMultiplatformAndroidExtension + + fun options(action: KotlinMultiplatformAndroidExtension.() -> Unit) + + fun onMainCompilation(action: KotlinMultiplatformAndroidCompilation.() -> Unit) + + fun onUnitTestCompilation(action: KotlinMultiplatformAndroidCompilation.() -> Unit) + + fun onInstrumentedTestCompilation(action: KotlinMultiplatformAndroidCompilation.() -> Unit) +} diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/KotlinMultiplatformAndroidVariant.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/KotlinMultiplatformAndroidVariant.kt index 6571b2dffe..0a27213f78 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/KotlinMultiplatformAndroidVariant.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/KotlinMultiplatformAndroidVariant.kt @@ -19,9 +19,9 @@ package com.android.build.api.variant.impl import com.android.build.api.artifact.Artifacts import com.android.build.api.variant.GeneratesAar import com.android.build.api.variant.HasAndroidTest +import com.android.build.api.variant.HasUnitTest import com.android.build.api.variant.Instrumentation import com.android.build.api.variant.Sources -import com.android.build.api.variant.UnitTest import org.gradle.api.artifacts.Configuration import org.gradle.api.file.FileCollection import org.gradle.api.provider.Provider @@ -31,7 +31,10 @@ import org.gradle.api.provider.Provider * * TODO(b/267309622): Move to gradle-api */ -interface KotlinMultiplatformAndroidVariant: GeneratesAar, HasAndroidTest { +interface KotlinMultiplatformAndroidVariant: GeneratesAar, + HasAndroidTest, + HasUnitTest { + val namespace: Provider<String> val name: String @@ -73,9 +76,4 @@ interface KotlinMultiplatformAndroidVariant: GeneratesAar, HasAndroidTest { * The returned [Configuration] should not be resolved until execution time. */ val runtimeConfiguration: Configuration - - /** - * Variant's [UnitTest], or null if the unit tests for this variant are disabled. - */ - val unitTest: UnitTest? } diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/SourceDirectoriesImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/SourceDirectoriesImpl.kt index da82c3a108..b1b18e8aab 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/SourceDirectoriesImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/SourceDirectoriesImpl.kt @@ -70,7 +70,7 @@ abstract class SourceDirectoriesImpl( override fun addStaticSourceDirectory(srcDir: String) { val directory = variantServices.projectInfo.projectDirectory.dir(srcDir) - if (!directory.asFile.exists() || !directory.asFile.isDirectory) { + if (directory.asFile.exists() && !directory.asFile.isDirectory) { throw IllegalArgumentException("$srcDir does not point to a directory") } addSource( diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/TestVariantImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/TestVariantImpl.kt index 14bf425edb..cf2154bdd0 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/TestVariantImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/TestVariantImpl.kt @@ -169,7 +169,7 @@ open class TestVariantImpl @Inject constructor( it, internalServices, minSdk.apiLevel, - services.projectOptions.get(IntegerOption.IDE_TARGET_DEVICE_API) + global.targetDeployApiFromIDE ) } } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/AndroidTestTaskManager.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/AndroidTestTaskManager.kt index 01741f23d3..d91c0427c9 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/AndroidTestTaskManager.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/AndroidTestTaskManager.kt @@ -20,6 +20,7 @@ import com.android.build.api.artifact.SingleArtifact import com.android.build.api.artifact.impl.InternalScopedArtifacts import com.android.build.gradle.internal.component.AndroidTestCreationConfig import com.android.build.gradle.internal.component.ComponentCreationConfig +import com.android.build.gradle.internal.component.KmpComponentCreationConfig import com.android.build.gradle.internal.coverage.JacocoConfigurations import com.android.build.gradle.internal.coverage.JacocoReportTask import com.android.build.gradle.internal.dependency.VariantDependencies @@ -183,8 +184,10 @@ class AndroidTestTaskManager( // Add data binding tasks if enabled createDataBindingTasksIfNecessary(androidTestProperties) - // Add a task to compile the test application - setJavaCompilerTask(createJavacTask(androidTestProperties), androidTestProperties) + if (androidTestProperties !is KmpComponentCreationConfig) { + // Add a task to compile the test application + setJavaCompilerTask(createJavacTask(androidTestProperties), androidTestProperties) + } createPostCompilationTasks(androidTestProperties) // Add tasks to produce the signing config files @@ -412,8 +415,7 @@ class AndroidTestTaskManager( override val javaResMergingScopes = setOf( InternalScopedArtifacts.InternalScope.SUB_PROJECTS, - InternalScopedArtifacts.InternalScope.EXTERNAL_LIBS, - InternalScopedArtifacts.InternalScope.LOCAL_DEPS, + InternalScopedArtifacts.InternalScope.EXTERNAL_LIBS ) override fun createVariantPreBuildTask(creationConfig: ComponentCreationConfig) { diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/CompileOptions.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/CompileOptions.kt index 65408e0120..7889b090e7 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/CompileOptions.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/CompileOptions.kt @@ -57,8 +57,8 @@ abstract class CompileOptions : CompileOptions { override var encoding: String = Charsets.UTF_8.name() override var isCoreLibraryDesugaringEnabled: Boolean = false - private var _sourceCompatibility: JavaVersion? = null - private var _targetCompatibility: JavaVersion? = null + protected var _sourceCompatibility: JavaVersion? = null + protected var _targetCompatibility: JavaVersion? = null private var sourceAndTargetFinalized: Boolean = false diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/DependencyConfigurator.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/DependencyConfigurator.kt index 53f903a230..8bfe409402 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/DependencyConfigurator.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/DependencyConfigurator.kt @@ -92,6 +92,7 @@ import org.gradle.api.ActionConfiguration import org.gradle.api.Project import org.gradle.api.artifacts.ArtifactView import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.Dependency import org.gradle.api.artifacts.dsl.DependencyHandler import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformSpec @@ -502,24 +503,30 @@ class DependencyConfigurator( { reg: TransformSpec<ExtractSdkShimTransform.Parameters> -> val experimentalProperties = variant.experimentalProperties experimentalProperties.finalizeValue() - val apigeneratorArtifact = - ModuleStringPropertyKeys.ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR - .getValueAsString(experimentalProperties.get()) - ?: projectServices.projectOptions - .get(StringOption.ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR) - ?: "androidx.privacysandbox.tools:tools-apigenerator:1.0.0-alpha02" - val runtimeDependenciesForShimSdk = - (ModuleStringPropertyKeys.ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR_GENERATED_RUNTIME_DEPENDENCIES - .getValueAsString(experimentalProperties.get()) - ?: projectServices.projectOptions - .get(StringOption.ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR_GENERATED_RUNTIME_DEPENDENCIES)) - ?.split(",") - ?: listOf("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1") + + val experimentalPropertiesApiGenerator = + experimentalProperties.get()[ModuleStringPropertyKeys.ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR.keyValue] as Dependency? + val apigeneratorArtifact: Dependency = + experimentalPropertiesApiGenerator + ?: project.dependencies.create( + projectServices.projectOptions.get(StringOption.ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR) + ?: "androidx.privacysandbox.tools:tools-apigenerator:1.0.0-alpha02" + ) as Dependency + + val experimentalPropertiesRuntimeApigeneratorDependencies = + experimentalProperties.get()[ModuleStringPropertyKeys.ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR_GENERATED_RUNTIME_DEPENDENCIES.keyValue] as ArrayList<Dependency>? + val runtimeDependenciesForShimSdk: List<Dependency> = + experimentalPropertiesRuntimeApigeneratorDependencies + ?: (projectServices.projectOptions + .get(StringOption.ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR_GENERATED_RUNTIME_DEPENDENCIES) + ?.split(",") + ?: listOf("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1")).map { + project.dependencies.create(it) + } val params = reg.parameters val apiGeneratorConfiguration = - project.configurations.detachedConfiguration( - project.dependencies.create(apigeneratorArtifact)) + project.configurations.detachedConfiguration(apigeneratorArtifact) apiGeneratorConfiguration.isCanBeConsumed = false apiGeneratorConfiguration.isCanBeResolved = true params.apiGenerator.setFrom(apiGeneratorConfiguration) @@ -540,9 +547,7 @@ class DependencyConfigurator( params.requireServices.set( projectServices.projectOptions[BooleanOption.PRIVACY_SANDBOX_SDK_REQUIRE_SERVICES]) val configuration = project.configurations.detachedConfiguration( - *runtimeDependenciesForShimSdk.map { - project.dependencies.create(it) - }.toTypedArray()) + *runtimeDependenciesForShimSdk.toTypedArray()) configuration.isCanBeConsumed = false configuration.isCanBeResolved = true params.runtimeDependencies.from(configuration.incoming.artifactView { config: ArtifactView.ViewConfiguration -> diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/KotlinMultiplatformCompileOptionsImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/KotlinMultiplatformCompileOptionsImpl.kt new file mode 100644 index 0000000000..8acf83ff48 --- /dev/null +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/KotlinMultiplatformCompileOptionsImpl.kt @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2023 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.build.gradle.internal + +import com.android.build.api.variant.impl.KotlinMultiplatformAndroidCompilation +import com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension +import org.gradle.api.JavaVersion + +/** + * Implementation of [CompileOptions] that is based on kotlin multiplatform APIs for internal use. + */ +internal class KotlinMultiplatformCompileOptionsImpl( + private val extension: KotlinMultiplatformAndroidExtension +): CompileOptions() { + + override var isCoreLibraryDesugaringEnabled + get() = extension.isCoreLibraryDesugaringEnabled + set(_) { + throw IllegalAccessException("Compile options for kmp variants are read only.") + } + + override var targetCompatibility: JavaVersion + get() = super.targetCompatibility + set(_) { + throw IllegalAccessException("Compile options for kmp variants are read only.") + } + + override var sourceCompatibility: JavaVersion + get() = super.sourceCompatibility + set(_) { + throw IllegalAccessException("Compile options for kmp variants are read only.") + } + + override var encoding: String + get() = super.encoding + set(_) { + throw IllegalAccessException("Compile options for kmp variants are read only.") + } + + override fun sourceCompatibility(sourceCompatibility: Any) { + throw IllegalAccessException("Compile options for kmp variants are read only.") + } + + override fun targetCompatibility(targetCompatibility: Any) { + throw IllegalAccessException("Compile options for kmp variants are read only.") + } + + fun initFromCompilation( + compilation: KotlinMultiplatformAndroidCompilation + ) { + compilation.compilerOptions.options.jvmTarget.orNull?.let { + _targetCompatibility = JavaVersion.toVersion(it.target) + _sourceCompatibility = JavaVersion.toVersion(it.target) + } + } +} diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/LibraryTaskManager.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/LibraryTaskManager.kt index d984e6c7fb..d95f9daebb 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/LibraryTaskManager.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/LibraryTaskManager.kt @@ -194,6 +194,15 @@ class LibraryTaskManager( ) { taskFactory.register(ExtractAnnotations.CreationAction(libraryVariant)) } + + // No jacoco transformation for library variants, however, we need to publish the classes + // pre transformation as the artifact is used in the jacoco report task. + libraryVariant.artifacts.forScope(ScopedArtifacts.Scope.PROJECT) + .publishCurrent( + ScopedArtifact.CLASSES, + InternalScopedArtifact.PRE_JACOCO_TRANSFORMED_CLASSES, + ) + val instrumented = libraryVariant.isAndroidTestCoverageEnabled maybeCreateTransformClassesWithAsmTask(libraryVariant) @@ -358,20 +367,6 @@ class LibraryTaskManager( } } - override fun createDependencyStreams(creationConfig: ComponentCreationConfig) { - super.createDependencyStreams(creationConfig) - - // add the same jars twice in the same stream as the EXTERNAL_LIB in the task manager - // so that filtering of duplicates in proguard can work. - creationConfig - .artifacts - .forScope(InternalScopedArtifacts.InternalScope.LOCAL_DEPS) - .setInitialContent( - ScopedArtifact.CLASSES, - creationConfig.computeLocalPackagedJars() - ) - } - private class MergeResourceCallback(private val variant: LibraryCreationConfig) : TaskProviderCallback<MergeResources> { override fun handleProvider(taskProvider: TaskProvider<MergeResources>) { diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/SdkComponents.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/SdkComponents.kt index 797e09638a..af1ab39e17 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/SdkComponents.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/SdkComponents.kt @@ -242,6 +242,14 @@ abstract class SdkComponentsBuildService @Inject constructor( sdkLoadStrategy.getOptionalLibraries() } + val aidlExecutableProvider: Provider<RegularFile> = objectFactory.fileProperty().fileProvider( + providerFactory.provider { sdkLoadStrategy.getAidlExecutable() } + ) + + val aidlFrameworkProvider: Provider<RegularFile> = objectFactory.fileProperty().fileProvider( + providerFactory.provider { sdkLoadStrategy.getAidlFramework() } + ) + /** * The API versions file from the platform being compiled against. * diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/TaskManager.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/TaskManager.kt index 934f94bbc4..374132d0d4 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/TaskManager.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/TaskManager.kt @@ -34,6 +34,7 @@ import com.android.build.gradle.internal.component.ApplicationCreationConfig import com.android.build.gradle.internal.component.ComponentCreationConfig import com.android.build.gradle.internal.component.ConsumableCreationConfig import com.android.build.gradle.internal.component.InstrumentedTestCreationConfig +import com.android.build.gradle.internal.component.KmpComponentCreationConfig import com.android.build.gradle.internal.component.TestComponentCreationConfig import com.android.build.gradle.internal.component.TestCreationConfig import com.android.build.gradle.internal.component.VariantCreationConfig @@ -301,6 +302,14 @@ abstract class TaskManager( ) ) + creationConfig + .artifacts + .forScope(InternalScopedArtifacts.InternalScope.LOCAL_DEPS) + .setInitialContent( + ScopedArtifact.CLASSES, + creationConfig.computeLocalPackagedJars() + ) + // Add stream of external java resources if EXTERNAL_LIBRARIES isn't in the set of java res // merging scopes. if (!javaResMergingScopes.contains(InternalScopedArtifacts.InternalScope.EXTERNAL_LIBS)) { @@ -1087,7 +1096,9 @@ abstract class TaskManager( * like proguard and jacoco */ protected fun createPostCompilationTasks(creationConfig: ApkCreationConfig) { - Preconditions.checkNotNull(creationConfig.taskContainer.javacTask) + if (creationConfig !is KmpComponentCreationConfig) { + Preconditions.checkNotNull(creationConfig.taskContainer.javacTask) + } taskFactory.register(MergeGeneratedProguardFilesCreationAction(creationConfig)) // Merge Java Resources. @@ -1531,7 +1542,9 @@ abstract class TaskManager( null, object : TaskConfigAction<PackageApplication> { override fun configure(task: PackageApplication) { - task.dependsOn(taskContainer.javacTask) + if (creationConfig !is KmpComponentCreationConfig) { + task.dependsOn(taskContainer.javacTask) + } if (taskContainer.packageSplitResourcesTask != null) { task.dependsOn(taskContainer.packageSplitResourcesTask) } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/VariantManager.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/VariantManager.kt index 7aaea9e9e5..c76a00427a 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/VariantManager.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/VariantManager.kt @@ -408,6 +408,7 @@ class VariantManager< .setUpSourceSet( computeSourceSetName(dslInfoBuilder.name, componentType), componentType.isTestComponent) as DefaultAndroidSourceSet + addExtraSourceSets(variantSourceSet) dslInfoBuilder.variantSourceProvider = variantSourceSet } if (productFlavorList.size > 1) { @@ -417,10 +418,17 @@ class VariantManager< computeSourceSetName(dslInfoBuilder.flavorName, componentType), componentType.isTestComponent) as DefaultAndroidSourceSet + addExtraSourceSets(multiFlavorSourceSet) dslInfoBuilder.multiFlavorSourceProvider = multiFlavorSourceSet } } + private fun addExtraSourceSets(sourceSet: DefaultAndroidSourceSet) { + variantApiOperationsRegistrar.onEachSourceSetExtensions { name: String -> + sourceSet.extras.create(name) + } + } + /** Create a test fixtures component for the specified main component. */ private fun createTestFixturesComponent( dimensionCombination: DimensionCombination, diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/KmpComponentCreationConfig.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/KmpComponentCreationConfig.kt index 2269c97d3a..15fc19794f 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/KmpComponentCreationConfig.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/KmpComponentCreationConfig.kt @@ -16,8 +16,12 @@ package com.android.build.gradle.internal.component +import com.android.build.api.variant.impl.KotlinMultiplatformAndroidCompilation + /** * Interface for all components related to the kotlin multiplatform plugin including the main * variant, unit tests, and instrumented tests. */ -interface KmpComponentCreationConfig: ComponentCreationConfig +interface KmpComponentCreationConfig: ComponentCreationConfig { + val androidKotlinCompilation: KotlinMultiplatformAndroidCompilation +} diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/features/DexingDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/features/DexingDslInfo.kt index 20a82a1816..3068f65ef0 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/features/DexingDslInfo.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/features/DexingDslInfo.kt @@ -29,12 +29,4 @@ interface DexingDslInfo { val multiDexKeepProguard: File? val multiDexKeepFile: File? - - /** - * Returns the API to which device/emulator we're deploying via the IDE or null if not. - * Can be used to optimize some build steps when deploying via the IDE. - * - * This has no relation with targetSdkVersion from build.gradle/manifest. - */ - val targetDeployApiFromIDE: Int? } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/AndroidTestComponentDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/AndroidTestComponentDslInfoImpl.kt index 1fae29ee85..643b32d81b 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/AndroidTestComponentDslInfoImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/AndroidTestComponentDslInfoImpl.kt @@ -116,7 +116,7 @@ internal class AndroidTestComponentDslInfoImpl( override val dexingDslInfo: DexingDslInfo by lazy { DexingDslInfoImpl( - buildTypeObj, mergedFlavor, services + buildTypeObj, mergedFlavor ) } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ApplicationVariantDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ApplicationVariantDslInfoImpl.kt index c025be655c..df9013ef4f 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ApplicationVariantDslInfoImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ApplicationVariantDslInfoImpl.kt @@ -174,7 +174,7 @@ internal class ApplicationVariantDslInfoImpl( override val dexingDslInfo: DexingDslInfo by lazy { DexingDslInfoImpl( - buildTypeObj, mergedFlavor, services + buildTypeObj, mergedFlavor ) } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DynamicFeatureVariantDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DynamicFeatureVariantDslInfoImpl.kt index e1fe2946a8..6890d065be 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DynamicFeatureVariantDslInfoImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DynamicFeatureVariantDslInfoImpl.kt @@ -71,7 +71,7 @@ internal class DynamicFeatureVariantDslInfoImpl( override val dexingDslInfo: DexingDslInfo by lazy { DexingDslInfoImpl( - buildTypeObj, mergedFlavor, services + buildTypeObj, mergedFlavor ) } } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/KmpAndroidTestDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/KmpAndroidTestDslInfoImpl.kt new file mode 100644 index 0000000000..521a5e0882 --- /dev/null +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/KmpAndroidTestDslInfoImpl.kt @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2022 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.build.gradle.internal.core.dsl.impl + +import com.android.build.api.component.impl.ComponentIdentityImpl +import com.android.build.api.variant.ResValue +import com.android.build.gradle.internal.core.dsl.AndroidTestComponentDslInfo +import com.android.build.gradle.internal.core.dsl.KmpComponentDslInfo +import com.android.build.gradle.internal.core.dsl.KmpVariantDslInfo +import com.android.build.gradle.internal.core.dsl.features.AndroidResourcesDslInfo +import com.android.build.gradle.internal.core.dsl.features.BuildConfigDslInfo +import com.android.build.gradle.internal.core.dsl.features.DexingDslInfo +import com.android.build.gradle.internal.core.dsl.features.ManifestPlaceholdersDslInfo +import com.android.build.gradle.internal.core.dsl.features.OptimizationDslInfo +import com.android.build.gradle.internal.core.dsl.features.RenderscriptDslInfo +import com.android.build.gradle.internal.core.dsl.features.ShadersDslInfo +import com.android.build.gradle.internal.dsl.AaptOptions +import com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension +import com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtensionImpl +import com.android.build.gradle.internal.dsl.SigningConfig +import com.android.build.gradle.internal.manifest.ManifestDataProvider +import com.android.build.gradle.internal.services.DslServices +import com.android.build.gradle.internal.services.VariantServices +import com.android.builder.core.ComponentTypeImpl +import com.android.builder.core.DefaultVectorDrawablesOptions +import com.android.builder.dexing.DexingType +import com.android.builder.dexing.isLegacyMultiDexMode +import com.android.builder.model.VectorDrawablesOptions +import com.google.common.collect.ImmutableSet +import org.gradle.api.provider.Provider +import java.io.File + +class KmpAndroidTestDslInfoImpl( + extension: KotlinMultiplatformAndroidExtension, + services: VariantServices, + private val dataProvider: ManifestDataProvider, + override val mainVariantDslInfo: KmpVariantDslInfo, + signingConfigOverride: SigningConfig?, + dslServices: DslServices +): KmpComponentDslInfoImpl( + extension, services +), AndroidTestComponentDslInfo, KmpComponentDslInfo { + + override val componentType = ComponentTypeImpl.ANDROID_TEST + override val componentIdentity = ComponentIdentityImpl("kotlinAndroidInstrumentedTest") + + override val namespace: Provider<String> by lazy { + extension.testNamespace?.let { services.provider { it } } + ?: extension.namespace?.let { services.provider {"$it.test" } } + ?: mainVariantDslInfo.namespace.map { testedVariantNamespace -> + "$testedVariantNamespace.test" + } + } + + val targetSdkVersion + get() = (extension as KotlinMultiplatformAndroidExtensionImpl).testTargetSdkVersion + + override val isDebuggable: Boolean + get() = true + override val signingConfig: SigningConfig by lazy { + val dslSigningConfig = + (extension as KotlinMultiplatformAndroidExtensionImpl).signingConfig + signingConfigOverride?.let { + // use enableV1 and enableV2 from the DSL if the override values are null + if (it.enableV1Signing == null) { + it.enableV1Signing = dslSigningConfig.enableV1Signing + } + if (it.enableV2Signing == null) { + it.enableV2Signing = dslSigningConfig.enableV2Signing + } + // use enableV3 and enableV4 from the DSL because they're not injectable + it.enableV3Signing = dslSigningConfig.enableV3Signing + it.enableV4Signing = dslSigningConfig.enableV4Signing + it + } ?: dslSigningConfig + } + override val isSigningReady: Boolean + get() = signingConfig.isSigningReady + + override val androidResourcesDsl = object: AndroidResourcesDslInfo { + override val androidResources = dslServices.newDecoratedInstance( + AaptOptions::class.java, + dslServices + ) + override val resourceConfigurations: ImmutableSet<String> = ImmutableSet.of() + override val vectorDrawables: VectorDrawablesOptions = DefaultVectorDrawablesOptions() + override val isPseudoLocalesEnabled: Boolean = false + override val isCrunchPngs: Boolean = false + override val isCrunchPngsDefault: Boolean = false + + override fun getResValues(): Map<ResValue.Key, ResValue> { + return emptyMap() + } + } + override val optimizationDslInfo: OptimizationDslInfo + get() = mainVariantDslInfo.optimizationDslInfo + override val dexingDslInfo = object: DexingDslInfo { + override val isMultiDexEnabled = extension.isTestMultiDexEnabled + override val multiDexKeepProguard: File? = extension.testMultiDexKeepProguard + override val multiDexKeepFile: File? = null + } + + override val isAndroidTestCoverageEnabled: Boolean + get() = extension.enableInstrumentedTestCoverage + + override fun getInstrumentationRunner(dexingType: DexingType): Provider<String> { + // first check whether the DSL has the info + return extension.testInstrumentationRunner?.let { + services.provider { it } + } // else return the value from the Manifest + ?: dataProvider.manifestData.map { + it.instrumentationRunner + ?: if (dexingType.isLegacyMultiDexMode()) { + MULTIDEX_TEST_RUNNER + } else { + DEFAULT_TEST_RUNNER + } + } + } + + override val instrumentationRunnerArguments: Map<String, String> + get() = extension.testInstrumentationRunnerArguments + override val handleProfiling: Provider<Boolean> + get() = + // first check whether the DSL has the info + extension.testHandleProfiling?.let { + services.provider { it } + } // else return the value from the Manifest + ?: dataProvider.manifestData.map { it.handleProfiling ?: DEFAULT_HANDLE_PROFILING } + + override val functionalTest: Provider<Boolean> + get() = + // first check whether the DSL has the info + extension.testFunctionalTest?.let { + services.provider { it } + } // else return the value from the Manifest + ?: dataProvider.manifestData.map { it.functionalTest ?: DEFAULT_FUNCTIONAL_TEST } + + override val testLabel: Provider<String?> + get() { + // there is actually no DSL value for this. + return dataProvider.manifestData.map { it.testLabel } + } + + // Unsupported features + // TODO(b/243387425): Figure out if we should have a full instrumented test component similar + // to libs + override val shadersDslInfo: ShadersDslInfo? = null + override val buildConfigDslInfo: BuildConfigDslInfo? = null + override val renderscriptDslInfo: RenderscriptDslInfo? = null + override val manifestPlaceholdersDslInfo: ManifestPlaceholdersDslInfo? = null +} diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/KmpUnitTestDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/KmpUnitTestDslInfoImpl.kt new file mode 100644 index 0000000000..96d7d48e8f --- /dev/null +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/KmpUnitTestDslInfoImpl.kt @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 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.build.gradle.internal.core.dsl.impl + +import com.android.build.api.component.impl.ComponentIdentityImpl +import com.android.build.gradle.internal.core.dsl.KmpComponentDslInfo +import com.android.build.gradle.internal.core.dsl.KmpVariantDslInfo +import com.android.build.gradle.internal.core.dsl.UnitTestComponentDslInfo +import com.android.build.gradle.internal.core.dsl.features.ManifestPlaceholdersDslInfo +import com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension +import com.android.build.gradle.internal.services.VariantServices +import com.android.builder.core.ComponentTypeImpl +import org.gradle.api.provider.Provider + +class KmpUnitTestDslInfoImpl( + extension: KotlinMultiplatformAndroidExtension, + services: VariantServices, + override val mainVariantDslInfo: KmpVariantDslInfo +): KmpComponentDslInfoImpl( + extension, services +), UnitTestComponentDslInfo, KmpComponentDslInfo { + + override val componentType = ComponentTypeImpl.UNIT_TEST + override val componentIdentity = ComponentIdentityImpl("kotlinAndroidTest") + + override val namespace: Provider<String> by lazy { + extension.testNamespace?.let { services.provider { it } } + ?: extension.namespace?.let { services.provider {"$it.test" } } + ?: mainVariantDslInfo.namespace.map { testedVariantNamespace -> + "$testedVariantNamespace.test" + } + } + + override val isUnitTestCoverageEnabled: Boolean + get() = extension.enableUnitTestCoverage +} diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/KmpVariantDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/KmpVariantDslInfoImpl.kt index 2ff6a2f5f0..64817e4a4c 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/KmpVariantDslInfoImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/KmpVariantDslInfoImpl.kt @@ -146,13 +146,7 @@ class KmpVariantDslInfoImpl( ) ) - override fun getPostprocessingFeatures(): PostprocessingFeatures { - return PostprocessingFeatures( - isRemoveUnusedCode = extension.isMinifyEnabled, - isObfuscate = extension.isMinifyEnabled, - isOptimize = extension.isMinifyEnabled - ) - } + override fun getPostprocessingFeatures(): PostprocessingFeatures? = null override fun codeShrinkerEnabled(): Boolean = extension.isMinifyEnabled diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestProjectVariantDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestProjectVariantDslInfoImpl.kt index 5d1c7ef675..aaaaae7583 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestProjectVariantDslInfoImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestProjectVariantDslInfoImpl.kt @@ -30,10 +30,8 @@ import com.android.build.gradle.internal.manifest.ManifestDataProvider import com.android.build.gradle.internal.profile.ProfilingMode import com.android.build.gradle.internal.services.VariantServices import com.android.build.gradle.options.StringOption -import com.android.build.gradle.options.Version import com.android.builder.core.ComponentType import com.android.builder.dexing.DexingType -import com.android.builder.errors.IssueReporter import org.gradle.api.file.DirectoryProperty import org.gradle.api.provider.Property import org.gradle.api.provider.Provider @@ -118,7 +116,7 @@ internal class TestProjectVariantDslInfoImpl( override val dexingDslInfo: DexingDslInfo by lazy { DexingDslInfoImpl( - buildTypeObj, mergedFlavor, services + buildTypeObj, mergedFlavor ) } } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/VariantDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/VariantDslInfoImpl.kt index 0b5b6a84f4..0bd9546177 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/VariantDslInfoImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/VariantDslInfoImpl.kt @@ -75,17 +75,14 @@ internal abstract class VariantDslInfoImpl internal constructor( override val namespace: Provider<String> get() = extension.namespace?.let { services.provider { it } } ?: throw RuntimeException( - "Namespace not specified. Please specify a namespace in the module's " + - "build.gradle file like so:\n\n" + - "android {\n" + - " namespace 'com.example.namespace'\n" + - "}\n\n" + - "If the package attribute is specified in the source " + - "AndroidManifest.xml, it can be migrated automatically to the namespace " + - "value in the build.gradle file using the AGP Upgrade Assistant; please " + - "refer to " + - "https://developer.android.com/studio/build/agp-upgrade-assistant for " + - "more information." + "Namespace not specified. Specify a namespace in the module's build file. " + + "See https://d.android.com/r/tools/upgrade-assistant/set-namespace for " + + "information about setting the namespace.\n\n" + + "If you've specified the package attribute in the source " + + "AndroidManifest.xml, you can use the AGP Upgrade Assistant to migrate " + + "to the namespace value in the build file. Refer to " + + "https://d.android.com/r/tools/upgrade-assistant/agp-upgrade-assistant " + + "for general information about using the AGP Upgrade Assistant." ) override val applicationId: Property<String> by lazy { diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/features/DexingDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/features/DexingDslInfoImpl.kt index f8c82beef6..7b3aa9f59c 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/features/DexingDslInfoImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/features/DexingDslInfoImpl.kt @@ -20,14 +20,11 @@ import com.android.build.api.dsl.ApplicationBuildType import com.android.build.api.dsl.BuildType import com.android.build.gradle.internal.core.MergedFlavor import com.android.build.gradle.internal.core.dsl.features.DexingDslInfo -import com.android.build.gradle.internal.services.BaseServices -import com.android.build.gradle.options.IntegerOption import java.io.File class DexingDslInfoImpl( private val buildTypeObj: BuildType, - private val mergedFlavor: MergedFlavor, - private val services: BaseServices + private val mergedFlavor: MergedFlavor ): DexingDslInfo { // Only require specific multidex opt-in for legacy multidex. @@ -55,8 +52,4 @@ class DexingDslInfoImpl( value = mergedFlavor.multiDexKeepFile return value } - - // TODO: move to global scope - override val targetDeployApiFromIDE: Int? = - services.projectOptions.get(IntegerOption.IDE_TARGET_DEVICE_API) } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/coverage/JacocoReportTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/coverage/JacocoReportTask.kt index d428d21617..e566556c31 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/coverage/JacocoReportTask.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/coverage/JacocoReportTask.kt @@ -103,7 +103,7 @@ abstract class JacocoReportTask : NonIncrementalTask() { @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) - abstract val javaSources: ListProperty<Provider<List<ConfigurableFileTree>>> + abstract val sources: ListProperty<Provider<List<ConfigurableFileTree>>> @get:Internal abstract val tabWidth: Property<Int> @@ -132,9 +132,9 @@ abstract class JacocoReportTask : NonIncrementalTask() { // Jacoco requires source set directory roots rather than source files to produce // source code highlighting in reports. - val sourceFolders: List<File> = javaSources.get().map { + val sourceFolders: List<File> = sources.get().map { it.get().map(ConfigurableFileTree::getDir) - }.flatten() + }.flatten().distinctBy { it.absolutePath } workerExecutor .classLoaderIsolation { classpath: ClassLoaderWorkerSpec -> @@ -181,9 +181,12 @@ abstract class JacocoReportTask : NonIncrementalTask() { task.reportName.setDisallowChanges(creationConfig.mainVariant.name) task.tabWidth.setDisallowChanges(4) creationConfig.mainVariant.sources.java { javaSources -> - task.javaSources.set(javaSources.getAsFileTrees()) + task.sources.addAll(javaSources.getAsFileTrees()) } - task.javaSources.disallowChanges() + creationConfig.mainVariant.sources.kotlin { kotlinSources -> + task.sources.addAll(kotlinSources.getAsFileTrees()) + } + task.sources.disallowChanges() task.classFileCollection.fromDisallowChanges( creationConfig.mainVariant.artifacts .forScope(ScopedArtifacts.Scope.PROJECT) diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/DexingTransform.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/DexingTransform.kt index cd5e6841fc..7f38dd2370 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/DexingTransform.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/DexingTransform.kt @@ -42,18 +42,17 @@ import com.android.builder.files.SerializableFileChanges import com.android.sdklib.AndroidVersion import com.android.utils.FileUtils import com.google.common.io.Closer -import com.google.common.io.Files import org.gradle.api.artifacts.dsl.DependencyHandler import org.gradle.api.artifacts.transform.CacheableTransform import org.gradle.api.artifacts.transform.InputArtifact import org.gradle.api.artifacts.transform.InputArtifactDependencies import org.gradle.api.artifacts.transform.TransformAction import org.gradle.api.artifacts.transform.TransformOutputs +import org.gradle.api.artifacts.type.ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE import org.gradle.api.attributes.Attribute import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.FileCollection import org.gradle.api.file.FileSystemLocation -import org.gradle.api.internal.artifacts.ArtifactAttributes.ARTIFACT_FORMAT import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.Classpath @@ -61,12 +60,10 @@ import org.gradle.api.tasks.CompileClasspath import org.gradle.api.tasks.Input import org.gradle.api.tasks.Internal import org.gradle.api.tasks.Optional -import org.gradle.work.FileChange import org.gradle.work.Incremental import org.gradle.work.InputChanges import org.slf4j.LoggerFactory import java.io.File -import java.nio.file.Path import javax.inject.Inject @CacheableTransform @@ -94,213 +91,178 @@ abstract class BaseDexingTransform<T : BaseDexingTransform.Parameters> : Transfo abstract val inputChanges: InputChanges @get:Classpath - @get:InputArtifact @get:Incremental - abstract val primaryInput: Provider<FileSystemLocation> + @get:InputArtifact + abstract val inputArtifact: Provider<FileSystemLocation> - protected abstract fun computeClasspathFiles(): List<Path> + /** Classpath used for dexing/desugaring, or null if it is not required. */ + protected abstract fun computeClasspathFiles(): List<File>? override fun transform(outputs: TransformOutputs) { //TODO(b/162813654) record transform execution span - val input = primaryInput.get().asFile - val outputDir = outputs.dir(Files.getNameWithoutExtension(input.name)) - doTransform(input, outputDir) - } - - private fun doTransform(inputFile: File, outputDir: File) { - val provideIncrementalSupport = !isJarFile(inputFile) - - val dexOutputDir = if (parameters.enableGlobalSynthetics.get()) { - outputDir.resolve(computeDexDirName(outputDir)) + val inputDirOrJar = inputArtifact.get().asFile.also { + check(it.isDirectory || isJarFile(it)) { + "Expected directory or jar but found: ${it.path}" + } + } + val classpath = computeClasspathFiles() + val outputDir = outputs.dir(inputDirOrJar.nameWithoutExtension) + + // Currently we are able to run incrementally only if + // - The input artifact is a directory (not jar). + // - Dexing/desugaring does not require a classpath. + // This is because the desugaring graph that is used for incremental dexing needs to be + // relocatable, which requires that all files in the graph share one single root directory + // so that they can be converted to relative paths (see `DesugarGraph`'s kdoc). + val provideIncrementalSupport = inputDirOrJar.isDirectory && classpath == null + + val (dexOutputDir, globalSyntheticsOutputDir) = if (parameters.enableGlobalSynthetics.get()) { + Pair( + outputDir.resolve(computeDexDirName(outputDir)), + outputDir.resolve(computeGlobalSyntheticsDirName(outputDir)) + ) } else { - outputDir + Pair(outputDir, null) } - val globalSyntheticsDir = if (parameters.enableGlobalSynthetics.get()) { - outputDir.resolve(computeGlobalSyntheticsDirName(outputDir)) + val desugarGraphOutputFile = if (provideIncrementalSupport) { + outputDir.resolve(DESUGAR_GRAPH_FILE_NAME) } else null - // desugarGraphFile != null iff provideIncrementalSupport == true - val desugarGraphFile = - if (provideIncrementalSupport) { - // The desugaring graph file is outside outputDir and is not registered as an - // output because the graph is not relocatable. - outputDir.resolve("../$DESUGAR_GRAPH_FILE_NAME") - } else null - if (provideIncrementalSupport && inputChanges.isIncremental) { - // Gradle API currently does not provide classpath changes. When the classpath changes, - // Gradle will run the transform non-incrementally in a new directory, so it is still - // correct, but not quite efficient yet. - // TODO(132615827): Update this code once Gradle provides classpath changes - // (https://github.com/gradle/gradle/issues/11794) - val classpathChanges = emptyList<FileChange>() + logger.verbose("Running dexing transform incrementally for '${inputDirOrJar.path}'") processIncrementally( - inputFile, - inputChanges.getFileChanges(primaryInput).toSerializable(), - classpathChanges.toSerializable(), + // Must be a directory (see the definition of `provideIncrementalSupport`) + inputDir = inputDirOrJar, + // `inputChanges` contains changes to the input artifact only, changes to the + // classpath are not available (https://github.com/gradle/gradle/issues/11794) + inputDirChanges = inputChanges.getFileChanges(inputArtifact).toSerializable(), dexOutputDir, - globalSyntheticsDir, - desugarGraphFile!! + globalSyntheticsOutputDir, + desugarGraphOutputFile!! ) } else { + logger.verbose("Running dexing transform non-incrementally for '${inputDirOrJar.path}'") processNonIncrementally( - inputFile, + inputDirOrJar, + classpath, dexOutputDir, - globalSyntheticsDir, + globalSyntheticsOutputDir, provideIncrementalSupport, - desugarGraphFile + desugarGraphOutputFile ) } } private fun processIncrementally( - input: File, - inputChanges: SerializableFileChanges, - classpathChanges: SerializableFileChanges, + inputDir: File, + inputDirChanges: SerializableFileChanges, dexOutputDir: File, - globalSyntheticsOutput: File?, - desugarGraphFile: File + globalSyntheticsOutputDir: File?, + desugarGraphOutputFile: File ) { - val desugarGraph = try { - readDesugarGraph(desugarGraphFile) - } catch (e: Exception) { - LoggerWrapper.getLogger(BaseDexingTransform::class.java).warning( - "Failed to read desugaring graph." + - " Cause: ${e.javaClass.simpleName}, message: ${e.message}.\n" + - "Fall back to non-incremental mode." - ) - processNonIncrementally( - input, - dexOutputDir, - globalSyntheticsOutput, - true, - desugarGraphFile - ) - return - } + val desugarGraph = DesugarGraph.read(desugarGraphOutputFile, rootDir = inputDir) // Compute impacted files based on the changed files and the desugaring graph - val removedFiles = - (inputChanges.removedFiles + classpathChanges.removedFiles).map { it.file }.toSet() - val modifiedFiles = - (inputChanges.modifiedFiles + classpathChanges.modifiedFiles).map { it.file }.toSet() - val addedFiles = - (inputChanges.addedFiles + classpathChanges.addedFiles).map { it.file }.toSet() + val removedFiles = inputDirChanges.removedFiles.map { it.file } + val modifiedFiles = inputDirChanges.modifiedFiles.map { it.file } + val addedFiles = inputDirChanges.addedFiles.map { it.file } val unchangedButImpactedFiles = desugarGraph.getAllDependents(removedFiles + modifiedFiles) - val modifiedImpactedOrAddedFiles = modifiedFiles + unchangedButImpactedFiles + addedFiles - val removedModifiedOrImpactedFiles = - removedFiles + modifiedFiles + unchangedButImpactedFiles // Remove outputs of removed, modified, and unchanged-but-impacted class files - check(input.isDirectory) { "In incremental mode, input must be a directory: ${input.path}" } - (inputChanges.removedFiles.map { it.file } + input.walk().toList()) - .filter { - ClassFileInput.CLASS_MATCHER.test(it.path) && it in removedModifiedOrImpactedFiles - } + (removedFiles + modifiedFiles + unchangedButImpactedFiles) + .filter { ClassFileInput.CLASS_MATCHER.test(it.path) } .forEach { classFile -> - // We are in DexFilePerClassFile output mode - DexFilePerClassFile.getDexOutputRelativePathsOfClassFile( - classFileRelativePath = classFile.toRelativeString(input) - ).forEach { outputRelativePath -> - FileUtils.deleteIfExists(dexOutputDir.resolve(outputRelativePath)) - } - globalSyntheticsOutput?.let { - DexFilePerClassFile.getGlobalOutputRelativePathOfClassFile( - classFile.toRelativeString(input) - ).let { outputRelativePath -> - FileUtils.deleteIfExists(it.resolve(outputRelativePath)) - } + val classFileRelativePath = classFile.toRelativeString(inputDir) + // Output mode must be DexFilePerClassFile (see the `process` method) + DexFilePerClassFile.getDexOutputRelativePath(classFileRelativePath) + .let { FileUtils.deleteIfExists(dexOutputDir.resolve(it)) } + globalSyntheticsOutputDir?.let { + DexFilePerClassFile.getGlobalSyntheticOutputRelativePath(classFileRelativePath) + .let { FileUtils.deleteIfExists(globalSyntheticsOutputDir.resolve(it)) } } + desugarGraph.removeNode(classFile) } - // Remove stale nodes in the desugaring graph - removedModifiedOrImpactedFiles.forEach { - desugarGraph.removeNode(it) - } - - // Process only input files that are modified, added, or unchanged-but-impacted - val filter: (File, String) -> Boolean = { inputDir: File, relativePath: String -> - check(inputDir.isDirectory) + // Process only class files that are modified, unchanged-but-impacted, or added + val modifiedImpactedOrAddedFiles = + (modifiedFiles + unchangedButImpactedFiles + addedFiles).toSet() + val inputFilter: (File, String) -> Boolean = { _, relativePath: String -> inputDir.resolve(relativePath) in modifiedImpactedOrAddedFiles } process( - input, - filter, + inputDir, + inputFilter, + // `classpath` must be null (see the definition of `provideIncrementalSupport`) + classpath = null, dexOutputDir, - globalSyntheticsOutput, - true, + globalSyntheticsOutputDir, + provideIncrementalSupport = true, desugarGraph ) - // Store the desugaring graph for use in the next build. If dexing failed earlier, it is - // intended that we will not store the graph as it is only meant to contain info about a - // previous successful build. - writeDesugarGraph(desugarGraphFile, desugarGraph) + desugarGraph.write(desugarGraphOutputFile) } private fun processNonIncrementally( - input: File, + inputDirOrJar: File, + classpath: List<File>?, dexOutputDir: File, - globalSyntheticsOutput: File?, + globalSyntheticsOutputDir: File?, provideIncrementalSupport: Boolean, - desugarGraphFile: File? // desugarGraphFile != null iff provideIncrementalSupport == true + desugarGraphOutputFile: File? // Not-null iff provideIncrementalSupport == true ) { - FileUtils.deleteRecursivelyIfExists(dexOutputDir) - FileUtils.mkdirs(dexOutputDir) - globalSyntheticsOutput?.let { - FileUtils.deleteRecursivelyIfExists(it) - FileUtils.mkdirs(it) - } - desugarGraphFile?.let { - FileUtils.deleteIfExists(it) - FileUtils.mkdirs(it.parentFile) - } - - val desugarGraph = desugarGraphFile?.let { - MutableDependencyGraph<File>() - } + FileUtils.cleanOutputDir(dexOutputDir) + globalSyntheticsOutputDir?.let { FileUtils.cleanOutputDir(it) } + desugarGraphOutputFile?.let { FileUtils.deleteIfExists(it) } + + val desugarGraph = if (provideIncrementalSupport) { + // `inputDirOrJar` must be a directory when `provideIncrementalSupport == true` + // (see the definition of `provideIncrementalSupport`) + DesugarGraph(rootDir = inputDirOrJar) + } else null process( - input, + inputDirOrJar, { _, _ -> true }, + classpath, dexOutputDir, - globalSyntheticsOutput, + globalSyntheticsOutputDir, provideIncrementalSupport, desugarGraph ) - // Store the desugaring graph for use in the next build. If dexing failed earlier, it is - // intended that we will not store the graph as it is only meant to contain info about a - // previous successful build. - desugarGraphFile?.let { - writeDesugarGraph(it, desugarGraph!!) + if (provideIncrementalSupport) { + desugarGraph!!.write(desugarGraphOutputFile!!) } } private fun process( - input: File, + inputDirOrJar: File, inputFilter: (File, String) -> Boolean, + classpath: List<File>?, dexOutputDir: File, - globalSyntheticsOutput: File?, + globalSyntheticsOutputDir: File?, provideIncrementalSupport: Boolean, - // desugarGraphUpdater != null iff provideIncrementalSupport == true - desugarGraphUpdater: DependencyGraphUpdater<File>? + desugarGraph: DesugarGraph? // Not-null iff provideIncrementalSupport == true ) { + @Suppress("UnstableApiUsage") Closer.create().use { closer -> val d8DexBuilder = DexArchiveBuilder.createD8DexBuilder( DexParameters( minSdkVersion = parameters.minSdkVersion.get(), debuggable = parameters.debuggable.get(), + // dexPerClass iff provideIncrementalSupport == true dexPerClass = provideIncrementalSupport, withDesugaring = parameters.enableDesugaring.get(), desugarBootclasspath = ClassFileProviderFactory( parameters.bootClasspath.files.map(File::toPath) ) .also { closer.register(it) }, - desugarClasspath = ClassFileProviderFactory(computeClasspathFiles()).also { - closer.register(it) - }, + desugarClasspath = ClassFileProviderFactory( + classpath?.map(File::toPath) ?: emptyList() + ) + .also { closer.register(it) }, coreLibDesugarConfig = parameters.libConfiguration.orNull, messageReceiver = MessageReceiverImpl( parameters.errorFormat.get(), @@ -309,15 +271,15 @@ abstract class BaseDexingTransform<T : BaseDexingTransform.Parameters> : Transfo ) ) - ClassFileInputs.fromPath(input.toPath()).use { classFileInput -> + ClassFileInputs.fromPath(inputDirOrJar.toPath()).use { classFileInput -> classFileInput.entries { rootPath, relativePath -> inputFilter(rootPath.toFile(), relativePath) }.use { classesInput -> d8DexBuilder.convert( classesInput, dexOutputDir.toPath(), - globalSyntheticsOutput?.toPath(), - desugarGraphUpdater + globalSyntheticsOutputDir?.toPath(), + desugarGraph ) } } @@ -325,23 +287,76 @@ abstract class BaseDexingTransform<T : BaseDexingTransform.Parameters> : Transfo } } +/** + * Desugaring graph used for incremental dexing. It contains class files and their dependencies. + * + * This graph handles files with absolute paths. To make it relocatable, it requires that all files + * in the graph share one single root directory ([rootDir]) so that they can be converted to + * relative paths. + * + * Internally, this graph maintains a [relocatableDesugarGraph] containing relative paths of the + * files. When writing this graph to disk, we will write the [relocatableDesugarGraph]. + */ +private class DesugarGraph( + + /** The root directory that is shared among all files in the desugaring graph. */ + private val rootDir: File, + + /** The relocatable desugaring graph, which contains relative paths of the files. */ + private val relocatableDesugarGraph: MutableDependencyGraph<File> = MutableDependencyGraph() + +) : DependencyGraphUpdater<File> { + + override fun addEdge(dependent: File, dependency: File) { + relocatableDesugarGraph.addEdge( + dependent.relativeTo(rootDir), + dependency.relativeTo(rootDir) + ) + } + + fun removeNode(nodeToRemove: File) { + relocatableDesugarGraph.removeNode(nodeToRemove.relativeTo(rootDir)) + } + + fun getAllDependents(nodes: Collection<File>): Set<File> { + val relativePaths = nodes.mapTo(mutableSetOf()) { it.relativeTo(rootDir) } + + val dependents = relocatableDesugarGraph.getAllDependents(relativePaths) + + return dependents.mapTo(mutableSetOf()) { rootDir.resolve(it) } + } + + fun write(relocatableDesugarGraphFile: File) { + writeDesugarGraph(relocatableDesugarGraphFile, relocatableDesugarGraph) + } + + companion object { + + fun read(relocatableDesugarGraphFile: File, rootDir: File): DesugarGraph { + return DesugarGraph( + rootDir = rootDir, + relocatableDesugarGraph = readDesugarGraph(relocatableDesugarGraphFile) + ) + } + } +} + @CacheableTransform abstract class DexingNoClasspathTransform : BaseDexingTransform<BaseDexingTransform.Parameters>() { - override fun computeClasspathFiles() = listOf<Path>() + + override fun computeClasspathFiles() = null } @CacheableTransform abstract class DexingWithClasspathTransform : BaseDexingTransform<BaseDexingTransform.Parameters>() { - /** - * Using compile classpath normalization is safe here due to the design of desugar: - * Method bodies are only moved to the companion class within the same artifact, - * not between artifacts. - */ + + // Use @CompileClasspath instead of @Classpath because non-ABI changes on the classpath do not + // impact dexing/desugaring of the artifact. @get:CompileClasspath @get:InputArtifactDependencies abstract val classpath: FileCollection - override fun computeClasspathFiles() = classpath.files.map(File::toPath) + override fun computeClasspathFiles() = classpath.files.toList() } fun getDexingArtifactConfigurations(components: Collection<ComponentCreationConfig>): Set<DexingArtifactConfiguration> { @@ -379,7 +394,7 @@ data class DexingArtifactConfiguration( ) { // If we want to do desugaring and our minSdk (or the API level of the device we're deploying - // to) is lower than N then we need additional classpaths in order to proper do the desugaring. + // to) is lower than N then we need a classpath in order to properly do the desugaring. private val needsClasspath = enableDesugaring && minSdk < AndroidVersion.VersionCodes.N fun registerTransform( @@ -453,14 +468,17 @@ data class DexingArtifactConfiguration( } } spec.from.attribute( - ARTIFACT_FORMAT, + ARTIFACT_TYPE_ATTRIBUTE, inputArtifact.type ) if (enableGlobalSynthetics) { - spec.to.attribute(ARTIFACT_FORMAT, AndroidArtifacts.ArtifactType.D8_OUTPUTS.type) + spec.to.attribute( + ARTIFACT_TYPE_ATTRIBUTE, + AndroidArtifacts.ArtifactType.D8_OUTPUTS.type + ) } else { - spec.to.attribute(ARTIFACT_FORMAT, AndroidArtifacts.ArtifactType.DEX.type) + spec.to.attribute(ARTIFACT_TYPE_ATTRIBUTE, AndroidArtifacts.ArtifactType.DEX.type) } getAttributes().apply { @@ -499,4 +517,6 @@ val ATTR_ENABLE_DESUGARING: Attribute<String> = val ATTR_ENABLE_JACOCO_INSTRUMENTATION: Attribute<String> = Attribute.of("dexing-enable-jacoco-instrumentation", String::class.java) -const val DESUGAR_GRAPH_FILE_NAME = "desugar_graph.bin" +private val logger = LoggerWrapper.getLogger(BaseDexingTransform::class.java) + +private const val DESUGAR_GRAPH_FILE_NAME = "desugar_graph.bin" diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/VariantDependencies.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/VariantDependencies.kt index a39008bf25..da7cd24aee 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/VariantDependencies.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/VariantDependencies.kt @@ -16,9 +16,12 @@ package com.android.build.gradle.internal.dependency +import com.android.Version +import com.android.build.api.attributes.AgpVersionAttr import com.android.build.api.attributes.BuildTypeAttr import com.android.build.api.attributes.ProductFlavorAttr import com.android.build.gradle.internal.component.VariantCreationConfig +import com.android.build.gradle.internal.core.dsl.KmpComponentDslInfo import com.android.build.gradle.internal.publishing.AndroidArtifacts import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactScope import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactType.ANDROID_RES @@ -32,11 +35,13 @@ import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactTyp import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactType.LINT_MODEL import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactType.PACKAGED_DEPENDENCIES import com.android.build.gradle.internal.publishing.AndroidArtifacts.ConsumedConfigType +import com.android.build.gradle.internal.publishing.AndroidArtifacts.PublishedConfigType import com.android.build.gradle.internal.publishing.PublishedConfigSpec import com.android.build.gradle.internal.services.VariantServices import com.android.build.gradle.options.BooleanOption import com.android.build.gradle.options.ProjectOptions import com.android.builder.core.ComponentType +import com.android.builder.core.ComponentTypeImpl import com.google.common.base.MoreObjects import com.google.common.collect.ImmutableList import org.gradle.api.Action @@ -59,6 +64,7 @@ import org.gradle.api.attributes.Category import org.gradle.api.attributes.DocsType import org.gradle.api.attributes.LibraryElements import org.gradle.api.attributes.Usage +import org.gradle.api.attributes.java.TargetJvmEnvironment import org.gradle.api.file.FileCollection import org.gradle.api.specs.Spec import java.io.File @@ -86,13 +92,14 @@ class VariantDependencies internal constructor( private val sourceSetRuntimeConfigurations: Collection<Configuration>, val sourceSetImplementationConfigurations: Collection<Configuration>, private val elements: Map<PublishedConfigSpec, Configuration>, - private val providedClasspath: Configuration, - val annotationProcessorConfiguration: Configuration, + private val providedClasspath: Configuration?, + val annotationProcessorConfiguration: Configuration?, private val reverseMetadataValuesConfiguration: Configuration?, val wearAppConfiguration: Configuration?, private val testedVariant: VariantCreationConfig?, private val project: Project, private val projectOptions: ProjectOptions, + val isLibraryConstraintsApplied: Boolean, isSelfInstrumenting: Boolean, ): ResolutionResultProvider { @@ -281,8 +288,8 @@ class VariantDependencies internal constructor( return when (configType) { ConsumedConfigType.COMPILE_CLASSPATH -> compileClasspath ConsumedConfigType.RUNTIME_CLASSPATH -> runtimeClasspath - ConsumedConfigType.PROVIDED_CLASSPATH -> providedClasspath - ConsumedConfigType.ANNOTATION_PROCESSOR -> annotationProcessorConfiguration + ConsumedConfigType.PROVIDED_CLASSPATH -> providedClasspath!! + ConsumedConfigType.ANNOTATION_PROCESSOR -> annotationProcessorConfiguration!! ConsumedConfigType.REVERSE_METADATA_VALUES -> checkNotNull(reverseMetadataValuesConfiguration) { "reverseMetadataValuesConfiguration is null" @@ -374,6 +381,115 @@ class VariantDependencies internal constructor( @Deprecated("") const val CONFIG_NAME_FEATURE = "feature" + fun createForKotlinMultiplatform( + project: Project, + projectOptions: ProjectOptions, + dslInfo: KmpComponentDslInfo, + apiClasspath: Configuration, + compileClasspath: Configuration, + runtimeClasspath: Configuration, + apiElements: Configuration?, + runtimeElements: Configuration?, + apiPublication: Configuration?, + runtimePublication: Configuration? + ): VariantDependencies { + + project.objects.named( + TargetJvmEnvironment::class.java, + TargetJvmEnvironment.ANDROID + ).let { androidTarget -> + listOfNotNull( + compileClasspath, + runtimeClasspath, + apiElements, + runtimeElements, + apiPublication, + runtimePublication + ).forEach { + it.attributes.attribute( + TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE, + androidTarget + ) + } + } + + project.objects.named( + AgpVersionAttr::class.java, + Version.ANDROID_GRADLE_PLUGIN_VERSION + ).let { agpVersion -> + listOfNotNull(compileClasspath, runtimeClasspath, apiElements, runtimeElements).forEach { + it.attributes.attribute(AgpVersionAttr.ATTRIBUTE, agpVersion) + } + } + + listOfNotNull(apiElements, apiPublication).forEach { + it.extendsFrom(apiClasspath) + } + + listOfNotNull(runtimeElements, runtimePublication).forEach { + it.extendsFrom(runtimeClasspath) + } + + // add dependency on main project + if (dslInfo.componentType.isTestComponent) { + compileClasspath.dependencies.add(project.dependencies.create(project)) + runtimeClasspath.dependencies.add(project.dependencies.create(project)) + } + + project.objects.named( + LibraryElements::class.java, + AndroidArtifacts.ArtifactType.AAR.type + ).let { aar -> + apiPublication?.attributes?.attribute( + LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, + aar + ) + runtimePublication?.attributes?.attribute( + LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, + aar + ) + } + + val elements = mutableMapOf<PublishedConfigSpec, Configuration>() + + runtimeElements?.let { + elements[PublishedConfigSpec(PublishedConfigType.RUNTIME_ELEMENTS)] = runtimeElements + } + apiElements?.let { + elements[PublishedConfigSpec(PublishedConfigType.API_ELEMENTS)] = apiElements + } + + apiPublication?.let { + elements[PublishedConfigSpec( + PublishedConfigType.API_PUBLICATION, dslInfo.componentIdentity.name + )] = apiPublication + } + runtimePublication?.let { + elements[PublishedConfigSpec( + PublishedConfigType.RUNTIME_PUBLICATION, dslInfo.componentIdentity.name + )] = runtimePublication + } + + return VariantDependencies( + variantName = dslInfo.componentIdentity.name, + componentType = ComponentTypeImpl.KMP_ANDROID, + compileClasspath = compileClasspath, + runtimeClasspath = runtimeClasspath, + sourceSetRuntimeConfigurations = emptySet(), + sourceSetImplementationConfigurations = emptySet(), + elements = elements, + providedClasspath = null, + annotationProcessorConfiguration = null, + reverseMetadataValuesConfiguration = null, + wearAppConfiguration = null, + testedVariant = null, + project = project, + projectOptions = projectOptions, + isLibraryConstraintsApplied = false, + isSelfInstrumenting = false + ) + } + private fun isArtifactTypeSubtractedForInstrumentationTests( artifactType: AndroidArtifacts.ArtifactType ): Boolean { diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/VariantDependenciesBuilder.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/VariantDependenciesBuilder.java index 1c41703757..e0d88e3623 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/VariantDependenciesBuilder.java +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/VariantDependenciesBuilder.java @@ -58,6 +58,7 @@ import com.android.build.gradle.internal.testFixtures.TestFixturesUtil; import com.android.build.gradle.options.BooleanOption; import com.android.build.gradle.options.ProjectOptions; import com.android.builder.core.ComponentType; +import com.android.builder.core.ComponentTypeImpl; import com.android.builder.errors.IssueReporter; import com.android.utils.StringHelper; import com.google.common.base.Preconditions; @@ -317,32 +318,9 @@ public class VariantDependenciesBuilder { runtimeAttributes.attribute(TARGET_JVM_ENVIRONMENT_ATTRIBUTE, jvmEnvironment); runtimeAttributes.attribute(AgpVersionAttr.ATTRIBUTE, agpVersion); - if (projectOptions.get(BooleanOption.USE_DEPENDENCY_CONSTRAINTS)) { - Provider<StringCachingBuildService> stringCachingService = - new StringCachingBuildService.RegistrationAction(project).execute(); - // make compileClasspath match runtimeClasspath - ConstraintHandler.alignWith( - compileClasspath, runtimeClasspath, dependencies, false, stringCachingService); - - // if this is a test App, then also synchronize the 2 runtime classpaths - if (componentType.isApk() && testedVariant != null) { - Configuration testedRuntimeClasspath = - testedVariant.getVariantDependencies().getRuntimeClasspath(); - ConstraintHandler.alignWith( - runtimeClasspath, - testedRuntimeClasspath, - dependencies, - true, - stringCachingService); - if (testedVariant.getComponentType().isApk()) { - ConstraintHandler.checkConfigurationAlignments( - runtimeClasspath, - testedRuntimeClasspath, - issueReporter, - project.getBuildFile()); - } - } - } + boolean isLibraryConstraintApplied = + maybeAddDependencyConstraints( + componentType, dependencies, compileClasspath, runtimeClasspath); Configuration globalTestedApks = configurations.findByName(VariantDependencies.CONFIG_NAME_TESTED_APKS); @@ -705,9 +683,64 @@ public class VariantDependenciesBuilder { testedVariant, project, projectOptions, + isLibraryConstraintApplied, isSelfInstrumenting); } + /** + * Returns whether any library constraints are applied This is used later to generate a sync + * warning if the IDE is set to skip runtime classpath, but the library constraints are still + * applied, which makes us resolve runtime classpath. + */ + private boolean maybeAddDependencyConstraints( + ComponentType componentType, + DependencyHandler dependencies, + Configuration compileClasspath, + Configuration runtimeClasspath) { + if (!projectOptions.get(BooleanOption.USE_DEPENDENCY_CONSTRAINTS)) { + return false; + } + // Contrary to what the name might suggest, this will actually filter all aar components, + // not just libraries. + boolean excludeLibraryComponents = + projectOptions.get(BooleanOption.EXCLUDE_LIBRARY_COMPONENTS_FROM_CONSTRAINTS); + boolean isAarTest = + (componentType == ComponentTypeImpl.ANDROID_TEST + || componentType == ComponentTypeImpl.UNIT_TEST) + && testedVariant.getComponentType().isAar(); + + if (excludeLibraryComponents && (componentType.isAar() || isAarTest)) { + return false; + } + + Provider<StringCachingBuildService> stringCachingService = + new StringCachingBuildService.RegistrationAction(project).execute(); + // make compileClasspath match runtimeClasspath + ConstraintHandler.alignWith( + compileClasspath, runtimeClasspath, dependencies, false, stringCachingService); + + if (componentType.isApk() && testedVariant != null) { + // if this is a test App, then also synchronize the 2 runtime classpaths + Configuration testedRuntimeClasspath = + testedVariant.getVariantDependencies().getRuntimeClasspath(); + ConstraintHandler.alignWith( + runtimeClasspath, + testedRuntimeClasspath, + dependencies, + true, + stringCachingService); + + if (testedVariant.getComponentType().isApk()) { + ConstraintHandler.checkConfigurationAlignments( + runtimeClasspath, + testedRuntimeClasspath, + issueReporter, + project.getBuildFile()); + } + } + return true; + } + @NonNull private Configuration createPublishingConfig( @NonNull ConfigurationContainer configurations, diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/DefaultAidl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/DefaultAidl.kt new file mode 100644 index 0000000000..d22b699b66 --- /dev/null +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/DefaultAidl.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 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.build.gradle.internal.dsl + +import com.android.build.api.variant.Aidl +import org.gradle.api.file.RegularFile +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity + +class DefaultAidl( + @get:Internal + override val executable: Provider<RegularFile>, + @get:PathSensitive(PathSensitivity.NAME_ONLY) + @get:InputFile + override val framework: Provider<RegularFile>, + @get:Input + override val version: Provider<String> +) : Aidl + diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/KotlinMultiplatformAndroidExtension.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/KotlinMultiplatformAndroidExtension.kt index 17db0733ed..7ffdc3b43b 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/KotlinMultiplatformAndroidExtension.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/KotlinMultiplatformAndroidExtension.kt @@ -21,6 +21,7 @@ import com.android.build.api.dsl.ApkSigningConfig import com.android.build.api.dsl.Installation import com.android.build.api.dsl.Optimization import com.android.build.api.dsl.Packaging +import com.android.build.api.dsl.TestCoverage import com.android.build.api.dsl.TestOptions import com.android.build.api.variant.impl.KotlinMultiplatformAndroidVariant import java.io.File @@ -77,6 +78,10 @@ interface KotlinMultiplatformAndroidExtension { var testFunctionalTest: Boolean? + var isTestMultiDexEnabled: Boolean? + var testMultiDexKeepProguard: File? + var isCoreLibraryDesugaringEnabled: Boolean + val installation: Installation // should this be here? @@ -88,6 +93,11 @@ interface KotlinMultiplatformAndroidExtension { var enableUnitTest: Boolean var enableAndroidTest: Boolean + var enableUnitTestCoverage: Boolean + var enableInstrumentedTestCoverage: Boolean + + val testCoverage: TestCoverage + fun onVariant( callback: KotlinMultiplatformAndroidVariant.() -> Unit ) diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/KotlinMultiplatformAndroidExtensionImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/KotlinMultiplatformAndroidExtensionImpl.kt index 5fedc3aa6a..2bd886a5f5 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/KotlinMultiplatformAndroidExtensionImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/KotlinMultiplatformAndroidExtensionImpl.kt @@ -20,11 +20,13 @@ import com.android.build.api.dsl.ApkSigningConfig import com.android.build.api.variant.AndroidVersion import com.android.build.api.variant.impl.KotlinMultiplatformAndroidVariant import com.android.build.api.variant.impl.MutableAndroidVersion +import com.android.build.gradle.internal.coverage.JacocoOptions import com.android.build.gradle.internal.dsl.decorator.annotation.WithLazyInitialization import com.android.build.gradle.internal.packaging.getDefaultDebugKeystoreLocation import com.android.build.gradle.internal.services.AndroidLocationsBuildService import com.android.build.gradle.internal.services.DslServices import com.android.build.gradle.internal.services.getBuildService +import com.android.builder.core.BuilderConstants import com.android.builder.core.LibraryRequest import com.android.builder.core.ToolsRevisionUtils import com.android.builder.signing.DefaultSigningConfig @@ -64,7 +66,7 @@ abstract class KotlinMultiplatformAndroidExtensionImpl @Inject @WithLazyInitiali ) var signingConfig = dslServices.newDecoratedInstance( - SigningConfig::class.java, "kotlinAndroidInstrumentation", dslServices + SigningConfig::class.java, BuilderConstants.DEBUG, dslServices ) override fun testSigningConfig(action: ApkSigningConfig.() -> Unit) { @@ -126,6 +128,8 @@ abstract class KotlinMultiplatformAndroidExtensionImpl @Inject @WithLazyInitiali target.api = null } + override val testCoverage = dslServices.newInstance(JacocoOptions::class.java) + private val variantOperations = mutableListOf<Action<KotlinMultiplatformAndroidVariant>>() private var actionsExecuted = false diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ManagedDevices.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ManagedDevices.kt index b24705cbf4..719234758c 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ManagedDevices.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ManagedDevices.kt @@ -32,6 +32,30 @@ open class ManagedDevices @Inject constructor(dslServices: DslServices) : com.android.build.api.dsl.ManagedVirtualDevice::class.java, ManagedVirtualDevice::class.java ) + whenObjectAdded { device: Device -> + if (device is com.android.build.api.dsl.ManagedVirtualDevice) { + localDevices.add(device) + } + } + whenObjectRemoved { device: Device -> + if (device is com.android.build.api.dsl.ManagedVirtualDevice) { + localDevices.remove(device) + } + } + } + + override val localDevices: + NamedDomainObjectContainer<com.android.build.api.dsl.ManagedVirtualDevice> = + dslServices.domainObjectContainer( + com.android.build.api.dsl.ManagedVirtualDevice::class.java, + ManagedVirtualDeviceFactory(dslServices) + ).apply { + whenObjectAdded { device: com.android.build.api.dsl.ManagedVirtualDevice -> + allDevices.add(device) + } + whenObjectRemoved { device: com.android.build.api.dsl.ManagedVirtualDevice -> + allDevices.remove(device) + } } override val devices: ExtensiblePolymorphicDomainObjectContainer<Device> = allDevices diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ManagedVirtualDeviceFactory.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ManagedVirtualDeviceFactory.kt new file mode 100644 index 0000000000..0db9b29e3e --- /dev/null +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ManagedVirtualDeviceFactory.kt @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2023 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.build.gradle.internal.dsl + +import com.android.build.gradle.internal.services.DslServices +import org.gradle.api.NamedDomainObjectFactory + +class ManagedVirtualDeviceFactory(private val dslServices: DslServices) : + NamedDomainObjectFactory<com.android.build.api.dsl.ManagedVirtualDevice> { + + override fun create(name: String): ManagedVirtualDevice { + return dslServices.newInstance(ManagedVirtualDevice::class.java, name); + } +} diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ModuleBooleanPropertyKeys.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ModuleBooleanPropertyKeys.kt index bba4bb4bd5..16b326e74c 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ModuleBooleanPropertyKeys.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ModuleBooleanPropertyKeys.kt @@ -31,7 +31,7 @@ enum class ModuleBooleanPropertyKeys(val keyValue: String, private val defaultVa * If false - R8 will not be provided with the merged art-profile * If true - R8 will rewrite the art-profile */ - ART_PROFILE_R8_REWRITING("android.experimental.art-profile-r8-rewriting", false), + ART_PROFILE_R8_REWRITING("android.experimental.art-profile-r8-rewriting", true), VERIFY_AAR_CLASSES(BooleanOption.VERIFY_AAR_CLASSES.propertyName, false), diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ModuleStringPropertyKeys.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ModuleStringPropertyKeys.kt index 538863a857..ddef75f66c 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ModuleStringPropertyKeys.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ModuleStringPropertyKeys.kt @@ -18,14 +18,20 @@ package com.android.build.gradle.internal.dsl import com.android.build.gradle.options.StringOption -enum class ModuleStringPropertyKeys(private val keyValue: String, private val defaultValue: String?) { +enum class ModuleStringPropertyKeys(private val _keyValue: String, private val _defaultValue: String?) { - ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR(StringOption.ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR.propertyName, null), + ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR( + StringOption.ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR.propertyName, + null), - ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR_GENERATED_RUNTIME_DEPENDENCIES(StringOption.ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR_GENERATED_RUNTIME_DEPENDENCIES.propertyName, null), + ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR_GENERATED_RUNTIME_DEPENDENCIES( + StringOption.ANDROID_PRIVACY_SANDBOX_SDK_API_GENERATOR_GENERATED_RUNTIME_DEPENDENCIES.propertyName, + null), ; - fun getValueAsString(properties: Map<String, Any>) : String? { - return properties[keyValue]?.toString() ?: defaultValue - } + fun getValueAsType(properties: Map<String, Any>): String? { + return properties[keyValue]?.toString() ?: _defaultValue + } + + val keyValue: String get() = _keyValue } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/SdkComponentsImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/SdkComponentsImpl.kt index 50665045c6..f63661746b 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/SdkComponentsImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/SdkComponentsImpl.kt @@ -17,6 +17,7 @@ package com.android.build.gradle.internal.dsl import com.android.build.api.dsl.SdkComponents +import com.android.build.api.variant.Aidl import com.android.build.gradle.internal.services.DslServices import com.android.repository.Revision import org.gradle.api.file.Directory @@ -53,4 +54,23 @@ open class SdkComponentsImpl @Inject constructor( } override val bootClasspath: Provider<List<RegularFile>> get() = bootclasspathProvider.get() + + override val aidl: Provider<Aidl> by lazy(LazyThreadSafetyMode.NONE) { + val aidlExecutable = dslServices.sdkComponents.flatMap { + it.sdkLoader(compileSdkVersion, buildToolsRevision).aidlExecutableProvider + } + + val aidlFramework = dslServices.sdkComponents.flatMap { + it.sdkLoader(compileSdkVersion, buildToolsRevision).aidlFrameworkProvider + } + + dslServices.provider( + Aidl::class.java, + DefaultAidl( + aidlExecutable, + aidlFramework, + buildToolsRevision.map { it.toString() } + ) + ) + } } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/v2/ModelBuilder.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/v2/ModelBuilder.kt index 0ea07abc5f..766fb5584b 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/v2/ModelBuilder.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/v2/ModelBuilder.kt @@ -816,6 +816,17 @@ class ModelBuilder< libraryService: LibraryService, dontBuildRuntimeClasspath: Boolean ): ArtifactDependencies { + if (dontBuildRuntimeClasspath && component.variantDependencies.isLibraryConstraintsApplied) { + variantModel.syncIssueReporter.reportWarning(IssueReporter.Type.GENERIC, """ + You have experimental IDE flag gradle.ide.gradle.skip.runtime.classpath.for.libraries enabled, + but AGP boolean option ${BooleanOption.EXCLUDE_LIBRARY_COMPONENTS_FROM_CONSTRAINTS.propertyName} is not used. + + Please set below in gradle.properties: + + ${BooleanOption.EXCLUDE_LIBRARY_COMPONENTS_FROM_CONSTRAINTS.propertyName}=true + + """.trimIndent()) + } val inputs = ArtifactCollectionsInputsImpl( variantDependencies = component.variantDependencies, diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/v2/VersionsImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/v2/VersionsImpl.kt index 84cdebb2ca..29aac89653 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/v2/VersionsImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/v2/VersionsImpl.kt @@ -32,7 +32,8 @@ data class VersionsImpl( data class VersionImpl( override val major: Int, - override val minor: Int + override val minor: Int, + override val humanReadable: String? = null, ): Version, Serializable { companion object { @JvmStatic diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/lint/AndroidLintInputs.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/lint/AndroidLintInputs.kt index d048c617bf..92c526d9f9 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/lint/AndroidLintInputs.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/lint/AndroidLintInputs.kt @@ -1571,6 +1571,7 @@ abstract class AndroidArtifactInput : ArtifactInput() { testedVariant = null, project = project, projectOptions = projectOptions, + isLibraryConstraintsApplied = false, isSelfInstrumenting = false, ) artifactCollectionsInputs.setDisallowChanges( @@ -1689,6 +1690,7 @@ abstract class JavaArtifactInput : ArtifactInput() { testedVariant = null, project = project, projectOptions = projectOptions, + isLibraryConstraintsApplied = false, isSelfInstrumenting = false, ) artifactCollectionsInputs.setDisallowChanges( diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/AndroidPluginBaseServices.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/AndroidPluginBaseServices.kt index 1ff701bf75..04d2d19a8d 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/AndroidPluginBaseServices.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/AndroidPluginBaseServices.kt @@ -17,8 +17,14 @@ package com.android.build.gradle.internal.plugins import com.android.Version +import com.android.build.api.dsl.ExecutionProfile +import com.android.build.api.dsl.SettingsExtension import com.android.build.gradle.internal.attribution.BuildAnalyzerConfiguratorService import com.android.build.gradle.internal.attribution.BuildAnalyzerService +import com.android.build.gradle.internal.core.DEFAULT_EXECUTION_PROFILE +import com.android.build.gradle.internal.core.ExecutionProfileOptions +import com.android.build.gradle.internal.core.SettingsOptions +import com.android.build.gradle.internal.core.ToolExecutionOptions import com.android.build.gradle.internal.errors.DeprecationReporterImpl import com.android.build.gradle.internal.errors.SyncIssueReporterImpl import com.android.build.gradle.internal.lint.LintFromMaven.Companion.from @@ -31,6 +37,7 @@ import com.android.build.gradle.internal.registerDependencyCheck import com.android.build.gradle.internal.res.Aapt2FromMaven.Companion.create import com.android.build.gradle.internal.scope.ProjectInfo import com.android.build.gradle.internal.services.AndroidLocationsBuildService +import com.android.build.gradle.internal.services.DslServices import com.android.build.gradle.internal.services.ProjectServices import com.android.build.gradle.options.BooleanOption import com.android.build.gradle.options.ProjectOptionService @@ -47,7 +54,6 @@ import org.gradle.api.tasks.StopExecutionException import org.gradle.build.event.BuildEventsListenerRegistry import java.util.Locale -@Suppress("UnstableApiUsage") abstract class AndroidPluginBaseServices( private val listenerRegistry: BuildEventsListenerRegistry ) { @@ -169,6 +175,78 @@ abstract class AndroidPluginBaseServices( } } + protected val settingsExtension: SettingsExtension? by lazy(LazyThreadSafetyMode.NONE) { + // Query for the settings extension via extra properties. + // This is deposited here by the SettingsPlugin + val properties = project?.extensions?.extraProperties + if (properties?.has("_android_settings") == true) { + properties.get("_android_settings") as? SettingsExtension + } else { + null + } + } + + // Create settings options, to be used in the global config, + // with values from the android settings extension + protected fun createSettingsOptions( + dslServices: DslServices + ): SettingsOptions { + // resolve settings extension + val actualSettingsExtension = settingsExtension ?: run { + dslServices.logger.info("Using default execution profile") + return SettingsOptions(DEFAULT_EXECUTION_PROFILE) + } + + // Map the profiles to make it easier to look them up + val executionProfiles = actualSettingsExtension.execution.profiles.associateBy { profile -> profile.name } + + val buildProfileOptions = { profile: ExecutionProfile -> + ExecutionProfileOptions( + name = profile.name, + r8Options = profile.r8.let { r8 -> + ToolExecutionOptions( + jvmArgs = r8.jvmOptions, + runInSeparateProcess = r8.runInSeparateProcess + ) + } + ) + } + + // If the string option is set use that one instead + val actualProfileName = + dslServices.projectOptions[StringOption.EXECUTION_PROFILE_SELECTION] ?: + actualSettingsExtension.execution.defaultProfile + // Find the selected (or the only) profile + val executionProfile = + if (actualProfileName == null) { + if (executionProfiles.isEmpty()) { // No profiles declared, and none selected, return default + dslServices.logger.info("Using default execution profile") + DEFAULT_EXECUTION_PROFILE + } else if (executionProfiles.size == 1) { // if there is exactly one profile use that + dslServices.logger.info("Using only execution profile '${executionProfiles.keys.first()}'") + buildProfileOptions(executionProfiles.values.first()) + } else { // no profile selected + dslServices.issueReporter.reportError(Type.GENERIC, "Found ${executionProfiles.size} execution profiles ${executionProfiles.keys}, but no profile was selected.\n") + null + } + } else { + if (!executionProfiles.containsKey(actualProfileName)) { // invalid profile selected + dslServices.issueReporter.reportError(Type.GENERIC,"Selected profile '$actualProfileName' does not exist") + null + } else { + if (actualProfileName == dslServices.projectOptions[StringOption.EXECUTION_PROFILE_SELECTION]) { + dslServices.logger.info("Using execution profile from android.settings.executionProfile '$actualProfileName'") + } else { + dslServices.logger.info("Using execution profile from dsl '$actualProfileName'") + } + + buildProfileOptions(executionProfiles[actualProfileName]!!) + } + } + + return SettingsOptions(executionProfile = executionProfile) + } + private fun checkPathForErrors() { // See if we're on Windows: if (!System.getProperty("os.name").lowercase(Locale.US).contains("windows")) { diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt index ce1d714f1d..0e1e5742e2 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.kt @@ -19,7 +19,6 @@ package com.android.build.gradle.internal.plugins import com.android.SdkConstants import com.android.build.api.dsl.BuildFeatures import com.android.build.api.dsl.CommonExtension -import com.android.build.api.dsl.ExecutionProfile import com.android.build.api.dsl.SettingsExtension import com.android.build.api.extension.impl.VariantApiOperationsRegistrar import com.android.build.api.variant.AndroidComponentsExtension @@ -100,7 +99,6 @@ import com.android.build.gradle.internal.variant.VariantFactory import com.android.build.gradle.internal.variant.VariantInputModel import com.android.build.gradle.internal.variant.VariantModel import com.android.build.gradle.internal.variant.VariantModelImpl -import com.android.build.gradle.options.StringOption import com.android.build.gradle.options.SyncOptions import com.android.builder.errors.IssueReporter.Type import com.android.builder.model.v2.ide.ProjectType @@ -110,7 +108,6 @@ import com.google.common.annotations.VisibleForTesting import com.google.common.base.Preconditions.checkState import com.google.wireless.android.sdk.stats.GradleBuildProfileSpan.ExecutionType import com.google.wireless.android.sdk.stats.GradleBuildProject -import org.gradle.api.JavaVersion import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Plugin import org.gradle.api.Project @@ -120,7 +117,6 @@ import org.gradle.api.artifacts.repositories.FlatDirectoryArtifactRepository import org.gradle.api.component.SoftwareComponentFactory import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.plugins.JavaPlugin -import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.provider.Provider import org.gradle.build.event.BuildEventsListenerRegistry import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry @@ -130,7 +126,6 @@ import java.util.concurrent.atomic.AtomicBoolean import java.util.function.Consumer /** Base class for all Android plugins */ -@Suppress("UnstableApiUsage") abstract class BasePlugin< BuildFeaturesT: BuildFeatures, BuildTypeT: com.android.build.api.dsl.BuildType, @@ -226,7 +221,7 @@ abstract class BasePlugin< createCustomLintChecksConfig(project), createAndroidJarConfig(project), createFakeDependencyConfig(project), - createSettingsOptions(), + createSettingsOptions(dslServices), managedDeviceRegistry ) } @@ -841,19 +836,6 @@ To learn more, go to https://d.android.com/r/tools/java-8-support-message.html return false } - private val settingsExtension: SettingsExtension? by lazy(LazyThreadSafetyMode.NONE) { - // Query for the settings extension via extra properties. - // This is deposited here by the SettingsPlugin - val properties = project?.extensions?.extraProperties - if (properties == null) { - null - } else if (properties.has("_android_settings")) { - properties.get("_android_settings") as? SettingsExtension - } else { - null - } - } - // Initialize the android extension with values from the android settings extension protected fun initExtensionFromSettings(extension: AndroidT) { settingsExtension?.let { @@ -882,7 +864,7 @@ To learn more, go to https://d.android.com/r/tools/java-8-support-message.html this.defaultConfig.minSdkPreview = minSdkPreview } - settings.ndkVersion?.let { ndkVersion -> + settings.ndkVersion.let { ndkVersion -> this.ndkVersion = ndkVersion } @@ -890,72 +872,11 @@ To learn more, go to https://d.android.com/r/tools/java-8-support-message.html this.ndkPath = ndkPath } - settings.buildToolsVersion?.let { buildToolsVersion -> + settings.buildToolsVersion.let { buildToolsVersion -> this.buildToolsVersion = buildToolsVersion } } - // Create settings options, to be used in the global config, - // with values from the android settings extension - private fun createSettingsOptions(): SettingsOptions { - // resolve settings extension - val actualSettingsExtension = settingsExtension ?: run { - dslServices.logger.info("Using default execution profile") - return SettingsOptions(DEFAULT_EXECUTION_PROFILE) - } - - // Map the profiles to make it easier to look them up - val executionProfiles = actualSettingsExtension.execution.profiles.associate { profile -> - profile.name to profile - } - - val buildProfileOptions = { profile: ExecutionProfile -> - ExecutionProfileOptions( - name = profile.name, - r8Options = profile.r8.let { r8 -> - ToolExecutionOptions( - jvmArgs = r8.jvmOptions, - runInSeparateProcess = r8.runInSeparateProcess - ) - } - ) - } - - // If the string option is set use that one instead - val actualProfileName = - dslServices.projectOptions[StringOption.EXECUTION_PROFILE_SELECTION] ?: - actualSettingsExtension.execution.defaultProfile - // Find the selected (or the only) profile - val executionProfile = - if (actualProfileName == null) { - if (executionProfiles.isEmpty()) { // No profiles declared, and none selected, return default - dslServices.logger.info("Using default execution profile") - DEFAULT_EXECUTION_PROFILE - } else if (executionProfiles.size == 1) { // if there is exactly one profile use that - dslServices.logger.info("Using only execution profile '${executionProfiles.keys.first()}'") - buildProfileOptions(executionProfiles.values.first()) - } else { // no profile selected - dslServices.issueReporter.reportError(Type.GENERIC, "Found ${executionProfiles.size} execution profiles ${executionProfiles.keys}, but no profile was selected.\n") - null - } - } else { - if (!executionProfiles.containsKey(actualProfileName)) { // invalid profile selected - dslServices.issueReporter.reportError(Type.GENERIC,"Selected profile '$actualProfileName' does not exist") - null - } else { - if (actualProfileName == dslServices.projectOptions[StringOption.EXECUTION_PROFILE_SELECTION]) { - dslServices.logger.info("Using execution profile from android.settings.executionProfile '$actualProfileName'") - } else { - dslServices.logger.info("Using execution profile from dsl '$actualProfileName'") - } - - buildProfileOptions(executionProfiles[actualProfileName]!!) - } - } - - return SettingsOptions(executionProfile = executionProfile) - } - // Create the "special" configuration for test buddy APKs. It will be resolved by the test // running task, so that we can install all the found APKs before running tests. private fun createAndroidTestUtilConfiguration(project: Project) { diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/publishing/PublishingSpecs.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/publishing/PublishingSpecs.kt index 6140f665c6..d520433504 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/publishing/PublishingSpecs.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/publishing/PublishingSpecs.kt @@ -303,7 +303,29 @@ class PublishingSpecs { output(LOCAL_AAR_FOR_LINT, ArtifactType.LOCAL_AAR_FOR_LINT) } - variantSpec(ComponentTypeImpl.KMP_ANDROID) + variantSpec(ComponentTypeImpl.KMP_ANDROID) { + publish(com.android.build.api.artifact.SingleArtifact.AAR, ArtifactType.AAR) + + api(COMPILE_LIBRARY_CLASSES_JAR, ArtifactType.CLASSES_JAR) + + // manifest is published to both to compare and detect provided-only library + // dependencies. + output(MERGED_MANIFEST, ArtifactType.MANIFEST) + output(FULL_JAR, ArtifactType.JAR) + + runtime(RUNTIME_LIBRARY_CLASSES_JAR, ArtifactType.CLASSES_JAR) + // Publish the CLASSES_DIR artifact type with a LibraryElements.CLASSES attribute to + // match the behavior of the Java library plugin. The LibraryElements attribute will + // be used for incremental dexing of test fixtures. + runtime(RUNTIME_LIBRARY_CLASSES_DIR, ArtifactType.CLASSES_DIR, LibraryElements.CLASSES) + + runtime(JAVA_RES, ArtifactType.JAVA_RES) + runtime(AAR_METADATA, ArtifactType.AAR_METADATA) + runtime(CONSUMER_PROGUARD_DIR, ArtifactType.UNFILTERED_PROGUARD_RULES) + // Publish LOCAL_AAR_FOR_LINT to API_AND_RUNTIME_ELEMENTS to support compileOnly + // module dependencies. + output(LOCAL_AAR_FOR_LINT, ArtifactType.LOCAL_AAR_FOR_LINT) + } // Publishing will be done manually from the lint standalone plugin for now. // Eventually we should just unify the infrastructure to declare the publications here. @@ -349,6 +371,7 @@ class PublishingSpecs { ComponentTypeImpl.BASE_APK -> AppVariantSpecBuilder(componentType) ComponentTypeImpl.LIBRARY -> LibraryVariantSpecBuilder(componentType) ComponentTypeImpl.TEST_FIXTURES -> TestFixturesVariantSpecBuilder(componentType) + ComponentTypeImpl.KMP_ANDROID -> KotlinMultiplatformVariantSpecBuilder(componentType) else -> VariantSpecBuilderImpl(componentType) } } @@ -515,3 +538,19 @@ private class AppVariantSpecBuilder(componentType: ComponentType): VariantSpecBu } } } + +private class KotlinMultiplatformVariantSpecBuilder(componentType: ComponentType): + VariantSpecBuilderImpl(componentType) { + + override fun publish(taskOutputType: Artifact.Single<*>, artifactType: ArtifactType) { + outputs.add(OutputSpecImpl(taskOutputType, artifactType, API_AND_RUNTIME_PUBLICATION)) + } + + override fun source(taskOutputType: Artifact.Single<*>, artifactType: ArtifactType) { + outputs.add(OutputSpecImpl(taskOutputType, artifactType, SOURCE_PUBLICATION)) + } + + override fun javaDoc(taskOutputType: Artifact.Single<*>, artifactType: ArtifactType) { + outputs.add(OutputSpecImpl(taskOutputType, artifactType, JAVA_DOC_PUBLICATION)) + } +} diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/scope/ArtifactPublishingUtil.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/scope/ArtifactPublishingUtil.kt index 6d365ebe81..d2b1dd315e 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/scope/ArtifactPublishingUtil.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/scope/ArtifactPublishingUtil.kt @@ -17,11 +17,21 @@ @file:JvmName("ArtifactPublishingUtil") package com.android.build.gradle.internal.scope +import com.android.build.gradle.internal.component.ComponentCreationConfig import com.android.build.gradle.internal.dependency.AndroidAttributes import com.android.build.gradle.internal.publishing.AndroidArtifacts +import com.android.build.gradle.internal.publishing.PublishedConfigSpec +import com.android.build.gradle.internal.publishing.PublishingSpecs +import com.android.build.gradle.internal.publishing.VariantPublishingInfo +import com.android.build.gradle.internal.testFixtures.testFixturesClassifier +import com.google.common.base.Preconditions import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.ConfigurationVariant +import org.gradle.api.attributes.DocsType +import org.gradle.api.attributes.LibraryElements +import org.gradle.api.file.FileSystemLocation +import org.gradle.api.provider.Provider /** * Publish an artifact to a configuration. @@ -86,3 +96,105 @@ private fun getConfigurationVariantName( return artifactType.type + (attributes?.toAttributeMapString() ?: "") } +/** Publish intermediate artifacts in the BuildArtifactsHolder based on PublishingSpecs. */ +fun publishBuildArtifacts( + creationConfig: ComponentCreationConfig, + publishInfo: VariantPublishingInfo? +) { + for (outputSpec in PublishingSpecs.getVariantPublishingSpec(creationConfig.componentType).outputs) { + val buildArtifactType = outputSpec.outputType + // Gradle only support publishing single file. Therefore, unless Gradle starts + // supporting publishing multiple files, PublishingSpecs should not contain any + // OutputSpec with an appendable ArtifactType. + if (BuildArtifactSpec.has(buildArtifactType) && BuildArtifactSpec.get(buildArtifactType).appendable) { + throw RuntimeException( + "Appendable ArtifactType '${buildArtifactType.name()}' cannot be published." + ) + } + val artifactProvider = creationConfig.artifacts.get(buildArtifactType) + val artifactContainer = creationConfig.artifacts.getArtifactContainer(buildArtifactType) + if (!artifactContainer.needInitialProducer().get()) { + val isPublicationConfigs = + outputSpec.publishedConfigTypes.any { it.isPublicationConfig } + + if (isPublicationConfigs) { + val components = publishInfo!!.components + for(component in components) { + publishIntermediateArtifact( + creationConfig, + artifactProvider, + outputSpec.artifactType, + outputSpec.publishedConfigTypes.map { + PublishedConfigSpec(it, component) }.toSet(), + outputSpec.libraryElements?.let { + creationConfig.services.named(LibraryElements::class.java, it) + } + ) + } + } else { + publishIntermediateArtifact( + creationConfig, + artifactProvider, + outputSpec.artifactType, + outputSpec.publishedConfigTypes.map { PublishedConfigSpec(it) }.toSet(), + outputSpec.libraryElements?.let { + creationConfig.services.named(LibraryElements::class.java, it) + } + ) + } + } + } +} + +/** + * Publish an intermediate artifact. + * + * @param artifact Provider of File or FileSystemLocation to be published. + * @param artifactType the artifact type. + * @param configSpecs the PublishedConfigSpec. + * @param libraryElements the artifact's library elements + */ +private fun publishIntermediateArtifact( + creationConfig: ComponentCreationConfig, + artifact: Provider<out FileSystemLocation>, + artifactType: AndroidArtifacts.ArtifactType, + configSpecs: Set<PublishedConfigSpec>, + libraryElements: LibraryElements? +) { + Preconditions.checkState(configSpecs.isNotEmpty()) + for (configSpec in configSpecs) { + val config = creationConfig.variantDependencies.getElements(configSpec) + val configType = configSpec.configType + if (config != null) { + if (configType.isPublicationConfig) { + var classifier: String? = null + val isSourcePublication = configType == AndroidArtifacts.PublishedConfigType.SOURCE_PUBLICATION + val isJavaDocPublication = + configType == AndroidArtifacts.PublishedConfigType.JAVA_DOC_PUBLICATION + if (configSpec.isClassifierRequired) { + classifier = if (isSourcePublication) { + creationConfig.name + "-" + DocsType.SOURCES + } else if (isJavaDocPublication) { + creationConfig.name + "-" + DocsType.JAVADOC + } else { + creationConfig.name + } + } else if (creationConfig.componentType.isTestFixturesComponent) { + classifier = testFixturesClassifier + } else if (isSourcePublication) { + classifier = DocsType.SOURCES + } else if (isJavaDocPublication) { + classifier = DocsType.JAVADOC + } + publishArtifactToDefaultVariant(config, artifact, artifactType, classifier) + } else { + publishArtifactToConfiguration( + config, + artifact, + artifactType, + AndroidAttributes(null, libraryElements) + ) + } + } + } +} diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/services/LintParallelBuildService.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/services/LintParallelBuildService.kt index 512da2e1b9..ce32c5557d 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/services/LintParallelBuildService.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/services/LintParallelBuildService.kt @@ -50,8 +50,8 @@ abstract class LintParallelBuildService : BuildService<BuildServiceParameters.No } private fun calculateMaxParallelUsagesInProcess(maxRuntimeMemory: Long): Int { - // We assume lint will use about 512 megabytes per analysis task. - val memoryPerLintTask = 512 * 1024 * 1024 + // We assume lint will use less than 1 gigabyte per analysis task. + val memoryPerLintTask = 1024 * 1024 * 1024 // Multiply maxRuntimeMemory by 0.75 to save memory for other things too val maxLintMemory = (maxRuntimeMemory * 0.75).toLong() return Math.floorDiv(maxLintMemory, memoryPerLintTask).coerceAtLeast(1).toInt() diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ApplicationTaskManager.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ApplicationTaskManager.kt index aebe000f64..d2fc0fabd4 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ApplicationTaskManager.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ApplicationTaskManager.kt @@ -287,8 +287,8 @@ class ApplicationTaskManager( taskFactory.register(PerModuleBundleTask.CreationAction(variant)) val debuggable = variantInfo.variantBuilder.debuggable - val includeSdkInfoInApk = variantInfo.variantBuilder.dependenciesInfo.includedInApk - val includeSdkInfoInBundle = variantInfo.variantBuilder.dependenciesInfo.includedInBundle + val includeSdkInfoInApk = variantInfo.variantBuilder.dependenciesInfo.includeInApk + val includeSdkInfoInBundle = variantInfo.variantBuilder.dependenciesInfo.includeInBundle if (!debuggable) { taskFactory.register(PerModuleReportDependenciesTask.CreationAction(variant)) } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/DexArchiveBuilderTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/DexArchiveBuilderTask.kt index 50c7cdc6e6..1547067909 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/DexArchiveBuilderTask.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/DexArchiveBuilderTask.kt @@ -26,13 +26,13 @@ import com.android.build.gradle.internal.profile.ProfileAwareWorkAction import com.android.build.gradle.internal.scope.InternalArtifactType import com.android.build.gradle.internal.scope.Java8LangSupport import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction +import com.android.build.gradle.internal.tasks.factory.features.DexingTaskCreationAction +import com.android.build.gradle.internal.tasks.factory.features.DexingTaskCreationActionImpl import com.android.build.gradle.internal.utils.getDesugarLibConfig import com.android.build.gradle.internal.utils.setDisallowChanges +import com.android.build.gradle.options.BooleanOption import com.android.build.gradle.options.IntegerOption import com.android.build.gradle.options.SyncOptions -import com.android.build.gradle.internal.tasks.factory.features.DexingTaskCreationAction -import com.android.build.gradle.internal.tasks.factory.features.DexingTaskCreationActionImpl -import com.android.build.gradle.options.BooleanOption import com.android.buildanalyzer.common.TaskCategory import com.android.sdklib.AndroidVersion import com.android.utils.FileUtils @@ -61,7 +61,6 @@ import org.gradle.work.FileChange import org.gradle.work.Incremental import org.gradle.work.InputChanges import java.io.File -import java.nio.file.Path import kotlin.math.max /** @@ -518,9 +517,7 @@ abstract class DexingExternalLibArtifactTransform: BaseDexingTransform<DexingExt val desugaringClasspath: ConfigurableFileCollection } - override fun computeClasspathFiles(): List<Path> { - return parameters.desugaringClasspath.files.map(File::toPath) - } + override fun computeClasspathFiles() = parameters.desugaringClasspath.files.toList() } /** diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/DexArchiveBuilderTaskDelegate.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/DexArchiveBuilderTaskDelegate.kt index 798aef3af8..569821d33c 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/DexArchiveBuilderTaskDelegate.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/DexArchiveBuilderTaskDelegate.kt @@ -46,7 +46,6 @@ import java.io.File import java.io.ObjectInputStream import java.io.ObjectOutputStream import java.nio.file.Path -import java.util.ArrayList /** * Delegate for the [DexArchiveBuilderTask]. This is where the actual processing happens. Using the @@ -298,13 +297,13 @@ class DexArchiveBuilderTaskDelegate( } ClassFileInput.CLASS_MATCHER.test(it.normalizedPath) -> { // We are in DexFilePerClassFile output mode - DexFilePerClassFile.getDexOutputRelativePathsOfClassFile( + DexFilePerClassFile.getDexOutputRelativePath( classFileRelativePath = it.normalizedPath - ).forEach { outputRelativePath -> + ).let { outputRelativePath -> FileUtils.deleteIfExists(outputDir.resolve(outputRelativePath)) } globalSyntheticsDir?.let {globalSyntheticsDir -> - DexFilePerClassFile.getGlobalOutputRelativePathOfClassFile( + DexFilePerClassFile.getGlobalSyntheticOutputRelativePath( it.normalizedPath ).let { outputRelativePath -> FileUtils.deleteIfExists(globalSyntheticsDir.resolve(outputRelativePath)) diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/KmpTaskManager.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/KmpTaskManager.kt index dc2335a4f4..29b3983220 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/KmpTaskManager.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/KmpTaskManager.kt @@ -16,35 +16,67 @@ package com.android.build.gradle.internal.tasks +import com.android.build.api.artifact.ScopedArtifact import com.android.build.api.artifact.SingleArtifact +import com.android.build.api.artifact.impl.InternalScopedArtifact import com.android.build.api.artifact.impl.InternalScopedArtifacts +import com.android.build.api.component.impl.KmpAndroidTestImpl +import com.android.build.api.component.impl.KmpUnitTestImpl +import com.android.build.api.variant.ScopedArtifacts +import com.android.build.gradle.internal.AndroidTestTaskManager import com.android.build.gradle.internal.TaskManager import com.android.build.gradle.internal.component.ComponentCreationConfig import com.android.build.gradle.internal.component.KmpCreationConfig +import com.android.build.gradle.internal.coverage.JacocoConfigurations +import com.android.build.gradle.internal.coverage.JacocoReportTask import com.android.build.gradle.internal.publishing.AndroidArtifacts import com.android.build.gradle.internal.res.GenerateEmptyResourceFilesTask +import com.android.build.gradle.internal.res.GenerateLibraryRFileTask import com.android.build.gradle.internal.services.R8ParallelBuildService +import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfig import com.android.build.gradle.internal.tasks.factory.TaskConfigAction import com.android.build.gradle.internal.tasks.factory.TaskProviderCallback -import com.android.build.gradle.internal.tasks.factory.dependsOn import com.android.build.gradle.internal.tasks.factory.registerTask import com.android.build.gradle.options.IntegerOption import com.android.build.gradle.tasks.BundleAar import com.android.build.gradle.tasks.ProcessLibraryManifest +import com.android.build.gradle.tasks.ProcessTestManifest import com.android.build.gradle.tasks.ZipMergingTask +import com.android.build.gradle.tasks.factory.AndroidUnitTest import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.tasks.TaskProvider +import org.gradle.testing.jacoco.plugins.JacocoPlugin -class KmpTaskManager { +class KmpTaskManager( + project: Project, + global: GlobalTaskCreationConfig +): TaskManager( + project, + global +) { + + override val javaResMergingScopes = setOf( + InternalScopedArtifacts.InternalScope.LOCAL_DEPS, + ) + + var hasCreatedTasks = false fun createTasks( project: Project, variant: KmpCreationConfig, + unitTest: KmpUnitTestImpl?, + androidTest: KmpAndroidTestImpl?, ) { createMainVariantTasks(project, variant) + unitTest?.let { createUnitTestTasks(project, unitTest) } + androidTest?.let { + createAndroidTestTasks(project, androidTest) + } variant.publishBuildArtifacts() + + hasCreatedTasks = true } private fun createMainVariantTasks( @@ -85,31 +117,58 @@ class KmpTaskManager { project.tasks.registerTask(ProcessJavaResTask.CreationAction(variant)) project.tasks.registerTask( MergeJavaResourceTask.CreationAction( - setOf(InternalScopedArtifacts.InternalScope.LOCAL_DEPS), + javaResMergingScopes, variant.packaging, variant ) ) if (variant.optimizationCreationConfig.minifiedEnabled) { - + project.tasks.registerTask( + GenerateLibraryProguardRulesTask.CreationAction(variant) + ) R8ParallelBuildService.RegistrationAction( project, variant.services.projectOptions.get(IntegerOption.R8_MAX_WORKERS) ).execute() - val r8Task = project.tasks.registerTask( + project.tasks.registerTask( R8Task.CreationAction( variant, isTestApplication = false, addCompileRClass = false ) ) + } - val checkFilesTask = - project.tasks.registerTask( - CheckProguardFiles.CreationAction(variant) + project.tasks.registerTask(MergeGeneratedProguardFilesCreationAction(variant)) + project.tasks.registerTask(MergeConsumerProguardFilesTask.CreationAction(variant)) + project.tasks.registerTask(ExportConsumerProguardFilesTask.CreationAction(variant)) + + // No jacoco transformation for kmp variants, however, we need to publish the classes + // pre transformation as the artifact is used in the jacoco report task. + variant.artifacts.forScope(ScopedArtifacts.Scope.PROJECT) + .publishCurrent( + ScopedArtifact.CLASSES, + InternalScopedArtifact.PRE_JACOCO_TRANSFORMED_CLASSES, + ) + + if (variant.isAndroidTestCoverageEnabled) { + val jacocoTask = project.tasks.registerTask( + JacocoTask.CreationAction(variant) + ) + // in case of library, we never want to publish the jacoco instrumented classes, so + // we basically fork the CLASSES into a specific internal type that is consumed + // by the jacoco report task. + variant.artifacts.forScope(ScopedArtifacts.Scope.PROJECT) + .use(jacocoTask) + .toFork( + type = ScopedArtifact.CLASSES, + inputJars = { a -> a.jarsWithIdentity.inputJars }, + inputDirectories = JacocoTask::classesDir, + intoJarDirectory = JacocoTask::outputForJars, + intoDirDirectory = JacocoTask::outputForDirs, + intoType = InternalScopedArtifact.JACOCO_TRANSFORMED_CLASSES ) - r8Task.dependsOn(checkFilesTask) } // Add a task to create the AAR metadata file @@ -148,9 +207,56 @@ class KmpTaskManager { project.tasks.getByName("assemble").dependsOn(variant.taskContainer.assembleTask) } + private fun createUnitTestTasks( + project: Project, + component: KmpUnitTestImpl + ) { + createAnchorTasks(project, component) + + project.tasks.registerTask(ProcessTestManifest.CreationAction(component)) + project.tasks.registerTask( + GenerateLibraryRFileTask.TestRuntimeStubRClassCreationAction( + component + ) + ) + project.tasks.registerTask(ProcessJavaResTask.CreationAction(component)) + + if (component.isUnitTestCoverageEnabled) { + project.pluginManager.apply(JacocoPlugin::class.java) + } + project.tasks.registerTask(AndroidUnitTest.CreationAction(component)) + if (component.isUnitTestCoverageEnabled) { + val ant = JacocoConfigurations.getJacocoAntTaskConfiguration( + project, JacocoTask.getJacocoVersion(component) + ) + project.plugins.withType(JacocoPlugin::class.java) { + // Jacoco plugin is applied and test coverage enabled, generate coverage report. + project.tasks.registerTask( + JacocoReportTask.CreateActionUnitTest(component, ant) + ) + } + } + } + + private fun createAndroidTestTasks( + project: Project, + component: KmpAndroidTestImpl + ) { + createAnchorTasks(project, component, false) + + AndroidTestTaskManager( + project = project, + globalConfig = component.global, + ).also { + it.createTopLevelTasks() + it.createTasks(component) + } + } + private fun createAnchorTasks( project: Project, - component: ComponentCreationConfig + component: ComponentCreationConfig, + createPreBuildTask: Boolean = true ) { project.tasks.registerTask( component.computeTaskName("assemble"), @@ -170,6 +276,9 @@ class KmpTaskManager { } ) - project.tasks.registerTask(TaskManager.PreBuildCreationAction(component)) + if (createPreBuildTask) { + project.tasks.registerTask(PreBuildCreationAction(component)) + createDependencyStreams(component) + } } } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeArtProfileTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeArtProfileTask.kt index 42f9e257dd..008b2a62aa 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeArtProfileTask.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeArtProfileTask.kt @@ -30,6 +30,7 @@ import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.Directory import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.ListProperty +import org.gradle.api.tasks.Classpath import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity @@ -40,8 +41,7 @@ import org.gradle.work.DisableCachingByDefault @BuildAnalyzer(primaryTaskCategory = TaskCategory.ART_PROFILE, secondaryTaskCategories = [TaskCategory.MERGING]) abstract class MergeArtProfileTask: MergeFileTask() { - @get:InputFiles - @get:PathSensitive(PathSensitivity.RELATIVE) + @get:Classpath // The order of `inputFiles` is important abstract override val inputFiles: ConfigurableFileCollection // Use InputFiles rather than InputFile to allow the file not to exist @@ -77,7 +77,7 @@ abstract class MergeArtProfileTask: MergeFileTask() { } override fun run() { - mergeFiles(parameters.inputFiles.files, parameters.outputFile.get().asFile) + mergeFiles(parameters.inputFiles.files.filter { it.isFile }, parameters.outputFile.get().asFile) } } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeFileTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeFileTask.kt index 660ed46cdb..0bd61bb44a 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeFileTask.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeFileTask.kt @@ -18,14 +18,10 @@ package com.android.build.gradle.internal.tasks import com.android.build.gradle.internal.caching.DisabledCachingReason.SIMPLE_MERGING_TASK import com.android.buildanalyzer.common.TaskCategory import com.android.utils.FileUtils -import com.google.common.base.Charsets -import com.google.common.io.Files import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.RegularFileProperty -import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Classpath import org.gradle.api.tasks.OutputFile -import org.gradle.api.tasks.PathSensitive -import org.gradle.api.tasks.PathSensitivity import org.gradle.work.DisableCachingByDefault import java.io.File import java.io.IOException @@ -37,41 +33,29 @@ import java.io.IOException @BuildAnalyzer(primaryTaskCategory = TaskCategory.MISC, secondaryTaskCategories = [TaskCategory.MERGING]) abstract class MergeFileTask : NonIncrementalTask() { - @get:InputFiles - @get:PathSensitive(PathSensitivity.RELATIVE) + @get:Classpath // The order of `inputFiles` is important abstract val inputFiles: ConfigurableFileCollection @get:OutputFile abstract val outputFile: RegularFileProperty - @Throws(IOException::class) override fun doTaskAction() { - mergeFiles(inputFiles.files, outputFile.get().asFile) + mergeFiles(inputFiles.files.filter { it.isFile }, outputFile.get().asFile) } companion object { - fun mergeFiles(inputFiles: Collection<File>, output: File) { - // filter out any non-existent files - val existingFiles = inputFiles.filter { it.isFile() } + fun mergeFiles(inputFiles: Collection<File>, outputFile: File) { + FileUtils.deleteIfExists(outputFile) - if (existingFiles.size == 1) { - FileUtils.copyFile(existingFiles[0], output) + // If there are no input files, we can either (1) not write the output file, or (2) + // write an empty output file. Let's go with option (1). + if (inputFiles.isEmpty()) { return } - // first delete the current file - FileUtils.deleteIfExists(output) - - // no input? done. - if (existingFiles.isEmpty()) { - return - } - - // otherwise put all the files together - for (file in existingFiles) { - val content = Files.toString(file, Charsets.UTF_8) - Files.append("$content\n", output, Charsets.UTF_8) + outputFile.printWriter().buffered().use { writer -> + inputFiles.joinTo(writer, "\n") { it.readText() } } } } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeGeneratedProguardFilesCreationAction.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeGeneratedProguardFilesCreationAction.kt index 651f1c5a70..5e9a5079d8 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeGeneratedProguardFilesCreationAction.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeGeneratedProguardFilesCreationAction.kt @@ -24,12 +24,9 @@ import com.android.build.gradle.internal.scope.InternalArtifactType import com.android.build.gradle.internal.scope.getDirectories import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction import com.android.build.gradle.internal.utils.fromDisallowChanges -import com.android.builder.dexing.isProguardRule +import com.android.build.gradle.internal.utils.getOrderedFileTree import org.gradle.api.file.Directory -import org.gradle.api.file.FileTree import org.gradle.api.tasks.TaskProvider -import java.io.File -import java.util.StringTokenizer /** * Configuration action for a task to merge generated proguard files. @@ -72,11 +69,8 @@ class MergeGeneratedProguardFilesCreationAction( directory, SdkConstants.META_INF, SdkConstants.PROGUARD_RULES_FOLDER_NAME - ) + )?.getOrderedFileTree() } - .map { - it.asFileTree - } } ) } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeJavaResourceTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeJavaResourceTask.kt index ebd9b504ec..5e57f05a4d 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeJavaResourceTask.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeJavaResourceTask.kt @@ -408,8 +408,7 @@ private fun getExternalLibJavaRes( AndroidArtifacts.ArtifactType.JAVA_RES ) ) - } - if (mergeScopes.contains(InternalScopedArtifacts.InternalScope.LOCAL_DEPS)) { + } else if (mergeScopes.contains(InternalScopedArtifacts.InternalScope.LOCAL_DEPS)) { externalLibJavaRes.from(creationConfig.computeLocalPackagedJars()) } return externalLibJavaRes @@ -418,5 +417,5 @@ private fun getExternalLibJavaRes( /** Returns true if anything's been added to the annotation processor configuration. */ fun projectHasAnnotationProcessors(creationConfig: ComponentCreationConfig): Boolean { val config = creationConfig.variantDependencies.annotationProcessorConfiguration - return config.incoming.dependencies.isNotEmpty() + return config != null && config.incoming.dependencies.isNotEmpty() } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/R8Task.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/R8Task.kt index f8d4162626..060991af3e 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/R8Task.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/R8Task.kt @@ -17,7 +17,6 @@ package com.android.build.gradle.internal.tasks import com.android.build.api.artifact.MultipleArtifact -import com.android.build.api.transform.Format import com.android.build.gradle.internal.LoggerWrapper import com.android.build.gradle.internal.PostprocessingFeatures import com.android.build.gradle.internal.api.BaselineProfiles @@ -228,6 +227,7 @@ abstract class R8Task @Inject constructor( @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) + @get:Optional abstract val baselineProfilesSources: ListProperty<RegularFile> @get:Optional @@ -424,6 +424,7 @@ abstract class R8Task @Inject constructor( task.coreLibDesugarConfig.set(getDesugarLibConfig(creationConfig.services)) } } + creationConfig.sources.baselineProfiles { task.baselineProfilesSources.setDisallowChanges( it.all.map { directories -> @@ -528,8 +529,8 @@ abstract class R8Task @Inject constructor( } val inputBaselineProfileForStartupOptimization = if (enableDexStartupOptimization.get()) { - val sources = baselineProfilesSources.get() - if (sources.isEmpty()) { + val sources = baselineProfilesSources.orNull + if (sources.isNullOrEmpty()) { throw RuntimeException(""" Dex optimization based on startup profile has been turned on with flag ${ModuleBooleanPropertyKeys.R8_DEX_STARTUP_OPTIMIZATION.keyValue} but there are no source folders. @@ -672,24 +673,19 @@ abstract class R8Task @Inject constructor( ) { val logger = LoggerWrapper.getLogger(R8Task::class.java) - val r8OutputType: R8OutputType - val outputFormat: Format - if (isAar) { - r8OutputType = R8OutputType.CLASSES - outputFormat = Format.JAR + val r8OutputType = if (isAar) { + R8OutputType.CLASSES } else { - r8OutputType = R8OutputType.DEX - outputFormat = Format.DIRECTORY + R8OutputType.DEX } FileUtils.deleteIfExists(outputResources) - when (outputFormat) { - Format.DIRECTORY -> { - FileUtils.cleanOutputDir(output) - featureDexDir?.let { FileUtils.cleanOutputDir(it) } - featureJavaResourceOutputDir?.let { FileUtils.cleanOutputDir(it) } - } - Format.JAR -> FileUtils.deleteIfExists(output) + if (isAar) { + FileUtils.deleteIfExists(output) + } else { + FileUtils.cleanOutputDir(output) + featureDexDir?.let { FileUtils.cleanOutputDir(it) } + featureJavaResourceOutputDir?.let { FileUtils.cleanOutputDir(it) } } val proguardOutputFiles = diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/factory/GlobalTaskCreationConfig.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/factory/GlobalTaskCreationConfig.kt index 10c37c843a..fc4a97ae8c 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/factory/GlobalTaskCreationConfig.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/factory/GlobalTaskCreationConfig.kt @@ -139,4 +139,12 @@ interface GlobalTaskCreationConfig: BootClasspathConfig { val settingsOptions: SettingsOptions val buildAnalyzerIssueReporter: BuildAnalyzerIssueReporter? + + /** + * Returns the API to which device/emulator we're deploying via the IDE or null if not. + * Can be used to optimize some build steps when deploying via the IDE. + * + * This has no relation with targetSdkVersion from build.gradle/manifest. + */ + val targetDeployApiFromIDE: Int? } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/factory/GlobalTaskCreationConfigImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/factory/GlobalTaskCreationConfigImpl.kt index 264eb784c6..9731ba4d34 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/factory/GlobalTaskCreationConfigImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/factory/GlobalTaskCreationConfigImpl.kt @@ -46,6 +46,7 @@ import com.android.build.gradle.internal.services.VersionedSdkLoaderService import com.android.build.gradle.internal.services.getBuildService import com.android.build.gradle.internal.testing.ManagedDeviceRegistry import com.android.build.gradle.options.BooleanOption +import com.android.build.gradle.options.IntegerOption import com.android.build.gradle.options.StringOption import com.android.builder.core.LibraryRequest import com.android.builder.testing.api.DeviceProvider @@ -243,4 +244,7 @@ class GlobalTaskCreationConfigImpl( services.buildServiceRegistry ) } + + override val targetDeployApiFromIDE: Int? = + services.projectOptions.get(IntegerOption.IDE_TARGET_DEVICE_API) } diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/factory/KmpGlobalTaskCreationConfigImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/factory/KmpGlobalTaskCreationConfigImpl.kt index 499aef0990..d4e4b602de 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/factory/KmpGlobalTaskCreationConfigImpl.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/factory/KmpGlobalTaskCreationConfigImpl.kt @@ -27,8 +27,8 @@ import com.android.build.api.dsl.Installation import com.android.build.api.dsl.Lint import com.android.build.api.dsl.Prefab import com.android.build.api.dsl.Splits -import com.android.build.api.dsl.TestCoverage import com.android.build.api.dsl.TestOptions +import com.android.build.gradle.internal.KotlinMultiplatformCompileOptionsImpl import com.android.build.gradle.internal.SdkComponentsBuildService import com.android.build.gradle.internal.attribution.BuildAnalyzerIssueReporter import com.android.build.gradle.internal.core.SettingsOptions @@ -45,14 +45,13 @@ import com.android.build.gradle.internal.services.getBuildService import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfigImpl.Companion.toExecutionEnum import com.android.build.gradle.internal.testing.ManagedDeviceRegistry import com.android.build.gradle.options.BooleanOption +import com.android.build.gradle.options.IntegerOption import com.android.build.gradle.options.StringOption import com.android.builder.core.LibraryRequest import com.android.builder.testing.api.DeviceProvider import com.android.builder.testing.api.TestServer import com.android.repository.Revision -import com.google.common.base.Charsets import org.gradle.api.Action -import org.gradle.api.JavaVersion import org.gradle.api.Project import org.gradle.api.artifacts.Configuration import org.gradle.api.attributes.AttributeContainer @@ -68,7 +67,8 @@ class KmpGlobalTaskCreationConfigImpl( compileSdkVersionProvider: () -> String, buildToolsVersionProvider: () -> Revision, private val androidJar: Configuration, - override val services: BaseServices + override val services: BaseServices, + override val settingsOptions: SettingsOptions ): GlobalTaskCreationConfig, BootClasspathConfig by bootClasspathConfig { init { @@ -118,30 +118,9 @@ class KmpGlobalTaskCreationConfigImpl( BuildAnalyzerIssueReporter(services.projectOptions, services.buildServiceRegistry) } - // TODO(b/267309622): Get this from kotlin plugin - override val compileOptions: CompileOptions - get() = object: CompileOptions { - override var sourceCompatibility = JavaVersion.VERSION_11 - - override fun sourceCompatibility(sourceCompatibility: Any) { - throw IllegalAccessException("Not supported for kmp") - } - - override var targetCompatibility: JavaVersion - get() = JavaVersion.VERSION_1_8 - set(value) {} - - override fun targetCompatibility(targetCompatibility: Any) { - throw IllegalAccessException("Not supported for kmp") - } - - override var encoding: String - get() = Charsets.UTF_8.name() - set(value) {} - override var isCoreLibraryDesugaringEnabled: Boolean - get() = false - set(value) {} - } + override val compileOptions: CompileOptions = KotlinMultiplatformCompileOptionsImpl( + extension + ) override val manifestArtifactType: InternalArtifactType<Directory> get() = if (services.projectOptions[BooleanOption.IDE_DEPLOY_AS_INSTANT_APP]) @@ -189,6 +168,11 @@ class KmpGlobalTaskCreationConfigImpl( return project.configurations.detachedConfiguration(fakeDependency) } + override val targetDeployApiFromIDE: Int? = + services.projectOptions.get(IntegerOption.IDE_TARGET_DEVICE_API) + + override val testCoverage = extension.testCoverage + // Unsupported properties // TODO: Refactor the parent interface so that we don't have to override these values to avoid // accidental calls. @@ -217,8 +201,6 @@ class KmpGlobalTaskCreationConfigImpl( override val splits: Splits get() = throw IllegalAccessException("Not supported for kmp") - override val testCoverage: TestCoverage - get() = throw IllegalAccessException("Not supported for kmp") override val legacyLanguageSplitOptions: LanguageSplitOptions get() = throw IllegalAccessException("Not supported for kmp") override val localCustomLintChecks: FileCollection @@ -227,8 +209,6 @@ class KmpGlobalTaskCreationConfigImpl( get() = throw IllegalAccessException("Not supported for kmp") override val lintPublish: Configuration get() = throw IllegalAccessException("Not supported for kmp") - override val settingsOptions: SettingsOptions - get() = throw IllegalAccessException("Not supported for kmp") override val externalNativeBuild: ExternalNativeBuild get() = throw IllegalAccessException("Not supported for kmp") override val lintOptions: Lint diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/manifest/ManifestHelper.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/manifest/ManifestHelper.kt index cc8c3282b0..e40260e1c1 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/manifest/ManifestHelper.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/manifest/ManifestHelper.kt @@ -38,6 +38,10 @@ import java.io.IOException * @param packageOverride the value used for the merged manifest's package attribute, which is * the applicationId for apps and the namespace for libraries. * @param namespace the namespace, used to create or shorten fully qualified class names + * @param extractNativeLibs the value to assign to the injected android:extractNativeLibs attribute. + * The attribute will not be injected if null. Even if not null, the + * attribute will not be modified if it's already present in the main + * manifest or an overlay manifest. */ fun mergeManifests( mainManifest: File, @@ -54,6 +58,7 @@ fun mergeManifests( targetSdkVersion: String?, maxSdkVersion: Int?, testOnly: Boolean, + extractNativeLibs: Boolean?, outMergedManifestLocation: String?, outAaptSafeManifestLocation: String?, mergeType: ManifestMerger2.MergeType, @@ -101,9 +106,16 @@ fun mergeManifests( setInjectableValues( manifestMergerInvoker, - packageOverride, versionCode, versionName, - minSdkVersion, targetSdkVersion, maxSdkVersion, - injectProfileable, testOnly, compileSdk + packageOverride, + versionCode, + versionName, + minSdkVersion, + targetSdkVersion, + maxSdkVersion, + injectProfileable, + testOnly, + compileSdk, + extractNativeLibs ) val mergingReport = manifestMergerInvoker.merge() @@ -203,7 +215,8 @@ private fun setInjectableValues( maxSdkVersion: Int?, profileable: Boolean, testOnly: Boolean, - compileSdk: Int? + compileSdk: Int?, + extractNativeLibs: Boolean? ) { if (packageOverride != null && packageOverride.isNotEmpty()) { @@ -238,6 +251,15 @@ private fun setInjectableValues( if (testOnly) { invoker.setOverride(ManifestSystemProperty.Application.TEST_ONLY, "true") } + if (extractNativeLibs != null) { + // android:extractNativeLibs unrecognized if using compile SDK < 23. + if (compileSdk == null || compileSdk >= 23) { + invoker.setOverride( + ManifestSystemProperty.Application.EXTRACT_NATIVE_LIBS, + extractNativeLibs.toString() + ) + } + } } /** diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/utils/GradleApiUtils.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/utils/GradleApiUtils.kt new file mode 100644 index 0000000000..bd2e476faf --- /dev/null +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/utils/GradleApiUtils.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 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.build.gradle.internal.utils + +import org.gradle.api.file.Directory +import java.io.File + +/** + * Returns all regular files in this [Directory] in stable order (even across platforms). + * + * Similar to [Directory.getAsFileTree], this method + * - returns regular files only + * - includes regular files in subdirectories + * + * Unlike [Directory.getAsFileTree], this method + * - ensures stable order across platforms (by sorting files based on [File.invariantSeparatorsPath]). + * This is the main reason we introduced this utility method. + * See https://github.com/gradle/gradle/issues/21379 for more context. + * - is not lazy (files are resolved immediately) -- we can make it lazy later if necessary + */ +fun Directory.getOrderedFileTree(): List<File> { + return asFileTree.files.sortedBy { it.invariantSeparatorsPath } +} diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/options/BooleanOption.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/options/BooleanOption.kt index ffc859f9fb..471fa6e152 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/options/BooleanOption.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/options/BooleanOption.kt @@ -181,6 +181,7 @@ enum class BooleanOption( ENABLE_CMAKE_BUILD_COHABITATION("android.enableCmakeBuildCohabitation", false, FeatureStage.Experimental), ENABLE_PROGUARD_RULES_EXTRACTION("android.proguard.enableRulesExtraction", true, FeatureStage.Experimental), USE_DEPENDENCY_CONSTRAINTS("android.dependency.useConstraints", true, FeatureStage.Experimental), + EXCLUDE_LIBRARY_COMPONENTS_FROM_CONSTRAINTS("android.experimental.dependency.excludeLibraryComponentsFromConstraints", false, FeatureStage.Experimental), ENABLE_DUPLICATE_CLASSES_CHECK("android.enableDuplicateClassesCheck", true, FeatureStage.Experimental), MINIMAL_KEEP_RULES("android.useMinimalKeepRules", true, FeatureStage.Experimental), EXCLUDE_RES_SOURCES_FOR_RELEASE_BUNDLES("android.bundle.excludeResSourcesForRelease", true, FeatureStage.Experimental), @@ -216,6 +217,14 @@ enum class BooleanOption( VERIFY_AAR_CLASSES("android.experimental.verifyLibraryClasses", false, FeatureStage.Experimental), DISABLE_COMPILE_SDK_CHECKS("android.experimental.disableCompileSdkChecks", false, FeatureStage.Experimental), ADDITIONAL_ARTIFACTS_IN_MODEL("android.experimental.additionalArtifactsInModel", false, FeatureStage.Experimental), + + // Whether to suppress warnings about android:extractNativeLibs set to true in dependencies + SUPPRESS_EXTRACT_NATIVE_LIBS_WARNINGS( + "android.experimental.suppressExtractNativeLibsWarnings", + false, + FeatureStage.Experimental + ), + /* ------------------------ * SOFTLY-ENFORCED FEATURES */ diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryManifestMergerTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryManifestMergerTask.kt index 92349e3457..896b19b311 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryManifestMergerTask.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryManifestMergerTask.kt @@ -132,6 +132,7 @@ abstract class FusedLibraryManifestMergerTask : ManifestProcessorTask() { targetSdkVersion = null, maxSdkVersion = null, testOnly = false, + extractNativeLibs = null, outMergedManifestLocation = outMergedManifestLocation.get().asFile.absolutePath, outAaptSafeManifestLocation = null, mergeType = ManifestMerger2.MergeType.FUSED_LIBRARY, diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PackageAndroidArtifact.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PackageAndroidArtifact.java index 7857c47f98..f9d12d6917 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PackageAndroidArtifact.java +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PackageAndroidArtifact.java @@ -42,6 +42,7 @@ import com.android.build.api.variant.impl.VariantOutputImpl; import com.android.build.gradle.internal.LoggerWrapper; import com.android.build.gradle.internal.component.ApkCreationConfig; import com.android.build.gradle.internal.component.ApplicationCreationConfig; +import com.android.build.gradle.internal.component.KmpComponentCreationConfig; import com.android.build.gradle.internal.component.TestComponentCreationConfig; import com.android.build.gradle.internal.core.Abi; import com.android.build.gradle.internal.dependency.AndroidAttributes; @@ -1263,10 +1264,14 @@ public abstract class PackageAndroidArtifact extends NewIncrementalTask { .set(creationConfig.getServices().getProjectInfo().getProjectBaseName()); packageAndroidArtifact.getProjectBaseName().disallowChanges(); packageAndroidArtifact.manifestType = manifestType; - packageAndroidArtifact.buildTargetAbi = - creationConfig.getGlobal().getSplits().getAbi().isEnable() - ? projectOptions.get(StringOption.IDE_BUILD_TARGET_ABI) - : null; + if (creationConfig instanceof KmpComponentCreationConfig) { + packageAndroidArtifact.buildTargetAbi = null; + } else { + packageAndroidArtifact.buildTargetAbi = + creationConfig.getGlobal().getSplits().getAbi().isEnable() + ? projectOptions.get(StringOption.IDE_BUILD_TARGET_ABI) + : null; + } if (creationConfig.getComponentType().isDynamicFeature()) { packageAndroidArtifact .getBaseModuleMetadata() diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessApplicationManifest.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessApplicationManifest.kt index 8a6adbef0d..c9aa5995f6 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessApplicationManifest.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessApplicationManifest.kt @@ -190,17 +190,12 @@ abstract class ProcessApplicationManifest : ManifestProcessorTask() { targetSdkVersion.orNull, maxSdkVersion.orNull, testOnly.get(), - mergedManifest.get().asFile.absolutePath /* aaptFriendlyManifestOutputFile */, + extractNativeLibs = jniLibsUseLegacyPackaging.get(), + mergedManifest.get().asFile.absolutePath, null /* outAaptSafeManifestLocation */, ManifestMerger2.MergeType.APPLICATION, manifestPlaceholders.get(), - optionalFeatures.get().plus( - mutableListOf<Invoker.Feature>().also { - if (!jniLibsUseLegacyPackaging.get()) { - it.add(Invoker.Feature.DO_NOT_EXTRACT_NATIVE_LIBS) - } - } - ), + optionalFeatures.get(), dependencyFeatureNames, generatedLocaleConfigAttribute = if (addLocaleConfigAttribute.get()) { generateLocaleConfigManifestAttribute(LOCALE_CONFIG_FILE_NAME) @@ -433,16 +428,11 @@ abstract class ProcessApplicationManifest : ManifestProcessorTask() { task.applicationId.set(creationConfig.applicationId) task.applicationId.disallowChanges() - val compileSdkHashString = - (creationConfig as? ApplicationCreationConfig)?.global?.compileSdkHashString - task.compileSdk.setDisallowChanges( - if (compileSdkHashString != null) { - parseTargetHash(compileSdkHashString).apiLevel - } else { - null - } - ) + task.compileSdk + .setDisallowChanges( + parseTargetHash(creationConfig.global.compileSdkHashString).apiLevel + ) task.minSdkVersion.setDisallowChanges(creationConfig.minSdk.getApiString()) task.targetSdkVersion .setDisallowChanges( @@ -581,22 +571,24 @@ abstract class ProcessApplicationManifest : ManifestProcessorTask() { features.add(Invoker.Feature.ADVANCED_PROFILING) } } + val projectOptions = creationConfig.services.projectOptions if (creationConfig.dexingCreationConfig.dexingType === DexingType.LEGACY_MULTIDEX) { features.add( - if (creationConfig.services.projectOptions[BooleanOption.USE_ANDROID_X]) { + if (projectOptions[BooleanOption.USE_ANDROID_X]) { Invoker.Feature.ADD_ANDROIDX_MULTIDEX_APPLICATION_IF_NO_NAME } else { Invoker.Feature.ADD_SUPPORT_MULTIDEX_APPLICATION_IF_NO_NAME }) } - if (creationConfig.services.projectOptions[BooleanOption.ENFORCE_UNIQUE_PACKAGE_NAMES] - ) { + if (projectOptions[BooleanOption.ENFORCE_UNIQUE_PACKAGE_NAMES]) { features.add(Invoker.Feature.ENFORCE_UNIQUE_PACKAGE_NAME) } - if (creationConfig.services.projectOptions[BooleanOption.DISABLE_MINSDKLIBRARY_CHECK]) { + if (projectOptions[BooleanOption.DISABLE_MINSDKLIBRARY_CHECK]) { features.add(Invoker.Feature.DISABLE_MINSDKLIBRARY_CHECK) } - features.add(Invoker.Feature.VALIDATE_EXTRACT_NATIVE_LIBS_ATTRIBUTE) + if (!projectOptions[BooleanOption.SUPPRESS_EXTRACT_NATIVE_LIBS_WARNINGS]) { + features.add(Invoker.Feature.VALIDATE_EXTRACT_NATIVE_LIBS_FROM_DEPENDENCIES) + } return if (features.isEmpty()) EnumSet.noneOf(Invoker.Feature::class.java) else EnumSet.copyOf(features) diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessLibraryManifest.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessLibraryManifest.kt index 884681e0bc..a9c3c5ecce 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessLibraryManifest.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessLibraryManifest.kt @@ -166,6 +166,7 @@ abstract class ProcessLibraryManifest : ManifestProcessorTask() { parameters.targetSdkVersion.orNull, parameters.maxSdkVersion.orNull, testOnly = false, + extractNativeLibs = null, parameters.manifestOutputFile.asFile.get().absolutePath, parameters.aaptFriendlyManifestOutputFile.asFile.orNull?.absolutePath /* outInstantRunManifestLocation */, ManifestMerger2.MergeType.LIBRARY /* outInstantAppManifestLocation */, diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessMultiApkApplicationManifest.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessMultiApkApplicationManifest.kt index 9cb9c3fc67..0787d2b575 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessMultiApkApplicationManifest.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessMultiApkApplicationManifest.kt @@ -152,6 +152,7 @@ abstract class ProcessMultiApkApplicationManifest: ManifestProcessorTask() { null, null, testOnly = false, + extractNativeLibs = null, mergedManifestOutputFile.absolutePath /* aaptFriendlyManifestOutputFile */, null, ManifestMerger2.MergeType.APPLICATION, diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessPackagedManifestTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessPackagedManifestTask.kt index 7e3541e18d..daa161397e 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessPackagedManifestTask.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessPackagedManifestTask.kt @@ -145,6 +145,7 @@ abstract class ProcessPackagedManifestTask @Inject constructor( targetSdkVersion = null, maxSdkVersion = null, testOnly = false, + extractNativeLibs = null, outMergedManifestLocation = outputFile.path, outAaptSafeManifestLocation = null, mergeType = ManifestMerger2.MergeType.APPLICATION, diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessTestManifest.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessTestManifest.kt index 5cb65bcd4c..a9413b945c 100644 --- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessTestManifest.kt +++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessTestManifest.kt @@ -34,6 +34,7 @@ import com.android.build.gradle.internal.scope.InternalArtifactType.PACKAGED_MAN import com.android.build.gradle.internal.tasks.BuildAnalyzer import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction import com.android.build.gradle.internal.tasks.manifest.ManifestProviderImpl +import com.android.build.gradle.internal.utils.parseTargetHash import com.android.build.gradle.internal.utils.setDisallowChanges import com.android.build.gradle.tasks.ProcessApplicationManifest.Companion.getArtifactName import com.android.buildanalyzer.common.TaskCategory @@ -109,6 +110,7 @@ abstract class ProcessTestManifest : ManifestProcessorTask() { namespace.get(), minSdkVersion.get(), targetSdkVersion.orNull, + compileSdk.orNull, testedApplicationId.get(), instrumentationRunner.get(), handleProfiling.orNull, @@ -118,9 +120,8 @@ abstract class ProcessTestManifest : ManifestProcessorTask() { computeProviders(), placeholdersValues.get(), navJsons, - jniLibsUseLegacyPackaging.orNull, + extractNativeLibs.orNull, debuggable.get(), - validateExtractNativeLibsAttribute.get(), manifestOutputFile, tmpDir.get().asFile ) @@ -144,6 +145,7 @@ abstract class ProcessTestManifest : ManifestProcessorTask() { * @param namespace the namespace of the test application * @param minSdkVersion the minSdkVersion of the test application * @param targetSdkVersion the targetSdkVersion of the test application + * @param compileSdk the compile SDK API level of the test application * @param testedApplicationId the application id of the tested application * @param instrumentationRunner the name of the instrumentation runner * @param handleProfiling whether or not the Instrumentation object will turn profiling on and @@ -155,13 +157,10 @@ abstract class ProcessTestManifest : ManifestProcessorTask() { * @param manifestProviders the manifest providers * @param manifestPlaceholders used placeholders in the manifest * @param navigationJsons the list of navigation JSON files - * @param jniLibsUseLegacyPackaging whether or not native libraries will be compressed in the - * APK. If false, native libraries will be uncompressed, so `android:extractNativeLibs="false"` - * will be injected in the manifest's application tag, unless that attribute is already - * explicitly set. If true, nothing if injected. + * @param extractNativeLibs the value to assign to the injected android:extractNativeLibs + * attribute. The attribute will not be injected if null. Even if not null, the attribute will + * not be modified if it's already present in the test's source manifest. * @param debuggable whether the variant is debuggable - * @param validateExtractNativeLibsAttribute whether the application element's - * [SdkConstants.ATTR_EXTRACT_NATIVE_LIBS] attribute will be validated for the source manifest. * @param outManifest the output location for the merged manifest * @param tmpDir temporary dir used for processing */ @@ -170,6 +169,7 @@ abstract class ProcessTestManifest : ManifestProcessorTask() { namespace: String, minSdkVersion: String, targetSdkVersion: String?, + compileSdk: Int?, testedApplicationId: String, instrumentationRunner: String, handleProfiling: Boolean?, @@ -179,9 +179,8 @@ abstract class ProcessTestManifest : ManifestProcessorTask() { manifestProviders: List<ManifestProvider?>, manifestPlaceholders: Map<String?, Any?>, navigationJsons: Collection<File>, - jniLibsUseLegacyPackaging: Boolean?, + extractNativeLibs: Boolean?, debuggable: Boolean, - validateExtractNativeLibsAttribute: Boolean, outManifest: File, tmpDir: File ) { @@ -285,11 +284,6 @@ abstract class ProcessTestManifest : ManifestProcessorTask() { ManifestSystemProperty.UsesSdk.TARGET_SDK_VERSION, it ) } - if (validateExtractNativeLibsAttribute) { - intermediateInvoker.withFeatures( - ManifestMerger2.Invoker.Feature.VALIDATE_EXTRACT_NATIVE_LIBS_ATTRIBUTE - ) - } tempFile2 = File.createTempFile("tempFile2ProcessTestManifest", ".xml", tmpDir) handleMergingResult(intermediateInvoker.merge(), tempFile2, logger) generatedTestManifest = tempFile2 @@ -307,8 +301,14 @@ abstract class ProcessTestManifest : ManifestProcessorTask() { .setPlaceHolderValues(manifestPlaceholders) .addNavigationJsons(navigationJsons) .setNamespace(namespace) - if (jniLibsUseLegacyPackaging == false) { - finalInvoker.withFeatures(ManifestMerger2.Invoker.Feature.DO_NOT_EXTRACT_NATIVE_LIBS) + extractNativeLibs?.let { + // android:extractNativeLibs unrecognized if using compile SDK < 23. + if (compileSdk == null || compileSdk >= 23) { + finalInvoker.setOverride( + ManifestSystemProperty.Application.EXTRACT_NATIVE_LIBS, + it.toString() + ) + } } if (debuggable) { finalInvoker.withFeatures(ManifestMerger2.Invoker.Feature.DEBUGGABLE) @@ -413,7 +413,7 @@ abstract class ProcessTestManifest : ManifestProcessorTask() { @get:Optional @get:Input - abstract val jniLibsUseLegacyPackaging: Property<Boolean> + abstract val extractNativeLibs: Property<Boolean> @get:Input abstract val debuggable: Property<Boolean> @@ -423,7 +423,8 @@ abstract class ProcessTestManifest : ManifestProcessorTask() { abstract val manifestOverlays: ListProperty<File> @get:Input - abstract val validateExtractNativeLibsAttribute: Property<Boolean> + @get:Optional + abstract val compileSdk: Property<Int> /** * Compute the final list of providers based on the manifest file collection. @@ -532,22 +533,24 @@ abstract class ProcessTestManifest : ManifestProcessorTask() { } when (creationConfig) { is AndroidTestCreationConfig -> { - task.jniLibsUseLegacyPackaging.setDisallowChanges( + task.extractNativeLibs.setDisallowChanges( creationConfig.packaging.jniLibs.useLegacyPackaging ) } is TestVariantCreationConfig -> { - task.jniLibsUseLegacyPackaging.setDisallowChanges( + task.extractNativeLibs.setDisallowChanges( creationConfig.packaging.jniLibs.useLegacyPackaging ) } else -> { - task.jniLibsUseLegacyPackaging.disallowChanges() + task.extractNativeLibs.disallowChanges() } } task.debuggable.setDisallowChanges(creationConfig.debuggable) - task.validateExtractNativeLibsAttribute - .setDisallowChanges(creationConfig.componentType.isSeparateTestProject) + task.compileSdk + .setDisallowChanges( + parseTargetHash(creationConfig.global.compileSdkHashString).apiLevel + ) } } diff --git a/build-system/gradle-core/src/test/java/com/android/build/api/extension/impl/VariantSelectorImplTest.kt b/build-system/gradle-core/src/test/java/com/android/build/api/extension/impl/VariantSelectorImplTest.kt index a2c48875ce..39c45acc4e 100644 --- a/build-system/gradle-core/src/test/java/com/android/build/api/extension/impl/VariantSelectorImplTest.kt +++ b/build-system/gradle-core/src/test/java/com/android/build/api/extension/impl/VariantSelectorImplTest.kt @@ -87,16 +87,27 @@ internal class VariantSelectorImplTest { @Test fun testWithProductFlavor() { - val variantSelector = VariantSelectorImpl() - .withFlavor("dim1" to "flavor1") as VariantSelectorImpl + val flavorAndDimensionVariantSelector = VariantSelectorImpl() + .withFlavor("dim1" to "flavor1") + val variantSelectorWithoutPair = VariantSelectorImpl() + .withFlavor("dim3","flavor1") val flavor1Variant = Mockito.mock(ApplicationVariantBuilder::class.java) + val flavor2variant = Mockito.mock(ApplicationVariantBuilder::class.java) + val flavor1Dim3Variant = Mockito.mock(ApplicationVariantBuilder::class.java) + Mockito.`when`(flavor1Variant.productFlavors).thenReturn( listOf("dim1" to "flavor1", "dim2" to "flavor2")) - val flavor2variant = Mockito.mock(ApplicationVariantBuilder::class.java) Mockito.`when`(flavor2variant.productFlavors).thenReturn( listOf("dim2" to "flavor2", "dim3" to "flavor3")) - Truth.assertThat(variantSelector.appliesTo(flavor1Variant)).isTrue() - Truth.assertThat(variantSelector.appliesTo(flavor2variant)).isFalse() + Mockito.`when`(flavor1Dim3Variant.productFlavors).thenReturn( + listOf("dim3" to "flavor1")) + + Truth.assertThat(flavorAndDimensionVariantSelector.appliesTo(flavor1Variant)).isTrue() + Truth.assertThat(flavorAndDimensionVariantSelector.appliesTo(flavor2variant)).isFalse() + + Truth.assertThat(variantSelectorWithoutPair.appliesTo(flavor1Dim3Variant)).isTrue() + Truth.assertThat(variantSelectorWithoutPair.appliesTo(flavor1Variant)).isFalse() + Truth.assertThat(variantSelectorWithoutPair.appliesTo(flavor2variant)).isFalse() } @Test diff --git a/build-system/gradle-core/src/test/java/com/android/build/api/variant/impl/AbstractSourceDirectoriesImplTest.kt b/build-system/gradle-core/src/test/java/com/android/build/api/variant/impl/AbstractSourceDirectoriesImplTest.kt index ba53c07291..98b7d19b00 100644 --- a/build-system/gradle-core/src/test/java/com/android/build/api/variant/impl/AbstractSourceDirectoriesImplTest.kt +++ b/build-system/gradle-core/src/test/java/com/android/build/api/variant/impl/AbstractSourceDirectoriesImplTest.kt @@ -69,8 +69,8 @@ internal class AbstractSourceDirectoriesImplTest { ) } - @Test(expected = IllegalArgumentException::class) - fun testAddIllegalSrcDir() { + @Test + fun testAddNonExistentSrcDir() { val testTarget = createTestTarget() val addedSource = File(temporaryFolder.root, "somewhere/not/existing") testTarget.addStaticSourceDirectory( diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/PseudoApiChangesTest.java b/build-system/gradle-core/src/test/java/com/android/build/gradle/PseudoApiChangesTest.java index c84bb32d17..e175f64d2d 100644 --- a/build-system/gradle-core/src/test/java/com/android/build/gradle/PseudoApiChangesTest.java +++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/PseudoApiChangesTest.java @@ -48,7 +48,8 @@ public class PseudoApiChangesTest { "StandardOutErrMessageReceiver", "ToolsRevisionUtils", "ComponentType", - "ComponentTypeImpl"); + "ComponentTypeImpl", + "DefaultAidl"); @Test public void stableImplementationClassesTest() throws IOException { diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantDslInfoTest.java b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantDslInfoTest.java index 0108b6839d..9180d0ef54 100644 --- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantDslInfoTest.java +++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantDslInfoTest.java @@ -216,7 +216,6 @@ public class VariantDslInfoTest { ApplicationVariantDslInfo variant = getVariant(); assertThat(variant.getMinSdkVersion().getApiLevel()).isEqualTo(16); - assertThat(variant.getDexingDslInfo().getTargetDeployApiFromIDE()).isEqualTo(18); } @Test @@ -231,7 +230,6 @@ public class VariantDslInfoTest { ApplicationVariantDslInfo variant = getVariant(); assertThat(variant.getMinSdkVersion().getApiLevel()).isEqualTo(16); - assertThat(variant.getDexingDslInfo().getTargetDeployApiFromIDE()).isEqualTo(18); } @Test @@ -246,7 +244,6 @@ public class VariantDslInfoTest { ApplicationVariantDslInfo variant = getVariant(); assertThat(variant.getMinSdkVersion().getApiLevel()).isEqualTo(16); - assertThat(variant.getDexingDslInfo().getTargetDeployApiFromIDE()).isEqualTo(18); } @Test @@ -261,7 +258,6 @@ public class VariantDslInfoTest { ApplicationVariantDslInfo variant = getVariant(); assertThat(variant.getMinSdkVersion().getApiLevel()).isEqualTo(16); - assertThat(variant.getDexingDslInfo().getTargetDeployApiFromIDE()).isEqualTo(22); } @Test diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/dependency/DexingTransformTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/dependency/DexingTransformTest.kt index cbc0421ee4..8398f22fd8 100644 --- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/dependency/DexingTransformTest.kt +++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/dependency/DexingTransformTest.kt @@ -93,7 +93,7 @@ class DexingTransformTest { TestInputsGenerator.dirWithEmptyClasses(input.toPath(), listOf("test/A")) dexingTransform.transform(outputs) - val dexFiles = FileUtils.getAllFiles(outputs.outputDirectory) + val dexFiles = outputs.outputDirectory.walk().filter { it.path.endsWith(".dex") }.toList() assertThat(dexFiles).containsExactly(outputs.outputDirectory.resolve( "${computeDexDirName(outputs.outputDirectory)}/test/A.dex")) val dexClasses = dexFiles.flatMap { Dex(it).classes.keys } @@ -144,7 +144,6 @@ class DexingTransformTest { TestInputsGenerator.pathWithClasses(input.toPath(), classes) val dexingTransform = TestDexingTransform( FakeGradleProvider(FakeGradleDirectory(input)), - classpath = listOf(), parameters = TestDexingTransform.TestParameters( desugaring = true ) @@ -152,7 +151,7 @@ class DexingTransformTest { val outputs = FakeTransformOutputs(tmp) dexingTransform.transform(outputs) - val dexFiles = FileUtils.getAllFiles(outputs.outputDirectory) + val dexFiles = outputs.outputDirectory.walk().filter { it.path.endsWith(".dex") }.toList() assertThat(dexFiles).hasSize(classes.size) val dexClasses = dexFiles.flatMap { Dex(it).classes.keys } assertThat(dexClasses).hasSize(classes.size + 1) @@ -207,7 +206,6 @@ class DexingTransformTest { TestInputsGenerator.pathWithClasses(input.toPath(), classes) var dexingTransform = TestDexingTransform( FakeGradleProvider(FakeGradleDirectory(input)), - classpath = listOf(), parameters = TestDexingTransform.TestParameters( desugaring = true ), @@ -215,7 +213,7 @@ class DexingTransformTest { ) dexingTransform.transform(outputs) - var dexFiles = FileUtils.getAllFiles(outputs.outputDirectory) + var dexFiles = outputs.outputDirectory.walk().filter { it.path.endsWith(".dex") }.toList() assertThat(dexFiles).hasSize(classes.size) var dexClasses = dexFiles.flatMap { Dex(it).classes.keys } assertThat(dexClasses).hasSize(classes.size + 1) @@ -250,7 +248,6 @@ class DexingTransformTest { dexingTransform = TestDexingTransform( FakeGradleProvider(FakeGradleDirectory(input)), - classpath = listOf(), parameters = TestDexingTransform.TestParameters( desugaring = true ), @@ -268,7 +265,7 @@ class DexingTransformTest { TestUtils.waitForFileSystemTick() dexingTransform.transform(outputs) - dexFiles = FileUtils.getAllFiles(outputs.outputDirectory) + dexFiles = outputs.outputDirectory.walk().filter { it.path.endsWith(".dex") }.toList() assertThat(dexFiles).hasSize(classes.size) dexClasses = dexFiles.flatMap { Dex(it).classes.keys } assertThat(dexClasses).hasSize(classes.size + 1) @@ -298,13 +295,13 @@ class DexingTransformTest { } private class TestDexingTransform( - override val primaryInput: Provider<FileSystemLocation>, + override val inputArtifact: Provider<FileSystemLocation>, private val parameters: TestParameters, - private val classpath: List<File> = listOf(), + private val classpath: List<File>? = null, override val inputChanges: InputChanges = FakeInputChanges() ) : BaseDexingTransform<BaseDexingTransform.Parameters>() { - override fun computeClasspathFiles() = classpath.map(File::toPath) + override fun computeClasspathFiles() = classpath class TestParameters( minSdkVersion: Int = 12, diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/dsl/AndroidComponentsExtensionTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/dsl/AndroidComponentsExtensionTest.kt index 1da63228e1..24e22e23b5 100644 --- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/dsl/AndroidComponentsExtensionTest.kt +++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/dsl/AndroidComponentsExtensionTest.kt @@ -18,7 +18,9 @@ package com.android.build.gradle.internal.dsl import com.android.build.api.AndroidPluginVersion import com.android.build.api.artifact.SingleArtifact +import com.android.build.api.dsl.ApplicationBuildType import com.android.build.api.dsl.ApplicationExtension +import com.android.build.api.dsl.ApplicationProductFlavor import com.android.build.api.dsl.CommonExtension import com.android.build.api.dsl.LibraryExtension import com.android.build.api.dsl.SdkComponents @@ -51,9 +53,11 @@ import com.android.build.gradle.internal.services.createDslServices import com.google.common.truth.Truth.assertThat import org.gradle.api.Action import org.gradle.api.NamedDomainObjectContainer +import org.gradle.api.plugins.ExtensionAware import org.gradle.api.plugins.ExtensionContainer import org.junit.Before import org.junit.Test +import org.mockito.ArgumentCaptor import org.mockito.Mockito import java.util.regex.Pattern @@ -293,6 +297,37 @@ class AndroidComponentsExtensionTest { interface DslExtensionType interface VariantExtensionType: VariantExtension + interface ProjectDslExtensionType + + @Test + fun testRegisterProjectExtension() { + + abstract class ExtensionAwareApplicationExtension: ApplicationExtension, ExtensionAware + + val extension = Mockito.mock(ExtensionAwareApplicationExtension::class.java) + val extensionContainer= Mockito.mock(ExtensionContainer::class.java) + Mockito.`when`(extension.extensions).thenReturn(extensionContainer) + + val variantApiOperationsRegistrar = VariantApiOperationsRegistrar<ApplicationExtension, ApplicationVariantBuilder, ApplicationVariant>(extension) + val appExtension = ApplicationAndroidComponentsExtensionImpl(dslServices, + Mockito.mock(SdkComponents::class.java), + Mockito.mock(ManagedDeviceRegistry::class.java), + variantApiOperationsRegistrar, + extension + ) + appExtension.registerExtension( + DslExtension.Builder("extension") + .extendProjectWith(ProjectDslExtensionType::class.java) + .build()) { + object: VariantExtensionType {} + } + Mockito.verify(extensionContainer).add("extension", ProjectDslExtensionType::class.java) + assertThat(variantApiOperationsRegistrar.dslExtensions).hasSize(1) + assertThat(variantApiOperationsRegistrar.dslExtensions[0].dslExtensionTypes.dslName) + .isEqualTo("extension") + assertThat(variantApiOperationsRegistrar.dslExtensions[0].dslExtensionTypes.projectExtensionType) + .isEqualTo(ProjectDslExtensionType::class.java) + } @Test fun testRegisterBuildTypeExtension() { @@ -506,26 +541,43 @@ class AndroidComponentsExtensionTest { private fun createExtensionAwareBuildType(extension: ApplicationExtension): ExtensionContainer { @Suppress("UNCHECKED_CAST") val buildTypesContainer = Mockito.mock(NamedDomainObjectContainer::class.java) - as NamedDomainObjectContainer<com.android.build.api.dsl.ApplicationBuildType> + as NamedDomainObjectContainer<ApplicationBuildType> Mockito.`when`(extension.buildTypes).thenReturn(buildTypesContainer) val buildTypeExtensionContainer= Mockito.mock(ExtensionContainer::class.java) - val buildType = Mockito.mock(com.android.build.api.dsl.BuildType::class.java) + val buildType = Mockito.mock(ApplicationBuildType::class.java) Mockito.`when`(buildType.extensions).thenReturn(buildTypeExtensionContainer) - val buildTypes = listOf<com.android.build.api.dsl.BuildType>(buildType) - Mockito.`when`(buildTypesContainer.iterator()).thenAnswer { buildTypes.iterator() } + val buildTypes = listOf<ApplicationBuildType>(buildType) + val argument = ArgumentCaptor.forClass( + Action::class.java + ) as ArgumentCaptor<Action<in ApplicationBuildType>> + + Mockito.`when`(buildTypesContainer.all(argument.capture())).thenAnswer {invocation -> + buildTypes.forEach { + invocation.getArgument<Action<in ApplicationBuildType>>(0).execute(it) + } + } return buildTypeExtensionContainer } private fun createExtensionAwareProductFlavor(extension: ApplicationExtension): ExtensionContainer { @Suppress("UNCHECKED_CAST") val productFlavorContainer = Mockito.mock(NamedDomainObjectContainer::class.java) - as NamedDomainObjectContainer<com.android.build.api.dsl.ApplicationProductFlavor> + as NamedDomainObjectContainer<ApplicationProductFlavor> Mockito.`when`(extension.productFlavors).thenReturn(productFlavorContainer) val extensionContainer= Mockito.mock(ExtensionContainer::class.java) - val productFlavor = Mockito.mock(com.android.build.api.dsl.ProductFlavor::class.java) + val productFlavor = Mockito.mock(ApplicationProductFlavor::class.java) Mockito.`when`(productFlavor.extensions).thenReturn(extensionContainer) - val productFlavors = listOf<com.android.build.api.dsl.ProductFlavor>(productFlavor) + val productFlavors = listOf<ApplicationProductFlavor>(productFlavor) Mockito.`when`(productFlavorContainer.iterator()).thenAnswer { productFlavors.iterator() } + val argument = ArgumentCaptor.forClass( + Action::class.java + ) as ArgumentCaptor<Action<in ApplicationProductFlavor>> + + Mockito.`when`(productFlavorContainer.all(argument.capture())).thenAnswer {invocation -> + productFlavors.forEach { + invocation.getArgument<Action<in ApplicationProductFlavor>>(0).execute(it) + } + } return extensionContainer } diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/services/LintParallelBuildServiceTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/services/LintParallelBuildServiceTest.kt index 6fde02c568..5c6441a483 100644 --- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/services/LintParallelBuildServiceTest.kt +++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/services/LintParallelBuildServiceTest.kt @@ -48,7 +48,7 @@ class LintParallelBuildServiceTest { maxRuntimeMemory = 20 * GB, totalPhysicalMemory = 40 * GB ) - ).isEqualTo(30) + ).isEqualTo(15) // Check case when there's not enough memory, but should still return 1 Truth.assertThat( diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/MergeArtProfileTaskTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/MergeArtProfileTaskTest.kt index 0bce7fd54a..c7dce120a0 100644 --- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/MergeArtProfileTaskTest.kt +++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/MergeArtProfileTaskTest.kt @@ -102,7 +102,7 @@ internal class MergeArtProfileTaskTest { ) task.taskAction() assertThat(task.outputFile.get().asFile.readText()).isEqualTo( - "${singleFile.readText()}\n${artProfileSourceFile.asFile.get().readText()}\n" + "${singleFile.readText()}\n${artProfileSourceFile.asFile.get().readText()}" ) } @@ -118,7 +118,7 @@ internal class MergeArtProfileTaskTest { val expectedResult = StringBuilder().apply { repeat(5) { this.append("file $it - line 1\n") } - }.toString() + }.toString().trimEnd() assertThat(task.outputFile.get().asFile.readText()).isEqualTo(expectedResult) } @@ -146,7 +146,7 @@ internal class MergeArtProfileTaskTest { val expectedResult = StringBuilder().apply { this.append("${singleFile.readText()}\n") repeat(5) { this.append("file $it - line 1\n") } - this.append("${artProfileSourceFile.asFile.get().readText()}\n") + this.append("${artProfileSourceFile.asFile.get().readText()}") }.toString() assertThat(task.outputFile.get().asFile.readText()).isEqualTo(expectedResult) diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/utils/GradleApiUtilsTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/utils/GradleApiUtilsTest.kt new file mode 100644 index 0000000000..2c681f4e62 --- /dev/null +++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/utils/GradleApiUtilsTest.kt @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2023 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.build.gradle.internal.utils + +import com.google.common.truth.Truth.assertThat +import org.gradle.testfixtures.ProjectBuilder +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder +import java.io.File + +class GradleApiUtilsTest { + + @get:Rule + val tmpDir = TemporaryFolder() + + @Test + fun `test Directory#getOrderedFileTree`() { + // The following file paths are crafted such that if `Directory.getOrderedFileTree()` + // does not sort the files based on `invariantSeparatorsPath`, this test will fail on + // Windows. + val rootDir = tmpDir.root + val files = listOf( + File(rootDir, "ABC/D"), + File(rootDir, "AB/CD"), + File(rootDir, "AB/xy") + ) + files.forEach { + it.parentFile.mkdirs() + it.createNewFile() + } + val project = ProjectBuilder.builder().build() + val directory = project.objects.directoryProperty().fileValue(rootDir).get() + + assertThat(directory.getOrderedFileTree()).isEqualTo(listOf( + File(rootDir, "AB/CD"), + File(rootDir, "AB/xy"), + File(rootDir, "ABC/D") + )) + } +} diff --git a/build-system/gradle-core/src/test/resources/com/android/build/gradle/pseudo-api.txt b/build-system/gradle-core/src/test/resources/com/android/build/gradle/pseudo-api.txt index e003d4fd45..06558f2b44 100644 --- a/build-system/gradle-core/src/test/resources/com/android/build/gradle/pseudo-api.txt +++ b/build-system/gradle-core/src/test/resources/com/android/build/gradle/pseudo-api.txt @@ -1546,7 +1546,9 @@ com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getCom com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getCompileSdkPreview: java.lang.String () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getConsumerProguardFiles: java.util.List<java.io.File> () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getEnableAndroidTest: boolean () +com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getEnableInstrumentedTestCoverage: boolean () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getEnableUnitTest: boolean () +com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getEnableUnitTestCoverage: boolean () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getExperimentalProperties: java.util.Map<java.lang.String, java.lang.Object> () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getInstallation: com.android.build.api.dsl.Installation () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getMaxSdkVersion: java.lang.Integer () @@ -1557,23 +1559,30 @@ com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getOpt com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getPackagingOptions: com.android.build.api.dsl.Packaging () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getProductFlavorsMatching: java.util.Map<java.lang.String, java.util.List<java.lang.String>> () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getProguardFiles: java.util.List<java.io.File> () +com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getTestCoverage: com.android.build.api.dsl.TestCoverage () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getTestFunctionalTest: java.lang.Boolean () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getTestHandleProfiling: java.lang.Boolean () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getTestInstrumentationRunner: java.lang.String () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getTestInstrumentationRunnerArguments: java.util.Map<java.lang.String, java.lang.String> () +com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getTestMultiDexKeepProguard: java.io.File () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getTestNamespace: java.lang.String () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getTestOptions: com.android.build.api.dsl.TestOptions () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getTestProguardFiles: java.util.List<java.io.File> () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getTestTargetSdk: java.lang.Integer () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.getTestTargetSdkPreview: java.lang.String () +com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.isCoreLibraryDesugaringEnabled: boolean () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.isMinifyEnabled: boolean () +com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.isTestMultiDexEnabled: java.lang.Boolean () com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.onVariant: void (kotlin.jvm.functions.Function1<? super com.android.build.api.variant.impl.KotlinMultiplatformAndroidVariant, kotlin.Unit>) com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setBuildToolsVersion: void (java.lang.String) com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setCompileSdk: void (java.lang.Integer) com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setCompileSdkExtension: void (java.lang.Integer) com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setCompileSdkPreview: void (java.lang.String) +com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setCoreLibraryDesugaringEnabled: void (boolean) com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setEnableAndroidTest: void (boolean) +com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setEnableInstrumentedTestCoverage: void (boolean) com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setEnableUnitTest: void (boolean) +com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setEnableUnitTestCoverage: void (boolean) com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setMinSdk: void (java.lang.Integer) com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setMinSdkPreview: void (java.lang.String) com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setMinifyEnabled: void (boolean) @@ -1581,6 +1590,8 @@ com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setNam com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setTestFunctionalTest: void (java.lang.Boolean) com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setTestHandleProfiling: void (java.lang.Boolean) com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setTestInstrumentationRunner: void (java.lang.String) +com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setTestMultiDexEnabled: void (java.lang.Boolean) +com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setTestMultiDexKeepProguard: void (java.io.File) com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setTestNamespace: void (java.lang.String) com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setTestTargetSdk: void (java.lang.Integer) com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension.setTestTargetSdkPreview: void (java.lang.String) @@ -1686,6 +1697,7 @@ com.android.build.gradle.internal.dsl.ManagedDevices.<init>: com.android.build.g com.android.build.gradle.internal.dsl.ManagedDevices.getAllDevices: org.gradle.api.ExtensiblePolymorphicDomainObjectContainer<com.android.build.api.dsl.Device> () com.android.build.gradle.internal.dsl.ManagedDevices.getDevices: org.gradle.api.ExtensiblePolymorphicDomainObjectContainer<com.android.build.api.dsl.Device> () com.android.build.gradle.internal.dsl.ManagedDevices.getGroups: org.gradle.api.NamedDomainObjectContainer<com.android.build.api.dsl.DeviceGroup> () +com.android.build.gradle.internal.dsl.ManagedDevices.getLocalDevices: org.gradle.api.NamedDomainObjectContainer<com.android.build.api.dsl.ManagedVirtualDevice> () com.android.build.gradle.internal.dsl.ManagedVirtualDevice implements com.android.build.api.dsl.ManagedVirtualDevice com.android.build.gradle.internal.dsl.ManagedVirtualDevice.<init>: com.android.build.gradle.internal.dsl.ManagedVirtualDevice (java.lang.String) com.android.build.gradle.internal.dsl.ManagedVirtualDevice.getApiLevel: int () @@ -1699,6 +1711,10 @@ com.android.build.gradle.internal.dsl.ManagedVirtualDevice.setApiPreview: void ( com.android.build.gradle.internal.dsl.ManagedVirtualDevice.setDevice: void (java.lang.String) com.android.build.gradle.internal.dsl.ManagedVirtualDevice.setRequire64Bit: void (boolean) com.android.build.gradle.internal.dsl.ManagedVirtualDevice.setSystemImageSource: void (java.lang.String) +com.android.build.gradle.internal.dsl.ManagedVirtualDeviceFactory implements org.gradle.api.NamedDomainObjectFactory +com.android.build.gradle.internal.dsl.ManagedVirtualDeviceFactory.<init>: com.android.build.gradle.internal.dsl.ManagedVirtualDeviceFactory (com.android.build.gradle.internal.services.DslServices) +com.android.build.gradle.internal.dsl.ManagedVirtualDeviceFactory.create: com.android.build.gradle.internal.dsl.ManagedVirtualDevice (java.lang.String) +com.android.build.gradle.internal.dsl.ManagedVirtualDeviceFactory.create: java.lang.Object (java.lang.String) com.android.build.gradle.internal.dsl.NdkBuildOptions implements com.android.build.gradle.internal.model.CoreNdkBuildOptions, com.android.build.api.dsl.NdkBuild com.android.build.gradle.internal.dsl.NdkBuildOptions.<init>: com.android.build.gradle.internal.dsl.NdkBuildOptions (com.android.build.gradle.internal.services.DslServices) com.android.build.gradle.internal.dsl.NdkBuildOptions.buildStagingDirectory: void (java.lang.Object) diff --git a/build-system/gradle-core/src/test/resources/com/android/build/gradle/undecorated-dsl-api.txt b/build-system/gradle-core/src/test/resources/com/android/build/gradle/undecorated-dsl-api.txt index 0ed0adbaed..82bc58165b 100644 --- a/build-system/gradle-core/src/test/resources/com/android/build/gradle/undecorated-dsl-api.txt +++ b/build-system/gradle-core/src/test/resources/com/android/build/gradle/undecorated-dsl-api.txt @@ -694,6 +694,7 @@ com.android.build.gradle.internal.dsl.LintOptions.warning: void (java.lang.Strin com.android.build.gradle.internal.dsl.ManagedDevices.getAllDevices: org.gradle.api.ExtensiblePolymorphicDomainObjectContainer<com.android.build.api.dsl.Device> () com.android.build.gradle.internal.dsl.ManagedDevices.getDevices: org.gradle.api.ExtensiblePolymorphicDomainObjectContainer<com.android.build.api.dsl.Device> () com.android.build.gradle.internal.dsl.ManagedDevices.getGroups: org.gradle.api.NamedDomainObjectContainer<com.android.build.api.dsl.DeviceGroup> () +com.android.build.gradle.internal.dsl.ManagedDevices.getLocalDevices: org.gradle.api.NamedDomainObjectContainer<com.android.build.api.dsl.ManagedVirtualDevice> () com.android.build.gradle.internal.dsl.ManagedVirtualDevice.getApiLevel: int () com.android.build.gradle.internal.dsl.ManagedVirtualDevice.getApiPreview: java.lang.String () com.android.build.gradle.internal.dsl.ManagedVirtualDevice.getDevice: java.lang.String () @@ -772,6 +773,7 @@ com.android.build.gradle.internal.dsl.ProductFlavor.setSigningConfig: void (com. com.android.build.gradle.internal.dsl.PublishingOptionsImpl.withJavadocJar: void () com.android.build.gradle.internal.dsl.PublishingOptionsImpl.withSourcesJar: void () com.android.build.gradle.internal.dsl.SdkComponentsImpl.getAdb: org.gradle.api.provider.Provider<org.gradle.api.file.RegularFile> () +com.android.build.gradle.internal.dsl.SdkComponentsImpl.getAidl: org.gradle.api.provider.Provider<com.android.build.api.variant.Aidl> () com.android.build.gradle.internal.dsl.SdkComponentsImpl.getBootClasspath: org.gradle.api.provider.Provider<java.util.List<org.gradle.api.file.RegularFile>> () com.android.build.gradle.internal.dsl.SdkComponentsImpl.getNdkDirectory: org.gradle.api.provider.Provider<org.gradle.api.file.Directory> () com.android.build.gradle.internal.dsl.SdkComponentsImpl.getSdkDirectory: org.gradle.api.provider.Provider<org.gradle.api.file.Directory> () diff --git a/build-system/gradle-settings-api/BUILD b/build-system/gradle-settings-api/BUILD index 30648d9275..756b54a243 100644 --- a/build-system/gradle-settings-api/BUILD +++ b/build-system/gradle-settings-api/BUILD @@ -37,8 +37,17 @@ filegroup( "src/main/**/*.kt", "src/main/resources/**", ]) + [ - "build.gradle", "NOTICE", + "build.gradle", ], visibility = ["//tools/base/build-system:__pkg__"], ) + +filegroup( + name = "agp_gradle_metalava_test_files", + srcs = glob([ + "src/metalavaTest/**/*.kt", + "api/**/*.txt", + ]), + visibility = ["//tools/base/build-system:__pkg__"], +) diff --git a/build-system/gradle-settings-api/api/current.txt b/build-system/gradle-settings-api/api/current.txt new file mode 100644 index 0000000000..66e2b32f3a --- /dev/null +++ b/build-system/gradle-settings-api/api/current.txt @@ -0,0 +1,76 @@ +// Signature format: 4.0 +package com.android.build.api.dsl { + + public interface Execution { + method public String? getDefaultProfile(); + method public org.gradle.api.NamedDomainObjectContainer<com.android.build.api.dsl.ExecutionProfile> getProfiles(); + method public void profiles(kotlin.jvm.functions.Function1<? super org.gradle.api.NamedDomainObjectContainer<com.android.build.api.dsl.ExecutionProfile>,kotlin.Unit> action); + method public void setDefaultProfile(String? defaultProfile); + property public abstract String? defaultProfile; + property public abstract org.gradle.api.NamedDomainObjectContainer<com.android.build.api.dsl.ExecutionProfile> profiles; + } + + public interface ExecutionProfile extends org.gradle.api.Named { + method public com.android.build.api.dsl.ToolOptions getR8(); + method public void r8(kotlin.jvm.functions.Function1<? super com.android.build.api.dsl.ToolOptions,kotlin.Unit> action); + property public abstract com.android.build.api.dsl.ToolOptions r8; + } + + public interface SettingsExtension { + method public void compileSdkAddon(String vendor, String name, int version); + method public void execution(kotlin.jvm.functions.Function1<? super com.android.build.api.dsl.Execution,kotlin.Unit> action); + method @org.gradle.api.Incubating public String? getAddOnName(); + method @org.gradle.api.Incubating public String? getAddOnVendor(); + method @org.gradle.api.Incubating public Integer? getAddOnVersion(); + method public String getBuildToolsVersion(); + method public Integer? getCompileSdk(); + method public Integer? getCompileSdkExtension(); + method public String? getCompileSdkPreview(); + method public com.android.build.api.dsl.Execution getExecution(); + method public Integer? getMinSdk(); + method public String? getMinSdkPreview(); + method public String? getNdkPath(); + method public String getNdkVersion(); + method public void setBuildToolsVersion(String buildToolsVersion); + method public void setCompileSdk(Integer? compileSdk); + method public void setCompileSdkExtension(Integer? compileSdkExtension); + method public void setCompileSdkPreview(String? compileSdkPreview); + method public void setMinSdk(Integer? minSdk); + method public void setMinSdkPreview(String? minSdkPreview); + method public void setNdkPath(String? ndkPath); + method public void setNdkVersion(String ndkVersion); + property @org.gradle.api.Incubating public abstract String? addOnName; + property @org.gradle.api.Incubating public abstract String? addOnVendor; + property @org.gradle.api.Incubating public abstract Integer? addOnVersion; + property public abstract String buildToolsVersion; + property public abstract Integer? compileSdk; + property public abstract Integer? compileSdkExtension; + property public abstract String? compileSdkPreview; + property public abstract com.android.build.api.dsl.Execution execution; + property public abstract Integer? minSdk; + property public abstract String? minSdkPreview; + property public abstract String? ndkPath; + property public abstract String ndkVersion; + } + + public interface ToolOptions { + method public java.util.List<java.lang.String> getJvmOptions(); + method public boolean getRunInSeparateProcess(); + method public void setRunInSeparateProcess(boolean runInSeparateProcess); + property public abstract java.util.List<java.lang.String> jvmOptions; + property public abstract boolean runInSeparateProcess; + } + +} + +package com.android.build.gradle { + + public final class SettingsPlugin implements org.gradle.api.Plugin<org.gradle.api.initialization.Settings> { + ctor public SettingsPlugin(); + method public void apply(org.gradle.api.initialization.Settings settings); + method public com.android.build.api.dsl.SettingsExtension getAndroid(); + property public final com.android.build.api.dsl.SettingsExtension android; + } + +} + diff --git a/build-system/gradle-settings-api/build.gradle b/build-system/gradle-settings-api/build.gradle index da45235d0c..2dcccae2c5 100644 --- a/build-system/gradle-settings-api/build.gradle +++ b/build-system/gradle-settings-api/build.gradle @@ -2,12 +2,18 @@ plugins { id 'com.android.tools.java-library' id 'com.android.tools.kotlin' id 'com.android.tools.publish' + id 'com.android.tools.metalava' id 'license-report' } dependencies { implementation gradleApi() implementation libs.kotlin_stdlib + + metalavaTestImplementation libs.com.android.tools.testutils + metalavaTestImplementation libs.guava + metalavaTestImplementation libs.junit + metalavaTestImplementation libs.kotlin_test } group = 'com.android.tools.build' @@ -16,3 +22,6 @@ version = rootProject.ext.buildVersion project.ext.pomName = 'Gradle Settings API for Android' project.ext.pomDesc = 'Gradle Settings API to build Android applications.' +def updateApi = tasks.register('updateApi') { + dependsOn('updateMetalavaApi') +} diff --git a/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/Execution.kt b/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/Execution.kt index d28e3ca0a7..29ad3be154 100644 --- a/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/Execution.kt +++ b/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/Execution.kt @@ -16,7 +16,6 @@ package com.android.build.api.dsl -import org.gradle.api.Action import org.gradle.api.NamedDomainObjectContainer interface Execution { @@ -24,9 +23,6 @@ interface Execution { val profiles: NamedDomainObjectContainer<ExecutionProfile> /** Container where profiles can be declared. */ - fun profiles(action: Action<NamedDomainObjectContainer<ExecutionProfile>>) - - /** Container where profiles can be declared. */ fun profiles(action: NamedDomainObjectContainer<ExecutionProfile>.() -> Unit) /** Select execution profile */ diff --git a/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/ExecutionProfile.kt b/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/ExecutionProfile.kt index a02a2e2343..140886da24 100644 --- a/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/ExecutionProfile.kt +++ b/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/ExecutionProfile.kt @@ -16,7 +16,6 @@ package com.android.build.api.dsl -import org.gradle.api.Action import org.gradle.api.Named interface ExecutionProfile: Named { @@ -24,8 +23,5 @@ interface ExecutionProfile: Named { val r8: ToolOptions /** Specify R8 execution options. */ - fun r8(action: Action<ToolOptions>) - - /** Specify R8 execution options. */ fun r8(action: ToolOptions.() -> Unit) } diff --git a/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/SettingsExtension.kt b/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/SettingsExtension.kt index e9b286187c..74cc5fa892 100644 --- a/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/SettingsExtension.kt +++ b/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/SettingsExtension.kt @@ -16,7 +16,6 @@ package com.android.build.api.dsl -import org.gradle.api.Action import org.gradle.api.Incubating /** @@ -26,7 +25,6 @@ import org.gradle.api.Incubating * This allows settings default values that are then applied to all android projects which this * build. */ -@Incubating interface SettingsExtension { /** @@ -69,10 +67,13 @@ interface SettingsExtension { fun compileSdkAddon(vendor: String, name: String, version: Int) /** Value set via `compileSdkAddon` */ + @get:Incubating val addOnVendor: String? /** Value set via `compileSdkAddon` */ + @get:Incubating val addOnName: String? /** Value set via `compileSdkAddon` */ + @get:Incubating val addOnVersion: Int? /** @@ -91,9 +92,6 @@ interface SettingsExtension { val execution: Execution /** Set execution profiles and options for tools. */ - fun execution(action: Action<Execution>) - - /** Set execution profiles and options for tools. */ fun execution(action: Execution.() -> Unit) /** @@ -101,7 +99,7 @@ interface SettingsExtension { * * See [com.android.build.api.dsl.CommonExtension.ndkVersion] for more information */ - var ndkVersion: String? + var ndkVersion: String /** * Requires the specified path to NDK be used. @@ -117,5 +115,5 @@ interface SettingsExtension { * * See [com.android.build.api.dsl.CommonExtension.buildToolsVersion] for more information */ - var buildToolsVersion: String? + var buildToolsVersion: String } diff --git a/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/ToolOptions.kt b/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/ToolOptions.kt index eda6d34328..10b1829696 100644 --- a/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/ToolOptions.kt +++ b/build-system/gradle-settings-api/src/main/java/com/android/build/api/dsl/ToolOptions.kt @@ -25,6 +25,4 @@ interface ToolOptions { * setting things like max memory usage */ val jvmOptions: MutableList<String> - - fun setJvmOptions(from: List<String>) } diff --git a/build-system/gradle-settings-api/src/metalavaTest/java/com/android/build/api/metalava/StableApiTest.kt b/build-system/gradle-settings-api/src/metalavaTest/java/com/android/build/api/metalava/StableApiTest.kt new file mode 100644 index 0000000000..b55c263e2b --- /dev/null +++ b/build-system/gradle-settings-api/src/metalavaTest/java/com/android/build/api/metalava/StableApiTest.kt @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2023 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.build.api.metalava + +import com.android.testutils.TestUtils +import com.google.common.io.Resources +import org.junit.Test +import java.lang.AssertionError +import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths + +/** + * Test that tries to ensure that our public API remains stable. + */ +class StableApiTest { + @Test + fun checkCurrentApi() { + @Suppress("UnstableApiUsage") + val expected: List<String> = Resources.asCharSource(EXPECTED_FILE, StandardCharsets.UTF_8).readLines() + val actual = Files.readAllLines(CURRENT, StandardCharsets.UTF_8) + if (expected != actual) { + throw AssertionError( + """ + The Android Gradle Plugin API does not match the expectation file. + + Either: + * revert the api change + * or apply the below changes by running the updateApi task: + gradle :base:build-system:gradle-settings-api:updateMetalavaApi + + To update all the API expectation files, run + gradlew updateApi + """.trimIndent() + + TestUtils.getDiff(expected.toTypedArray(), actual.toTypedArray()) + ) + } + } + + companion object { + @Suppress("UnstableApiUsage") + private val EXPECTED_FILE = Resources.getResource("current.txt") + val CURRENT: Path = Paths.get(System.getProperty("metalavaCurrentApiFile")!!).resolve("current.txt") + } +} diff --git a/build-system/gradle-settings/BUILD b/build-system/gradle-settings/BUILD index 5d01a82b22..d45eba23d0 100644 --- a/build-system/gradle-settings/BUILD +++ b/build-system/gradle-settings/BUILD @@ -32,8 +32,8 @@ filegroup( "src/main/**/*.kt", "src/main/resources/**", ]) + [ - "build.gradle", "NOTICE", + "build.gradle", ], visibility = ["//tools/base/build-system:__pkg__"], ) diff --git a/build-system/gradle-settings/build.gradle b/build-system/gradle-settings/build.gradle index 30629872f1..2238ced606 100644 --- a/build-system/gradle-settings/build.gradle +++ b/build-system/gradle-settings/build.gradle @@ -45,6 +45,8 @@ dependencies { implementation gradleApi() implementation libs.kotlin_stdlib + testImplementation libs.com.android.tools.sdkCommon + testImplementation libs.com.android.tools.common testImplementation libs.junit testImplementation libs.truth testImplementation libs.truth_java8_extension diff --git a/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/ExecutionImpl.kt b/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/ExecutionImpl.kt index 654ac7d143..14a62f6a9e 100644 --- a/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/ExecutionImpl.kt +++ b/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/ExecutionImpl.kt @@ -24,9 +24,13 @@ import org.gradle.api.model.ObjectFactory import javax.inject.Inject internal open class ExecutionImpl @Inject constructor(objectFactory: ObjectFactory): Execution { - override val profiles: NamedDomainObjectContainer<ExecutionProfile> = objectFactory.domainObjectContainer(ExecutionProfile::class.java, ExecutionProfileFactory(objectFactory)) + override val profiles: NamedDomainObjectContainer<ExecutionProfile> = + objectFactory.domainObjectContainer( + ExecutionProfile::class.java, + ExecutionProfileFactory(objectFactory) + ) - override fun profiles(action: Action<NamedDomainObjectContainer<ExecutionProfile>>) { + fun profiles(action: Action<NamedDomainObjectContainer<ExecutionProfile>>) { action.execute(profiles) } diff --git a/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/ExecutionProfileImpl.kt b/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/ExecutionProfileImpl.kt index 06740d8332..aacaa0ca60 100644 --- a/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/ExecutionProfileImpl.kt +++ b/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/ExecutionProfileImpl.kt @@ -33,10 +33,9 @@ open class ExecutionProfileImpl @Inject constructor(private val name: String, ob override val r8: ToolOptions = objectFactory.newInstance(ToolOptionsImpl::class.java) - override fun r8(action: Action<ToolOptions>) { + fun r8(action: Action<ToolOptions>) { action.execute(r8) } - override fun r8(action: ToolOptions.() -> Unit) { action.invoke(r8) } diff --git a/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/SdkConstants.kt b/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/SdkConstants.kt new file mode 100644 index 0000000000..e6f73d1abe --- /dev/null +++ b/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/SdkConstants.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 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.build.gradle.internal.dsl + +object SdkConstants { + const val NDK_VERSION = "25.1.8937393" + const val BUILD_TOOLS_VERSION = "33.0.1" +} diff --git a/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/SettingsExtensionImpl.kt b/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/SettingsExtensionImpl.kt index 54398ab711..33e06c9b59 100644 --- a/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/SettingsExtensionImpl.kt +++ b/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/SettingsExtensionImpl.kt @@ -95,16 +95,19 @@ internal open class SettingsExtensionImpl @Inject constructor(objectFactory: Obj _minSdk = null } - override val execution: Execution = objectFactory.newInstance(ExecutionImpl::class.java, objectFactory) + override val execution: Execution = objectFactory.newInstance( + ExecutionImpl::class.java, objectFactory + ) - override fun execution(action: Action<Execution>) { + fun execution(action: Action<Execution>) { action.execute(execution) } + override fun execution(action: Execution.() -> Unit) { action.invoke(execution) } - override var ndkVersion: String? = null + override var ndkVersion: String = SdkConstants.NDK_VERSION override var ndkPath: String? = null - override var buildToolsVersion: String? = null + override var buildToolsVersion: String = SdkConstants.BUILD_TOOLS_VERSION } diff --git a/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/ToolOptionsImpl.kt b/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/ToolOptionsImpl.kt index bc187ba6ea..6165de84ee 100644 --- a/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/ToolOptionsImpl.kt +++ b/build-system/gradle-settings/src/main/java/com/android/build/gradle/internal/dsl/ToolOptionsImpl.kt @@ -23,7 +23,7 @@ open class ToolOptionsImpl: ToolOptions { override val jvmOptions: MutableList<String> = mutableListOf() - override fun setJvmOptions(from: List<String>) { + fun setJvmOptions(from: List<String>) { jvmOptions.clear() jvmOptions.addAll(from) } diff --git a/build-system/gradle-settings/src/test/kotlin/com/android/build/gradle/internal/dsl/SdkConstantsSyncTest.kt b/build-system/gradle-settings/src/test/kotlin/com/android/build/gradle/internal/dsl/SdkConstantsSyncTest.kt new file mode 100644 index 0000000000..9dccd86a2d --- /dev/null +++ b/build-system/gradle-settings/src/test/kotlin/com/android/build/gradle/internal/dsl/SdkConstantsSyncTest.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 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.build.gradle.internal.dsl + +import com.google.common.truth.Truth +import org.junit.Test + +class SdkConstantsSyncTest { + @Test + fun checkBuildToolsVersion() { + Truth.assertThat(SdkConstants.BUILD_TOOLS_VERSION) + .isEqualTo(com.android.SdkConstants.CURRENT_BUILD_TOOLS_VERSION) + } + + @Test + fun checkNdkVersion() { + Truth.assertThat(SdkConstants.NDK_VERSION) + .isEqualTo(com.android.SdkConstants.NDK_DEFAULT_VERSION) + } + +} diff --git a/build-system/integration-test/application/BUILD.bazel b/build-system/integration-test/application/BUILD.bazel index df801bde95..34ccc801f4 100644 --- a/build-system/integration-test/application/BUILD.bazel +++ b/build-system/integration-test/application/BUILD.bazel @@ -108,6 +108,7 @@ TEST_DATA = [ "//tools/base/build-system/integration-test:test-projects/jetifier", "//tools/base/build-system/integration-test:test-projects/kotlinApp", "//tools/base/build-system/integration-test:test-projects/kotlinAppWithKsp", + "//tools/base/build-system/integration-test:test-projects/kotlinMultiplatform", "//tools/base/build-system/integration-test:test-projects/kotlinWithEclipseSourceSet", "//tools/base/build-system/integration-test:test-projects/libDependency", "//tools/base/build-system/integration-test:test-projects/libMinify", @@ -263,6 +264,7 @@ single_gradle_integration_test_per_source( "src/test/java/com/android/build/gradle/integration/testing/**", "src/test/java/com/android/build/gradle/integration/resources/**", "src/test/java/com/android/build/gradle/integration/dependencies/**", + "src/test/java/com/android/build/gradle/integration/multiplatform/v2/**", "src/test/java/com/android/build/gradle/integration/application/Java11CompileTest.kt", "src/test/java/com/android/build/gradle/integration/application/AgpVersionConsistencyTest.kt", "src/test/java/com/android/build/gradle/integration/application/JavaCompileWithToolChainTest.kt", @@ -368,7 +370,7 @@ gradle_integration_test( ], exclude = CONNECTED_TESTS, ), - data = TEST_DATA, + data = TEST_DATA + OLD_SDKS, maven_repo_zips = [ "//tools/base/build-system:android_gradle_plugin", ], @@ -569,6 +571,35 @@ gradle_integration_test( deps = TEST_DEPS, ) +# Test for kotlin multiplatform android prototype +gradle_integration_test( + name = "kotlin-multiplatform-prototype-tests", + timeout = "long", + srcs = glob( + [ + "src/test/java/com/android/build/gradle/integration/multiplatform/v2/*.kt", + ], + ), + data = TEST_DATA, + #keep sorted + maven_repo_zips = [ + "//tools/base/build-system:android_gradle_plugin", + "//tools/base/build-system:kmp_prototype", + ], + maven_repos = [ + "//tools/base/build-system:android_gradle_plugin_runtime_dependencies", + "//tools/base/build-system/integration-test:androidx_test_latest", + "//tools/base/build-system/integration-test:kotlin_gradle_plugin_prebuilts", + "//tools/base/build-system/integration-test:support_library_latest", + "//tools/base/build-system/integration-test/application:prebuilts", + ], + #keep sorted + tags = [ + "no_test_mac", # b/69151132 + ], + deps = TEST_DEPS, +) + # Maven repo with all the dependencies required by test projects. # # Quick way of updating this list: diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/AidlSdkComponentsTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/AidlSdkComponentsTest.kt new file mode 100644 index 0000000000..fb0a4d8e90 --- /dev/null +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/AidlSdkComponentsTest.kt @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2023 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.build.gradle.integration.application + +import com.android.build.gradle.integration.common.fixture.GradleTestProject +import com.android.build.gradle.integration.common.fixture.GradleTestProject.Companion.DEFAULT_BUILD_TOOL_VERSION +import com.android.build.gradle.integration.common.fixture.GradleTestProject.Companion.DEFAULT_COMPILE_SDK_VERSION +import com.android.build.gradle.integration.common.fixture.app.MinimalSubProject +import org.junit.Rule +import org.junit.Test + +class AidlSdkComponentsTest { + @JvmField + @Rule + val project = GradleTestProject.builder().fromTestApp( + MinimalSubProject.app("com.example.app") + ).withPluginManagementBlock(true).create() + + @Test + fun testAidlTools() { + project.buildFile.delete() + + project.file("build.gradle.kts").writeText(""" + apply(from = "../commonHeader.gradle") + plugins { + id("com.android.application") + } + + android { + namespace = "com.example.app" + compileSdk = $DEFAULT_COMPILE_SDK_VERSION + buildToolsVersion = "$DEFAULT_BUILD_TOOL_VERSION" + } + + abstract class AidlTask : DefaultTask() { + + @get:Nested + abstract val aidlInput: Property<com.android.build.api.variant.Aidl> + + @TaskAction + fun execute() { + val aidlBinary = aidlInput.get().executable.get().asFile + val aidlFramework = aidlInput.get().framework.get().asFile + val version = aidlInput.get().version.get() + + if (aidlBinary.exists().not()) + throw GradleException("executable file missing") + if (aidlFramework.exists().not()) + throw GradleException("framework file missing") + if (aidlFramework.path.contains("$DEFAULT_COMPILE_SDK_VERSION").not()) + throw GradleException("wrong framework file") + if (version != "$DEFAULT_BUILD_TOOL_VERSION") + throw GradleException("version mismatch") + + } + } + + val taskProvider = tasks.register<AidlTask>("getAidlTools") { + this.aidlInput.set(androidComponents.sdkComponents.aidl) + } + + """.trimIndent()) + + project.executor().run("getAidlTools") + } +} diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/ArtifactApiTest.java b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/ArtifactApiTest.java index 0f6f70db62..a1f95776cb 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/ArtifactApiTest.java +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/ArtifactApiTest.java @@ -198,6 +198,6 @@ public class ArtifactApiTest { // ATTENTION Author and Reviewers - please make sure required changes to the build file // are backwards compatible before updating this test. assertThat(TestFileUtils.sha1NormalizedLineEndings(project.file("build.gradle"))) - .isEqualTo("9c90d2a9660fe501de6292bb365ee06e4b07390e"); + .isEqualTo("36da9529a6084dc8d3351a2cdf54d922877c73fd"); } } diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/GenFolderApi2Test.java b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/GenFolderApi2Test.java index e43e5ffda3..e3dd17d753 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/GenFolderApi2Test.java +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/GenFolderApi2Test.java @@ -90,6 +90,6 @@ public class GenFolderApi2Test { // ATTENTION Author and Reviewers - please make sure required changes to the build file // are backwards compatible before updating this test. assertThat(TestFileUtils.sha1NormalizedLineEndings(project.file("build.gradle"))) - .isEqualTo("943ed7864358a2e4e5ec112765c32885f7b33077"); + .isEqualTo("48b1df5b5a40abb122b2fb27109c7dd5cc85b2a0"); } } diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/GenFolderApiTest.java b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/GenFolderApiTest.java index 4364c3e47f..537631136c 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/GenFolderApiTest.java +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/GenFolderApiTest.java @@ -238,6 +238,6 @@ public class GenFolderApiTest { // ATTENTION Author and Reviewers - please make sure required changes to the build file // are backwards compatible before updating this test. assertThat(TestFileUtils.sha1NormalizedLineEndings(project.file("build.gradle"))) - .isEqualTo("89eeb4e83538a3734127c703b69f5a030dd19cdc"); + .isEqualTo("f9a636a63493919e028601d375ff365aa5c21004"); } } diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/JacocoLibraryProjectTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/JacocoLibraryProjectTest.kt index b6339bb0de..1da369cdae 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/JacocoLibraryProjectTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/JacocoLibraryProjectTest.kt @@ -19,6 +19,7 @@ import com.android.build.gradle.integration.common.fixture.GradleTestProject.Com import com.android.build.gradle.integration.common.fixture.LoggingLevel import com.android.build.gradle.integration.common.fixture.app.HelloWorldApp import com.android.build.gradle.integration.common.truth.ScannerSubject.Companion.assertThat +import com.android.utils.FileUtils import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Rule @@ -65,11 +66,23 @@ class JacocoLibraryProjectTest { $buildFile """.trimIndent()) - val result = project.executor().withLoggingLevel(LoggingLevel.INFO).run("testDebugUnitTest") + val result = project.executor().withLoggingLevel(LoggingLevel.INFO).run("createDebugUnitTestCoverageReport") assertThat(result.stdout).doesNotContain("Cannot process instrumented class") val coverageData = project.buildDir.walk().filter { it.extension=="exec" }.toList() assertThat(coverageData).hasSize(1) + + val coveragePackageFolder = FileUtils.join( + project.buildDir, + "reports", "coverage", "test", "debug", "com.example.helloworld" + ) + + assertThat(coveragePackageFolder.exists()).isTrue() + + assertThat(coveragePackageFolder.listFiles()!!.map { it.name }).containsAtLeast( + "HelloWorld.html", + "HelloWorld.java.html" + ) } } diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/KaptTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/KaptTest.kt index 727915e696..66d3fa4b5a 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/KaptTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/KaptTest.kt @@ -85,7 +85,7 @@ buildscript { apply from: "../../commonBuildScript.gradle" dependencies { // Provides the 'android-kotlin' build plugin for the app - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${"$"}rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${"$"}{libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/MergeFileTaskTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/MergeFileTaskTest.kt index 3dce70ae0d..9ab133ddfd 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/MergeFileTaskTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/MergeFileTaskTest.kt @@ -44,6 +44,7 @@ class MergeFileTaskTest { totalTxt += txt + "\n" inputs.add(file) } + totalTxt = totalTxt.trimEnd() val output = tmp.root.resolve("output.txt") @@ -51,4 +52,4 @@ class MergeFileTaskTest { assertThat(output.readText()).matches(totalTxt) } -}
\ No newline at end of file +} diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/NavigationIntentFilterTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/NavigationIntentFilterTest.kt index e5155b22f0..b0d60713e4 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/NavigationIntentFilterTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/NavigationIntentFilterTest.kt @@ -207,7 +207,8 @@ class NavigationIntentFilterTest { <application android:appComponentFactory="androidx.core.app.CoreComponentFactory" - android:debuggable="true" > + android:debuggable="true" + android:extractNativeLibs="true" > <activity android:name="com.example.app.MyActivity" > <intent-filter> <action android:name="android.intent.action.APP_ACTION" /> diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/NavigationPlaceholderTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/NavigationPlaceholderTest.kt index c5eb4b454b..2a717449a1 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/NavigationPlaceholderTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/NavigationPlaceholderTest.kt @@ -238,7 +238,9 @@ class NavigationPlaceholderTest { android:minSdkVersion="14" android:targetSdkVersion="14" /> - <application android:debuggable="true" > + <application + android:debuggable="true" + android:extractNativeLibs="true" > <activity android:name="com.example.app.MyActivity" > <intent-filter> <action android:name="android.intent.action.VIEW" /> diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/ProfileableTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/ProfileableTest.kt index d0c50382ba..6e32c26d42 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/ProfileableTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/ProfileableTest.kt @@ -189,7 +189,7 @@ class ProfileableTest { arrayListOf( " E: application (line=11)", " A: http://schemas.android.com/apk/res/android:testOnly(0x01010272)=true", - " E: profileable (line=12)", + " E: profileable (line=14)", " A: http://schemas.android.com/apk/res/android:enabled(0x0101000e)=true", " A: http://schemas.android.com/apk/res/android:shell(0x01010594)=true" ) diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/SettingsPluginTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/SettingsPluginTest.kt index eec7969841..6c12b7fe15 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/SettingsPluginTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/SettingsPluginTest.kt @@ -18,8 +18,6 @@ package com.android.build.gradle.integration.application import com.android.build.gradle.integration.common.fixture.DEFAULT_COMPILE_SDK_VERSION import com.android.build.gradle.integration.common.fixture.DEFAULT_MIN_SDK_VERSION -import com.android.build.gradle.integration.common.fixture.GradleTestProject -import com.android.build.gradle.integration.common.fixture.GradleTestProject.Companion.ANDROID_GRADLE_PLUGIN_VERSION import com.android.build.gradle.integration.common.fixture.testprojects.PluginType import com.android.build.gradle.integration.common.fixture.testprojects.createGradleProject import com.android.build.gradle.integration.common.fixture.testprojects.prebuilts.setUpHelloWorld @@ -37,7 +35,6 @@ class SettingsPluginTest { rootProject { plugins.add(PluginType.ANDROID_APP) android { - setUpHelloWorld(setupDefaultCompileSdk = false) } } diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/taskstates/UtpTestTaskStatesTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/taskstates/UtpTestTaskStatesTest.kt index 3f8548d0a9..c495b03f12 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/taskstates/UtpTestTaskStatesTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/taskstates/UtpTestTaskStatesTest.kt @@ -124,6 +124,33 @@ class UtpTestTaskStatesTest { } @Test + fun checkAddLocalDevicesAddsTasks() { + project.gradlePropertiesFile.appendText( + "\nandroid.experimental.androidTest.useUnifiedTestPlatform=true\n") + appProject.buildFile.appendText(""" + android { + testOptions { + managedDevices { + localDevices { + device1 { + device = "Pixel 2" + apiLevel = 29 + systemImageSource = "aosp" + } + } + } + } + } + """) + assertTaskExists(project, "app:cleanManagedDevices") + assertTaskExists(project, "app:device1Setup") + assertTaskExists(project, "app:device1DebugAndroidTest") + assertTaskExists(project, "app:allDevicesDebugAndroidTest") + assertTaskExists(project, "app:device1Check") + assertTaskExists(project, "app:allDevicesCheck") + } + + @Test fun checkDslSupportsMultipleDevices() { project.gradlePropertiesFile.appendText( "\nandroid.experimental.androidTest.useUnifiedTestPlatform=true\n") diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/automatic/CheckAll.java b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/automatic/CheckAll.java index 58853f8dd8..8961675b76 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/automatic/CheckAll.java +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/automatic/CheckAll.java @@ -151,6 +151,7 @@ public class CheckAll { "lintCustomLocalAndPublishRules", // contains integ test for lint itself "simpleCompositeBuild", // broken composite build project. "multiCompositeBuild", // too complex composite build project to setup - "sourceDependency" // not set up fully, just used for sync tests + "sourceDependency", // not set up fully, just used for sync tests + "kotlinMultiplatform" // TODO(b/243387425): enable when the prototype is moved to gradle-core ); } diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/bundle/DynamicAppLegacyMultidexTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/bundle/DynamicAppLegacyMultidexTest.kt index 0a92be1923..72b72c1915 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/bundle/DynamicAppLegacyMultidexTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/bundle/DynamicAppLegacyMultidexTest.kt @@ -67,7 +67,7 @@ class DynamicAppLegacyMultidexTest { | |android { | namespace 'foo.feature' - | compileSdkVersion rootProject.latestCompileSdk + | compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() | defaultConfig { | minSdkVersion 18 | } diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/dependencies/AppWithProvidedLibTest.java b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/dependencies/AppWithProvidedLibTest.java index a090520f62..7a763ff38e 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/dependencies/AppWithProvidedLibTest.java +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/dependencies/AppWithProvidedLibTest.java @@ -59,7 +59,7 @@ public class AppWithProvidedLibTest { + "\n" + "android {\n" + " namespace 'com.example.android.multiproject.library.base'\n" - + " compileSdkVersion rootProject.latestCompileSdk\n" + + " compileSdkVersion libs.versions.latestCompileSdk.get().toInteger()\n" + "\n" + "}\n"); final File mainFolder = new File(libFolder, "src/main"); diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/dependencies/LibraryAlignmentWarningTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/dependencies/LibraryAlignmentWarningTest.kt new file mode 100644 index 0000000000..6ec7283354 --- /dev/null +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/dependencies/LibraryAlignmentWarningTest.kt @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2018 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.build.gradle.integration.dependencies + +import com.android.build.gradle.integration.common.fixture.GradleTestProject +import com.android.build.gradle.integration.common.fixture.app.MinimalSubProject +import com.android.build.gradle.integration.common.truth.ScannerSubject +import com.android.build.gradle.options.BooleanOption +import com.android.builder.model.v2.ide.SyncIssue +import com.android.testutils.MavenRepoGenerator +import com.google.common.truth.Truth +import org.junit.Before +import org.junit.Rule +import org.junit.Test + +class LibraryAlignmentWarningTest { + @JvmField + @Rule + val project: GradleTestProject = GradleTestProject.builder() + .fromTestApp(MinimalSubProject.lib()) + .create() + + @Test + fun `warning issued when runtime classpath is built but libraries constrained`() { + val model = project.modelV2().ignoreSyncIssues(SyncIssue.SEVERITY_WARNING).fetchModels("debug", dontBuildRuntimeClasspath = true) + val issueModel = model.container.singleProjectInfo.issues + Truth.assertThat(issueModel).isNotNull() + Truth.assertThat(issueModel!!.syncIssues.map {it.message}).containsExactly(""" + You have experimental IDE flag gradle.ide.gradle.skip.runtime.classpath.for.libraries enabled, + but AGP boolean option ${BooleanOption.EXCLUDE_LIBRARY_COMPONENTS_FROM_CONSTRAINTS.propertyName} is not used. + + Please set below in gradle.properties: + + ${BooleanOption.EXCLUDE_LIBRARY_COMPONENTS_FROM_CONSTRAINTS.propertyName}=true + + """.trimIndent()) + + } + + @Test + fun `warning not issued when flag is set`() { + project.gradlePropertiesFile.appendText( + "${BooleanOption.EXCLUDE_LIBRARY_COMPONENTS_FROM_CONSTRAINTS.propertyName}=true" + ) + project.modelV2() + // allowing experimental option warning + .allowOptionWarning(BooleanOption.EXCLUDE_LIBRARY_COMPONENTS_FROM_CONSTRAINTS) + .fetchModels("debug", dontBuildRuntimeClasspath = true) + } + + @Test + fun `warning not issued when runtime classpath is built`() { + project.modelV2().fetchModels("debug", dontBuildRuntimeClasspath = false) + } +} diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/dependencies/LibraryCompileAndRuntimeClasspathTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/dependencies/LibraryCompileAndRuntimeClasspathTest.kt new file mode 100644 index 0000000000..d3771f42ad --- /dev/null +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/dependencies/LibraryCompileAndRuntimeClasspathTest.kt @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2018 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.build.gradle.integration.dependencies + +import com.android.build.gradle.integration.common.fixture.GradleTestProject +import com.android.build.gradle.integration.common.fixture.app.MinimalSubProject +import com.android.build.gradle.integration.common.truth.ScannerSubject +import com.android.build.gradle.options.BooleanOption +import com.android.testutils.MavenRepoGenerator +import org.junit.Before +import org.junit.Rule +import org.junit.Test + +class LibraryCompileAndRuntimeClasspathTest { + @JvmField + @Rule + val project: GradleTestProject = GradleTestProject.builder() + .fromTestApp( + MinimalSubProject.lib(), + ).withAdditionalMavenRepo(MavenRepoGenerator(listOf( + MavenRepoGenerator.Library("com.example:package:1.0-runtimeOnly"), + MavenRepoGenerator.Library("com.example:package:2.0-compileOnly"), + MavenRepoGenerator.Library("com.example:package:3.0-androidTestRuntimeOnly"), + MavenRepoGenerator.Library("com.example:package:4.0-androidTestCompileOnly"), + MavenRepoGenerator.Library("com.example:package:5.0-testRuntimeOnly"), + MavenRepoGenerator.Library("com.example:package:6.0-testCompileOnly"), + ))).create() + + @Before + fun setUpDependencies() { + project.buildFile.appendText(""" + |dependencies { + | testCompileOnly 'com.example:package:6.0-testCompileOnly' + | testRuntimeOnly 'com.example:package:5.0-testRuntimeOnly' + | androidTestCompileOnly 'com.example:package:4.0-androidTestCompileOnly' + | androidTestRuntimeOnly 'com.example:package:3.0-androidTestRuntimeOnly' + | compileOnly 'com.example:package:2.0-compileOnly' + |} + |""".trimMargin()) + } + + @Test + fun `debugAndroidTestCompileClasspath - constraints unsatisfiable`() { + assertDependenciesOutput( + "debugAndroidTestCompileClasspath", """ + |debugAndroidTestCompileClasspath - Resolved configuration for compilation for variant: debugAndroidTest + |+--- com.example:package:4.0-androidTestCompileOnly FAILED + |+--- project : (*) + |\--- com.example:package:{strictly 3.0-androidTestRuntimeOnly} FAILED + """ + ) + } + + @Test + fun `all other cases - constraints unsatisfiable`() { + // Adding this causes the debugAndroidTestRuntimeClasspath to fail, which in turn makes the + // debugAndroidTestCompileClasspath not applicable in this case, so that's a separate + // test case without the 1.0-runtimeOnly dependency + project.buildFile.appendText(""" + |dependencies { + | runtimeOnly 'com.example:package:1.0-runtimeOnly' + |} + |""".trimMargin()) + + assertDependenciesOutput("debugCompileClasspath", """ + |debugCompileClasspath - Resolved configuration for compilation for variant: debug + |+--- com.example:package:2.0-compileOnly FAILED + |\--- com.example:package:{strictly 1.0-runtimeOnly} FAILED + """) + assertDependenciesOutput("debugUnitTestCompileClasspath", """ + |debugUnitTestCompileClasspath - Resolved configuration for compilation for variant: debugUnitTest + |+--- project : (*) + |+--- com.example:package:6.0-testCompileOnly FAILED + |\--- com.example:package:{strictly 5.0-testRuntimeOnly} FAILED + """) + + // This fails because the main runtimeClasspath is aligned to androidTest runtimeClasspath. + assertDependenciesOutput("debugAndroidTestRuntimeClasspath", """ + |debugAndroidTestRuntimeClasspath - Resolved configuration for runtime for variant: debugAndroidTest + |+--- com.example:package:3.0-androidTestRuntimeOnly FAILED + |+--- project : (*) + |+--- com.example:package:{strictly 1.0-runtimeOnly} FAILED + |\--- com.example:package:1.0-runtimeOnly FAILED + """) + } + + @Test + fun `debugAndroidTestCompileClasspath - succeeds with constraints disabled`() { + project.gradlePropertiesFile.appendText( + "${BooleanOption.EXCLUDE_LIBRARY_COMPONENTS_FROM_CONSTRAINTS.propertyName}=true" + ) + + assertDependenciesOutput("debugAndroidTestCompileClasspath", """ + |debugAndroidTestCompileClasspath - Resolved configuration for compilation for variant: debugAndroidTest + |+--- com.example:package:4.0-androidTestCompileOnly + |\--- project : (*) + """) + } + + + @Test + fun `all other cases - succeeds with constraints disabled`() { + project.gradlePropertiesFile.appendText( + "${BooleanOption.EXCLUDE_LIBRARY_COMPONENTS_FROM_CONSTRAINTS.propertyName}=true" + ) + + // Adding this causes the debugAndroidTestRuntimeClasspath to fail, which in turn makes the + // debugAndroidTestCompileClasspath not applicable in this case, so that's a separate + // test case without the 1.0-runtimeOnly dependency + project.buildFile.appendText(""" + |dependencies { + | runtimeOnly 'com.example:package:1.0-runtimeOnly' + |} + |""".trimMargin()) + + assertDependenciesOutput("debugCompileClasspath", """ + |debugCompileClasspath - Resolved configuration for compilation for variant: debug + |\--- com.example:package:2.0-compileOnly + """) + assertDependenciesOutput("debugUnitTestCompileClasspath", """ + |debugUnitTestCompileClasspath - Resolved configuration for compilation for variant: debugUnitTest + |+--- project : (*) + |\--- com.example:package:6.0-testCompileOnly + """) + + assertDependenciesOutput("debugAndroidTestRuntimeClasspath", """ + |debugAndroidTestRuntimeClasspath - Resolved configuration for runtime for variant: debugAndroidTest + |+--- com.example:package:3.0-androidTestRuntimeOnly + |+--- project : (*) + |\--- com.example:package:1.0-runtimeOnly -> 3.0-androidTestRuntimeOnly + """) + } + + private fun assertDependenciesOutput(configurationName: String, expectedOutput: String) { + val result = project.executor().withArguments(listOf("dependencies","--configuration", configurationName)).run() + result.stdout.use { + ScannerSubject.assertThat(it).contains(expectedOutput.trimMargin()) + } + } +} diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/dexing/CacheableDexingTransformTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/dexing/CacheableDexingTransformTest.kt new file mode 100644 index 0000000000..a0d3e02379 --- /dev/null +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/dexing/CacheableDexingTransformTest.kt @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2023 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.build.gradle.integration.dexing + +import com.android.build.gradle.integration.common.fixture.testprojects.PluginType +import com.android.build.gradle.integration.common.fixture.testprojects.createGradleProject +import com.android.build.gradle.integration.common.truth.TruthHelper.assertThat +import com.android.build.gradle.integration.common.utils.TestFileUtils.searchAndReplace +import org.gradle.api.JavaVersion +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder +import java.io.File + +class CacheableDexingTransformTest { + + @get:Rule + val buildCacheDir = TemporaryFolder() + + @get:Rule + val projectCopy1 = createProject("projectCopy1") + + @get:Rule + val projectCopy2 = createProject("projectCopy2") + + private fun createProject(name: String) = createGradleProject(name) { + subProject(":app") { + plugins.add(PluginType.ANDROID_APP) + android { + defaultCompileSdk() + minSdk = 24 + } + dependencies { + implementation(project(":lib")) + } + } + subProject(":lib") { + plugins.add(PluginType.ANDROID_LIB) + android { + defaultCompileSdk() + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + } + addFile( + "src/main/java/com/example/lib/JavaClassWithNestedClass.java", + """ + package com.example.lib; + public class JavaClassWithNestedClass { + public class NestedClass { + // This line will be changed later + } + } + """.trimIndent() + ) + } + } + + @Before + fun setUp() { + listOf(projectCopy1, projectCopy2).forEach { project -> + project.settingsFile.appendText("\n" + + """ + |buildCache { + | local { + | directory = "${buildCacheDir.root.path.replace("\\", "\\\\")}" + | } + |} + """.trimMargin() + ) + } + } + + @Test + fun `Bug 266599585 - test incremental build after cache hit`() { + val result1 = + projectCopy1.executor().withArgument("--build-cache").run(":app:mergeLibDexDebug") + assertThat(result1.getTask(":app:mergeLibDexDebug")).didWork() + result1.assertOutputContains("Running dexing transform non-incrementally") + + // Building the same project from a different location should get a cache hit + val result2 = + projectCopy2.executor().withArgument("--build-cache").run(":app:mergeLibDexDebug") + assertThat(result2.getTask(":app:mergeLibDexDebug")).wasFromCache() + result2.assertOutputDoesNotContain("Running dexing transform") + + // Make a change to a nested class (regression test for bug 266599585) + searchAndReplace( + File( + projectCopy2.getSubproject(":lib").mainSrcDir, + "com/example/lib/JavaClassWithNestedClass.java" + ), + "// This line will be changed later", + "public void newMethodInNestedClass() { }" + ) + + // The next build after cache hit should be incremental + val result3 = + projectCopy2.executor().withArgument("--build-cache").run(":app:mergeLibDexDebug") + assertThat(result3.getTask(":app:mergeLibDexDebug")).didWork() + result3.assertOutputContains("Running dexing transform incrementally") + } + +} diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ApiTest.java b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ApiTest.java index 6d650b2b06..fa4dcdadc6 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ApiTest.java +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ApiTest.java @@ -52,8 +52,8 @@ public class ApiTest { // ATTENTION Author and Reviewers - please make sure required changes to the build file // are backwards compatible before updating this test. assertThat(TestFileUtils.sha1NormalizedLineEndings(project.file("app/build.gradle"))) - .isEqualTo("29186fa45df8c3a1149a28c181583412c65deabe"); + .isEqualTo("7a0d27bd070b33b93c4b2f6f9d75359a97eeefbb"); assertThat(TestFileUtils.sha1NormalizedLineEndings(project.file("lib/build.gradle"))) - .isEqualTo("6e5765ae2f9b51c2efeafb8000239989d1c5a12e"); + .isEqualTo("1d2511f3075f449ed8e0f23ffccd34f695b2a928"); } } diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ArtProfileBaselineTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ArtProfileBaselineTest.kt index 4f419b4426..55696c3ed7 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ArtProfileBaselineTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ArtProfileBaselineTest.kt @@ -125,9 +125,9 @@ class ArtProfileBaselineTest { ) val expectedContent = if (addOldBaselineProfile) { - "$mainBaselineProfileFileContent\n$releaseBaselineProfileFileContent\n$oldBaselineProfileFileContent\n" + "$mainBaselineProfileFileContent\n$releaseBaselineProfileFileContent\n$oldBaselineProfileFileContent" } else { - "$mainBaselineProfileFileContent\n$releaseBaselineProfileFileContent\n" + "$mainBaselineProfileFileContent\n$releaseBaselineProfileFileContent" } Truth.assertThat(mergedFile.readText()).isEqualTo(expectedContent) diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ArtProfileMultipleLibrariesTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ArtProfileMultipleLibrariesTest.kt index 9e072a2df3..da394c2d49 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ArtProfileMultipleLibrariesTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ArtProfileMultipleLibrariesTest.kt @@ -215,6 +215,8 @@ class ArtProfileMultipleLibrariesTest( expectedMergedRewrittenFileContent.plus( applicationBaselineProfContent.plus("\n")) } + expectedMergedFileContent = expectedMergedFileContent.trimEnd() + expectedMergedRewrittenFileContent = expectedMergedRewrittenFileContent.trimEnd() val result = project.executor() .run( @@ -270,7 +272,7 @@ class ArtProfileMultipleLibrariesTest( SdkConstants.FN_ART_PROFILE, ) Truth.assertThat( - mergedFile.readText() + mergedFile.readText().trimEnd() // R8 seems to add a newline at the end ).isEqualTo( if (withArtProfileR8Rewriting) expectedMergedRewrittenFileContent diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ArtProfileSingleLibraryTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ArtProfileSingleLibraryTest.kt index d43264aea4..c1517c3374 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ArtProfileSingleLibraryTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/ArtProfileSingleLibraryTest.kt @@ -153,7 +153,7 @@ class ArtProfileSingleLibraryTest { SdkConstants.FN_ART_PROFILE, ) val expectedContent = if (addApplicationProfile) { - "$libraryFileContent\n$applicationFileContent\n" + "$libraryFileContent\n$applicationFileContent" } else libraryFileContent Truth.assertThat(mergedFile.readText()).isEqualTo(expectedContent) diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/PrivacySandboxSdkTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/PrivacySandboxSdkTest.kt index 58b3235030..5915e1f118 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/PrivacySandboxSdkTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/PrivacySandboxSdkTest.kt @@ -419,7 +419,7 @@ class PrivacySandboxSdkTest { assertThat(manifestContent).containsAtLeastElementsIn( listOf( " E: application (line=14)", - " E: uses-sdk-library (line=17)", + " E: uses-sdk-library (line=18)", " A: http://schemas.android.com/apk/res/android:name(0x01010003)=\"com.example.privacysandboxsdk\" (Raw: \"com.example.privacysandboxsdk\")", " A: http://schemas.android.com/apk/res/android:certDigest(0x01010548)=\"$certDigest\" (Raw: \"$certDigest\")", " A: http://schemas.android.com/apk/res/android:versionMajor(0x01010577)=10002" diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/manifest/ProcessApplicationManifestTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/manifest/ProcessApplicationManifestTest.kt new file mode 100644 index 0000000000..3be36d3161 --- /dev/null +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/manifest/ProcessApplicationManifestTest.kt @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2023 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.build.gradle.integration.manifest + +import com.android.build.gradle.integration.common.fixture.GradleTestProject +import com.android.build.gradle.integration.common.fixture.app.MinimalSubProject +import com.android.build.gradle.integration.common.fixture.app.MultiModuleTestProject +import com.android.build.gradle.integration.common.truth.ScannerSubject +import com.android.build.gradle.options.BooleanOption +import com.android.testutils.truth.PathSubject.assertThat +import org.junit.Rule +import org.junit.Test + +class ProcessApplicationManifestTest { + + private val app = + MinimalSubProject.app() + .appendToBuild( + """ + android { + packaging { + jniLibs { + useLegacyPackaging false + } + } + } + """.trimIndent() + ) + private val lib = + MinimalSubProject.lib() + .withFile( + "src/main/AndroidManifest.xml", + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android"> + <application android:extractNativeLibs="true"/> + </manifest> + """.trimIndent() + ) + + @get:Rule + val project: GradleTestProject = + GradleTestProject.builder() + .fromTestApp( + MultiModuleTestProject.builder() + .subproject(":app", app) + .subproject(":lib", lib) + .dependency(app, lib) + .build() + ).create() + + @Test + fun testDependencyExtractNativeLibsIsNotMerged() { + val result1 = project.executor().run(":app:processDebugManifest") + + val manifestFile = + project.getSubproject(":app") + .file("build/intermediates/merged_manifests/debug/AndroidManifest.xml") + assertThat(manifestFile).exists() + assertThat(manifestFile).contains("android:extractNativeLibs=\"false\"") + + val expectedWarning = + "android:extractNativeLibs is set to true in a dependency's AndroidManifest.xml" + ScannerSubject.assertThat(result1.stdout).contains(expectedWarning) + + // Check that no warning message if it's suppressed + val result2 = + project.executor() + .with(BooleanOption.SUPPRESS_EXTRACT_NATIVE_LIBS_WARNINGS, true) + .run("clean", ":app:processDebugManifest") + ScannerSubject.assertThat(result2.stdout).doesNotContain(expectedWarning) + } +} diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/manifest/ProcessTestManifestTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/manifest/ProcessTestManifestTest.kt index d67d6e551f..63e4b3015e 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/manifest/ProcessTestManifestTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/manifest/ProcessTestManifestTest.kt @@ -232,9 +232,8 @@ class ProcessTestManifestTest { } } - // This should eventually be a warning, but not until there's AUA support (b/272815813) @Test - fun testNoWarningsForApplicationAttributes() { + fun testWarningForExtractNativeLibsAttribute() { FileUtils.createFile( project.file("src/androidTest/AndroidManifest.xml"), """ @@ -244,7 +243,7 @@ class ProcessTestManifestTest { """.trimIndent()) val result = project.executor().run("assembleDebugAndroidTest") result.stdout.use { - assertThat(it).doesNotContain("android:extractNativeLibs should not be specified") + assertThat(it).contains("android:extractNativeLibs should not be specified") } } diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/multiplatform/v2/KotlinMultiplatformAndroidDexingTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/multiplatform/v2/KotlinMultiplatformAndroidDexingTest.kt new file mode 100644 index 0000000000..cedb9b4fa6 --- /dev/null +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/multiplatform/v2/KotlinMultiplatformAndroidDexingTest.kt @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2023 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.build.gradle.integration.multiplatform.v2 + +import com.android.build.gradle.integration.common.fixture.BaseGradleExecutor +import com.android.build.gradle.integration.common.fixture.DESUGAR_DEPENDENCY_VERSION +import com.android.build.gradle.integration.common.fixture.GradleTestProjectBuilder +import com.android.build.gradle.integration.common.utils.TestFileUtils +import com.android.testutils.apk.Apk +import com.android.testutils.truth.DexClassSubject +import com.android.testutils.truth.DexSubject +import com.android.utils.FileUtils +import org.junit.Before +import org.junit.Rule +import org.junit.Test + +class KotlinMultiplatformAndroidDexingTest { + @Suppress("DEPRECATION") // kmp doesn't support configuration caching for now (b/276472789) + @get:Rule + val project = GradleTestProjectBuilder() + .fromTestProject("kotlinMultiplatform") + .withConfigurationCaching(BaseGradleExecutor.ConfigurationCaching.OFF) + .create() + + @Before + fun setUp() { + TestFileUtils.appendToFile( + project.getSubproject("kmpFirstLib").ktsBuildFile, + """ + kotlin { + androidPrototype { + onMainCompilation { + compilerOptions.configure { + jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8) + } + } + + options { + isTestMultiDexEnabled = true + isCoreLibraryDesugaringEnabled = true + } + } + } + dependencies { + add("coreLibraryDesugaring", "com.android.tools:desugar_jdk_libs:$DESUGAR_DEPENDENCY_VERSION") + } + """.trimIndent()) + + TestFileUtils.addMethod( + FileUtils.join( + project.getSubproject("kmpFirstLib").projectDir, + "src", "androidMain", "kotlin", "com", "example", "kmpfirstlib", "KmpAndroidActivity.kt" + ), + """ + fun getText(): String { + val collection = java.util.Arrays.asList("first", "second", "third") + val streamOfCollection = collection.stream() + return streamOfCollection.findFirst().get() + } + """.trimIndent()) + } + + @Test + fun testDesugaringForInstrumentedTestApk() { + project.executor().run(":kmpFirstLib:assembleInstrumentedTest") + val testApk = project.getSubproject("kmpFirstLib").getOutputFile( + "apk", "androidTest", "main", "kmpFirstLib-androidTest.apk" + ) + + Apk(testApk).use { apk -> + DexClassSubject.assertThat(apk.getClass("Lcom/example/kmpfirstlib/KmpAndroidActivity;")) + .hasMethodThatInvokes("getText", "Lj$/util/stream/Stream;->findFirst()Lj$/util/Optional;") + } + } + + @Test + fun testLegacyMultiDexWithKeepRules() { + TestFileUtils.appendToFile( + project.getSubproject("androidLib").ktsBuildFile, + """ + android.defaultConfig.minSdk = 20 + """.trimIndent() + ) + + TestFileUtils.appendToFile( + project.getSubproject("kmpSecondLib").ktsBuildFile, + """ + android.minSdk = 20 + """.trimIndent() + ) + + TestFileUtils.appendToFile( + project.getSubproject("kmpFirstLib").ktsBuildFile, + """ + android.testMultiDexKeepProguard = File(project.projectDir, "dex-rules.pro") + android.minSdk = 20 + """.trimIndent() + ) + + FileUtils.writeToFile( + FileUtils.join(project.getSubproject("kmpFirstLib").projectDir, "dex-rules.pro"), + """ + -keep class com.example.kmpfirstlib.KmpAndroidActivity { *; } + """.trimIndent() + ) + + project.executor().run(":kmpFirstLib:assembleInstrumentedTest") + val testApk = project.getSubproject("kmpFirstLib").getOutputFile( + "apk", "androidTest", "main", "kmpFirstLib-androidTest.apk" + ) + + Apk(testApk).use { apk -> + DexClassSubject.assertThat(apk.getClass("Lcom/example/kmpfirstlib/KmpAndroidActivity;")) + .hasMethodThatInvokes("getText", "Lj$/util/stream/Stream;->findFirst()Lj$/util/Optional;") + + DexSubject.assertThat( + apk.allDexes.find { it.classes.containsKey( "Lcom/example/kmpfirstlib/KmpAndroidFirstLibClass;") } + ).doesNotContainClasses("Lcom/example/kmpfirstlib/KmpAndroidActivity;") + + DexSubject.assertThat( + apk.mainDexFile.get() + ).containsClass("Lcom/example/kmpfirstlib/KmpAndroidActivity;") + } + } +} diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/multiplatform/v2/KotlinMultiplatformAndroidMinificationTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/multiplatform/v2/KotlinMultiplatformAndroidMinificationTest.kt new file mode 100644 index 0000000000..f9c740f57f --- /dev/null +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/multiplatform/v2/KotlinMultiplatformAndroidMinificationTest.kt @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2023 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.build.gradle.integration.multiplatform.v2 + +import com.android.build.gradle.integration.common.fixture.BaseGradleExecutor +import com.android.build.gradle.integration.common.fixture.GradleTestProject +import com.android.build.gradle.integration.common.fixture.GradleTestProjectBuilder +import com.android.build.gradle.integration.common.utils.TestFileUtils +import com.android.testutils.apk.Aar +import com.android.utils.FileUtils +import com.google.common.truth.Truth +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import kotlin.io.path.pathString + +class KotlinMultiplatformAndroidMinificationTest { + + @Suppress("DEPRECATION") // kmp doesn't support configuration caching for now (b/276472789) + @get:Rule + val project = GradleTestProjectBuilder() + .fromTestProject("kotlinMultiplatform") + .withConfigurationCaching(BaseGradleExecutor.ConfigurationCaching.OFF) + .create() + + @Before + fun setUp() { + TestFileUtils.appendToFile( + project.getSubproject("kmpFirstLib").ktsBuildFile, + """ + android.isMinifyEnabled = true + android.consumerProguardFiles.add( + File(project.projectDir, "consumer-proguard-rules.pro") + ) + android.proguardFiles.add( + File(project.projectDir, "proguard-rules.pro") + ) + """.trimIndent() + ) + + TestFileUtils.appendToFile( + project.getSubproject("app").ktsBuildFile, + """ + android { + buildTypes { + getByName("debug") { + isMinifyEnabled = true + isShrinkResources = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + } + """.trimIndent() + ) + } + + @Test + fun testKmpLibClassesAreMinified() { + project.executor().run(":kmpFirstLib:assemble") + + Aar( + project.getSubproject("kmpFirstLib").getOutputFile( + "aar", + "kmpFirstLib.aar" + ) + ).use { aar -> + aar.getEntryAsZip("classes.jar").use { classesJar -> + Truth.assertThat(classesJar.entries.map { it.pathString }) + .containsExactly( + "/kmp_resource.txt", + "/com/example/kmpfirstlib/KmpAndroidActivity.class" + ) + } + } + } + + @Test + fun testAppClassesAreMinified() { + project.executor().run(":app:assembleDebug") + + project.getSubproject("app").getApk(GradleTestProject.ApkType.DEBUG).use { apk -> + // only the main activity is left + Truth.assertThat(apk.mainDexFile.get().classes.keys).containsExactly( + "Lcom/example/kmpfirstlib/KmpAndroidActivity;" + ) + } + } + + @Test + fun testProguardRulesInKmpLib() { + FileUtils.writeToFile( + project.getSubproject("kmpFirstLib").file("proguard-rules.pro"), + """ + -keep public class com.example.kmpfirstlib.KmpAndroidFirstLibClass { + java.lang.String callCommonLibClass(); + java.lang.String callAndroidLibClass(); + } + """.trimIndent() + ) + + project.executor().run(":kmpFirstLib:assemble") + + Aar( + project.getSubproject("kmpFirstLib").getOutputFile( + "aar", + "kmpFirstLib.aar" + ) + ).use { aar -> + aar.getEntryAsZip("classes.jar").use { classesJar -> + Truth.assertThat(classesJar.entries.map { it.pathString }) + // code is optimized by default, and so the invocations to classes from common + // and androidLib are replaced by a literal string and removed. + .containsExactly( + "/kmp_resource.txt", + "/com/example/kmpfirstlib/KmpAndroidActivity.class", + "/com/example/kmpfirstlib/KmpAndroidFirstLibClass.class", + ) + } + } + } + + @Test + fun testProguardRulesInApp() { + FileUtils.writeToFile( + project.getSubproject("app").file("proguard-rules.pro"), + """ + -keep public class com.example.app.AndroidApp { *; } + """.trimIndent() + ) + + project.executor().run(":app:assembleDebug") + + project.getSubproject("app").getApk(GradleTestProject.ApkType.DEBUG).use { apk -> + Truth.assertThat(apk.mainDexFile.get().classes.keys).containsExactly( + "Lcom/example/androidlib/AndroidLib;", + "Lcom/example/app/AndroidApp;", + "Lcom/example/kmpfirstlib/KmpAndroidActivity;", + "Lcom/example/kmpfirstlib/KmpAndroidFirstLibClass;", + "Lcom/example/kmpfirstlib/KmpCommonFirstLibClass;", + "Lcom/example/kmpsecondlib/KmpAndroidSecondLibClass;", + "Lcom/example/kmpsecondlib/KmpCommonSecondLibClass;", + "Lkotlin/jvm/internal/Intrinsics;" + ) + } + } + + @Test + fun testConsumerProguardRulesFromKmpLib() { + FileUtils.writeToFile( + project.getSubproject("kmpFirstLib").file("consumer-proguard-rules.pro"), + """ + -keep public class com.example.kmpfirstlib.KmpAndroidFirstLibClass { + java.lang.String callCommonLibClass(); + java.lang.String callKmpSecondLibClass(); + } + """.trimIndent() + ) + + project.executor().run(":app:assembleDebug") + + project.getSubproject("app").getApk(GradleTestProject.ApkType.DEBUG).use { apk -> + Truth.assertThat(apk.mainDexFile.get().classes.keys).containsExactly( + "Lcom/example/kmpfirstlib/KmpAndroidActivity;", + "Lcom/example/kmpfirstlib/KmpAndroidFirstLibClass;", + "Lcom/example/kmpfirstlib/KmpCommonFirstLibClass;", + "Lcom/example/kmpsecondlib/KmpAndroidSecondLibClass;", + "Lcom/example/kmpsecondlib/KmpCommonSecondLibClass;" + ) + } + } +} diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/multiplatform/v2/KotlinMultiplatformAndroidPluginTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/multiplatform/v2/KotlinMultiplatformAndroidPluginTest.kt new file mode 100644 index 0000000000..155caf6fc1 --- /dev/null +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/multiplatform/v2/KotlinMultiplatformAndroidPluginTest.kt @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2022 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.build.gradle.integration.multiplatform.v2 + +import com.android.build.gradle.integration.common.fixture.BaseGradleExecutor +import com.android.build.gradle.integration.common.fixture.GradleTestProject +import com.android.build.gradle.integration.common.fixture.GradleTestProjectBuilder +import com.android.build.gradle.integration.common.truth.ApkSubject +import com.android.build.gradle.integration.common.truth.TruthHelper.assertThatApk +import com.android.build.gradle.integration.common.utils.TestFileUtils +import com.android.testutils.apk.Aar +import com.android.testutils.apk.Apk +import com.android.utils.FileUtils +import com.google.common.truth.Truth +import com.google.common.truth.Truth.assertThat +import com.google.common.truth.Truth.assertWithMessage +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized +import kotlin.io.path.pathString +import kotlin.io.path.readText + +@RunWith(Parameterized::class) +class KotlinMultiplatformAndroidPluginTest(private val publishLibs: Boolean) { + + companion object { + + @JvmStatic + @Parameterized.Parameters(name = "publishLibs={0}") + fun getOptions() = listOf(false, true) + } + + @Suppress("DEPRECATION") // kmp doesn't support configuration caching for now (b/276472789) + @get:Rule + val project = GradleTestProjectBuilder() + .fromTestProject("kotlinMultiplatform") + .withConfigurationCaching(BaseGradleExecutor.ConfigurationCaching.OFF) + .create() + + @Before + fun setUpProject() { + if (!publishLibs) { + return + } + + TestFileUtils.appendToFile( + project.settingsFile, + """ + dependencyResolutionManagement { + repositories { + maven { + url 'testRepo' + } + } + } + """.trimIndent() + ) + + TestFileUtils.searchAndReplace( + project.getSubproject("kmpFirstLib").ktsBuildFile, + "project(\":kmpSecondLib\")", + "\"com.example:kmpSecondLib-android:1.0\"" + ) + + TestFileUtils.searchAndReplace( + project.getSubproject("kmpFirstLib").ktsBuildFile, + "project(\":androidLib\")", + "\"com.example:androidLib:1.0\"" + ) + + TestFileUtils.searchAndReplace( + project.getSubproject("app").ktsBuildFile, + "project(\":kmpFirstLib\")", + "\"com.example:kmpFirstLib-android:1.0\"" + ) + + listOf("androidLib", "kmpFirstLib", "kmpSecondLib").forEach { projectName -> + TestFileUtils.searchAndReplace( + project.getSubproject(projectName).ktsBuildFile, + "plugins {", + "plugins {\n id(\"maven-publish\")" + ) + + TestFileUtils.appendToFile(project.getSubproject(projectName).ktsBuildFile, + """ + group = "com.example" + version = "1.0" + publishing { + repositories { + maven { + url = uri("../testRepo") + } + } + } + """.trimIndent() + ) + } + + // set up publishing for android lib + TestFileUtils.appendToFile( + project.getSubproject("androidLib").ktsBuildFile, + """ + android { + publishing { + multipleVariants("all") { + allVariants() + } + } + } + + afterEvaluate { + publishing { + publications { + create<MavenPublication>("all") { + from(components["all"]) + } + } + } + } + """.trimIndent() + ) + + project.executor().run(":androidLib:publish") + project.executor().run(":kmpSecondLib:publish") + project.executor().run(":kmpFirstLib:publish") + } + + @Test + fun testRunningUnitTests() { + TestFileUtils.appendToFile( + project.getSubproject("kmpFirstLib").ktsBuildFile, + """ + android.enableUnitTestCoverage = true + """.trimIndent() + ) + + project.executor().run(":kmpFirstLib:createKotlinAndroidTestCoverageReport") + + assertWithMessage( + "Running kmp unit tests should run common tests as well" + ).that( + FileUtils.join( + project.getSubproject("kmpFirstLib").buildDir, + "reports", + "tests", + "testKotlinAndroidTest", + "classes" + ).listFiles()!!.map { it.name } + ).containsExactly( + "com.example.kmpfirstlib.KmpAndroidFirstLibClassTest.html", + "com.example.kmpfirstlib.KmpCommonFirstLibClassTest.html" + ) + + val coveragePackageFolder = FileUtils.join( + project.getSubproject("kmpFirstLib").buildDir, + "reports", "coverage", "test", "main", "com.example.kmpfirstlib" + ) + assertThat(coveragePackageFolder.exists()).isTrue() + + assertThat(coveragePackageFolder.listFiles()!!.map { it.name }).containsExactly( + "index.html", + "index.source.html", + + "KmpCommonFirstLibClass.html", + "KmpCommonFirstLibClass.kt.html", + + "KmpAndroidActivity.html", + "KmpAndroidActivity.kt.html", + + "KmpAndroidFirstLibClass.html", + "KmpAndroidFirstLibClass.kt.html", + ) + + val packageCoverageReport = FileUtils.join( + coveragePackageFolder, + "index.html" + ) + + val generatedCoverageReportHTML = packageCoverageReport.readLines().joinToString("\n") + + val totalCoverageMetricsContents = Regex("<tfoot>(.*?)</tfoot>") + .find(generatedCoverageReportHTML) + val totalCoverageInfo = Regex("<td class=\"ctr2\">(.*?)</td>") + .find(totalCoverageMetricsContents?.groups?.first()!!.value) + + val packageCoveragePercentage = totalCoverageInfo!!.groups[1]!!.value + + assertThat(packageCoveragePercentage.trimEnd('%').toInt() > 0).isTrue() + + project.executor().run(":app:testDebugUnitTest") + } + + @Test + fun testAppApkContents() { + project.executor().run(":app:assembleDebug") + + project.getSubproject("app").getApk(GradleTestProject.ApkType.DEBUG).use { apk -> + // classes from commonMain are packaged + assertThatApk(apk).hasClass("Lcom/example/kmpfirstlib/KmpCommonFirstLibClass;") + assertThatApk(apk).hasClass("Lcom/example/kmpsecondlib/KmpCommonSecondLibClass;") + + // classes from androidMain are packaged + assertThatApk(apk).hasClass("Lcom/example/kmpfirstlib/KmpAndroidFirstLibClass;") + assertThatApk(apk).hasClass("Lcom/example/kmpsecondlib/KmpAndroidSecondLibClass;") + + // transitive deps are packaged + assertThatApk(apk).hasClass("Lcom/example/androidlib/AndroidLib;") + assertThatApk(apk).hasClass("Lcom/example/app/AndroidApp;") + + val manifestContents = ApkSubject.getManifestContent(apk.file).joinToString("\n") + assertThat(manifestContents).contains( + "com.example.kmpfirstlib.KmpAndroidActivity" + ) + + assertThat(apk.getEntry("kmp_resource.txt").readText()).isEqualTo( + "kmp resource\n" + ) + + assertThat(apk.getEntry("android_lib_resource.txt").readText()).isEqualTo( + "android lib resource\n" + ) + } + } + + @Test + fun testKmpLibraryAarContents() { + project.executor().run(":kmpFirstLib:assemble") + + Aar( + project.getSubproject("kmpFirstLib").getOutputFile( + "aar", + "kmpFirstLib.aar" + ) + ).use { aar -> + + assertThat(aar.getEntry("R.txt")).isNotNull() + + aar.getEntryAsZip("classes.jar").use { classesJar -> + assertThat(classesJar.entries.map { it.pathString }).containsExactlyElementsIn( + listOf( + "/kmp_resource.txt", + "/com/example/kmpfirstlib/KmpCommonFirstLibClass.class", + "/com/example/kmpfirstlib/KmpAndroidFirstLibClass.class", + "/com/example/kmpfirstlib/KmpAndroidActivity.class", + ) + ) + + assertThat(classesJar.getEntry("kmp_resource.txt").readText()).isEqualTo( + "kmp resource\n" + ) + } + + assertThat(aar.androidManifestContentsAsString).contains("uses-sdk android:minSdkVersion=\"22\"") + assertThat(aar.androidManifestContentsAsString).contains("package=\"com.example.kmpfirstlib\"") + + assertThat( + aar.getEntry("META-INF/com/android/build/gradle/aar-metadata.properties").readText() + ).contains("minAndroidGradlePluginVersion=7.2.0") + } + } + + @Test + fun testKmpLibraryTestApkContents() { + TestFileUtils.appendToFile( + project.getSubproject("kmpFirstLib").ktsBuildFile, + """ + android.packagingOptions.resources.excludes.addAll(listOf( + "**/*.java", + "junit/**", + "LICENSE-junit.txt" + )) + """.trimIndent() + ) + + project.executor().run(":kmpFirstLib:assembleInstrumentedTest") + + val testApk = project.getSubproject("kmpFirstLib").getOutputFile( + "apk", "androidTest", "main", "kmpFirstLib-androidTest.apk" + ) + + assertThat(testApk.exists()).isTrue() + + Apk(testApk).use { apk -> + // Test apk should be signed by debug signing config + assertThatApk(apk).containsApkSigningBlock() + + assertThatApk(apk).hasApplicationId("com.example.kmpfirstlib.test") + + // classes from commonMain are packaged + assertThatApk(apk).hasClass("Lcom/example/kmpfirstlib/KmpCommonFirstLibClass;") + assertThatApk(apk).hasClass("Lcom/example/kmpsecondlib/KmpCommonSecondLibClass;") + + // instrumented test classes are packaged + assertThatApk(apk).containsClass("Lcom/example/kmpfirstlib/test/KmpAndroidFirstLibActivityTest;") + + // classes from common tests and unit tests are not packaged + assertThatApk(apk).doesNotContainClass("Lcom/example/kmpfirstlib/KmpCommonFirstLibClassTest;") + assertThatApk(apk).doesNotContainClass("Lcom/example/kmpfirstlib/KmpAndroidFirstLibClassTest;") + + // classes from androidMain are packaged + assertThatApk(apk).hasClass("Lcom/example/kmpfirstlib/KmpAndroidFirstLibClass;") + assertThatApk(apk).hasClass("Lcom/example/kmpsecondlib/KmpAndroidSecondLibClass;") + + // classes from library dependencies are packaged + assertThatApk(apk).hasClass("Lcom/example/androidlib/AndroidLib;") + assertThatApk(apk).hasClass("Landroidx/test/core/app/ActivityScenario;") + + // resources from dependencies are packaged + assertThatApk(apk).contains("resources.arsc") + + val manifestContents = ApkSubject.getManifestContent(apk.file).joinToString("\n") + assertThat(manifestContents).contains( + "com.example.kmpfirstlib.KmpAndroidActivity" + ) + + assertThat(apk.getEntry("kmp_resource.txt").readText()).isEqualTo( + "kmp resource\n" + ) + + assertThat(apk.getEntry("android_lib_resource.txt").readText()).isEqualTo( + "android lib resource\n" + ) + + // all contents + assertThat( + apk.entries.map { it.pathString }.filterNot { + it.startsWith("/res") || it.endsWith(".kotlin_builtins") || + it.startsWith("/META-INF") || + (it.startsWith("/classes") && it.endsWith(".dex")) + } + ).containsExactlyElementsIn( + listOf( + "/AndroidManifest.xml", + "/kmp_resource.txt", + "/android_lib_resource.txt", + ) + ) + } + } +} diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/packaging/ExtractNativeLibsPackagingTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/packaging/ExtractNativeLibsPackagingTest.kt index 71dee12f51..c81b277a73 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/packaging/ExtractNativeLibsPackagingTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/packaging/ExtractNativeLibsPackagingTest.kt @@ -16,6 +16,7 @@ package com.android.build.gradle.integration.packaging +import com.android.build.gradle.integration.common.fixture.DEFAULT_COMPILE_SDK_VERSION import com.android.build.gradle.integration.common.fixture.GradleTestProject import com.android.build.gradle.integration.common.fixture.GradleTestProject.ApkType import com.android.build.gradle.integration.common.fixture.app.MinimalSubProject @@ -27,7 +28,8 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized -import java.util.zip.ZipEntry +import java.util.zip.ZipEntry.DEFLATED +import java.util.zip.ZipEntry.STORED import java.util.zip.ZipFile /** @@ -42,33 +44,36 @@ import java.util.zip.ZipFile class ExtractNativeLibsPackagingTest( private val sourceManifestValue: Boolean?, private val minSdk: Int, + compileSdk: Int, private val useLegacyPackaging: Boolean?, private val expectedMergedManifestValue: Boolean?, - private val expectedCompression: Int + private val expectedCompression: Int, ) { companion object { @JvmStatic - @Parameterized.Parameters(name = "extractNativeLibs_{0}_minSdk_{1}_useLegacyPackaging_{2}") + @Parameterized.Parameters(name = "extractNativeLibs_{0}_minSdk_{1}_compileSdk_{2}_useLegacyPackaging_{3}") fun parameters() = listOf( - arrayOf(true, 22, true, true, ZipEntry.DEFLATED), - arrayOf(true, 22, false, true, ZipEntry.DEFLATED), - arrayOf(true, 22, null, true, ZipEntry.DEFLATED), - arrayOf(true, 23, true, true, ZipEntry.DEFLATED), - arrayOf(true, 23, false, true, ZipEntry.DEFLATED), - arrayOf(true, 23, null, true, ZipEntry.DEFLATED), - arrayOf(false, 22, true, false, ZipEntry.STORED), - arrayOf(false, 22, false, false, ZipEntry.STORED), - arrayOf(false, 22, null, false, ZipEntry.STORED), - arrayOf(false, 23, true, false, ZipEntry.STORED), - arrayOf(false, 23, false, false, ZipEntry.STORED), - arrayOf(false, 23, null, false, ZipEntry.STORED), - arrayOf(null, 22, true, null, ZipEntry.DEFLATED), - arrayOf(null, 22, false, false, ZipEntry.STORED), - arrayOf(null, 22, null, null, ZipEntry.DEFLATED), - arrayOf(null, 23, true, null, ZipEntry.DEFLATED), - arrayOf(null, 23, false, false, ZipEntry.STORED), - arrayOf(null, 23, null, false, ZipEntry.STORED) + arrayOf(true, 22, DEFAULT_COMPILE_SDK_VERSION, true, true, DEFLATED), + arrayOf(true, 22, DEFAULT_COMPILE_SDK_VERSION, false, true, DEFLATED), + arrayOf(true, 22, DEFAULT_COMPILE_SDK_VERSION, null, true, DEFLATED), + arrayOf(true, 23, DEFAULT_COMPILE_SDK_VERSION, true, true, DEFLATED), + arrayOf(true, 23, DEFAULT_COMPILE_SDK_VERSION, false, true, DEFLATED), + arrayOf(true, 23, DEFAULT_COMPILE_SDK_VERSION, null, true, DEFLATED), + arrayOf(false, 22, DEFAULT_COMPILE_SDK_VERSION, true, false, STORED), + arrayOf(false, 22, DEFAULT_COMPILE_SDK_VERSION, false, false, STORED), + arrayOf(false, 22, DEFAULT_COMPILE_SDK_VERSION, null, false, STORED), + arrayOf(false, 23, DEFAULT_COMPILE_SDK_VERSION, true, false, STORED), + arrayOf(false, 23, DEFAULT_COMPILE_SDK_VERSION, false, false, STORED), + arrayOf(false, 23, DEFAULT_COMPILE_SDK_VERSION, null, false, STORED), + arrayOf(null, 22, DEFAULT_COMPILE_SDK_VERSION, true, true, DEFLATED), + arrayOf(null, 22, DEFAULT_COMPILE_SDK_VERSION, false, false, STORED), + arrayOf(null, 22, DEFAULT_COMPILE_SDK_VERSION, null, true, DEFLATED), + arrayOf(null, 23, DEFAULT_COMPILE_SDK_VERSION, true, true, DEFLATED), + arrayOf(null, 23, DEFAULT_COMPILE_SDK_VERSION, false, false, STORED), + arrayOf(null, 23, DEFAULT_COMPILE_SDK_VERSION, null, false, STORED), + // test case with older compile SDK that doesn't recognize android:extractNativeLibs. + arrayOf(null, 22, 21, null, null, DEFLATED) ) } @@ -94,7 +99,7 @@ class ExtractNativeLibsPackagingTest( apply plugin: 'com.android.application' android { namespace "com.example" - compileSdk = ${GradleTestProject.DEFAULT_COMPILE_SDK_VERSION} + compileSdk = $compileSdk defaultConfig { minSdk = $minSdk } @@ -133,7 +138,7 @@ class ExtractNativeLibsPackagingTest( apply plugin: 'com.android.test' android { namespace "com.example" - compileSdk = ${GradleTestProject.DEFAULT_COMPILE_SDK_VERSION} + compileSdk = $compileSdk defaultConfig { minSdk = $minSdk } @@ -177,12 +182,12 @@ class ExtractNativeLibsPackagingTest( result.stdout.use { val resolvedUseLegacyPackaging: Boolean = useLegacyPackaging ?: (minSdk < 23) when { - resolvedUseLegacyPackaging && expectedCompression == ZipEntry.STORED -> { + resolvedUseLegacyPackaging && expectedCompression == STORED -> { assertThat(it).contains( "PackagingOptions.jniLibs.useLegacyPackaging should be set to false" ) } - !resolvedUseLegacyPackaging && expectedCompression == ZipEntry.DEFLATED -> { + !resolvedUseLegacyPackaging && expectedCompression == DEFLATED -> { assertThat(it).contains( "PackagingOptions.jniLibs.useLegacyPackaging should be set to true" ) diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/packaging/NativeSoPackagingOptionsTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/packaging/NativeSoPackagingOptionsTest.kt index 5987d315b0..b326a25a38 100644 --- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/packaging/NativeSoPackagingOptionsTest.kt +++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/packaging/NativeSoPackagingOptionsTest.kt @@ -154,9 +154,11 @@ class NativeSoPackagingOptionsTest { assertThat(nativeLibEntry.method).isEqualTo(ZipEntry.DEFLATED) } assertThat( - ApkSubject.getManifestContent(debugApkFile.toPath()).none { - it.contains("android:extractNativeLibs") - } + ApkSubject.getManifestContent(debugApkFile.toPath()).any { + // check strings separately because there are extra characters between them + // in this manifest. + it.contains("android:extractNativeLibs") && it.contains("=true") + } ).isTrue() val releaseApkFile = appSubProject.getApk(RELEASE).file.toFile() diff --git a/build-system/integration-test/application/src/test/resources/com/android/build/gradle/integration/model/HelloWorldAppModelTest_Versions.txt b/build-system/integration-test/application/src/test/resources/com/android/build/gradle/integration/model/HelloWorldAppModelTest_Versions.txt index 9244e28a45..90f7819470 100644 --- a/build-system/integration-test/application/src/test/resources/com/android/build/gradle/integration/model/HelloWorldAppModelTest_Versions.txt +++ b/build-system/integration-test/application/src/test/resources/com/android/build/gradle/integration/model/HelloWorldAppModelTest_Versions.txt @@ -1,20 +1,25 @@ > Versions: > versions: - android_dsl: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) - android_project: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) - basic_android_project: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) - native_module: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) - variant_dependencies: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) < versions - agp = DEFAULT_AGP_REVISION < Versions diff --git a/build-system/integration-test/application/src/test/resources/com/android/build/gradle/integration/model/HelloWorldLibModelTest_Versions.txt b/build-system/integration-test/application/src/test/resources/com/android/build/gradle/integration/model/HelloWorldLibModelTest_Versions.txt index 9244e28a45..90f7819470 100644 --- a/build-system/integration-test/application/src/test/resources/com/android/build/gradle/integration/model/HelloWorldLibModelTest_Versions.txt +++ b/build-system/integration-test/application/src/test/resources/com/android/build/gradle/integration/model/HelloWorldLibModelTest_Versions.txt @@ -1,20 +1,25 @@ > Versions: > versions: - android_dsl: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) - android_project: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) - basic_android_project: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) - native_module: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) - variant_dependencies: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) < versions - agp = DEFAULT_AGP_REVISION < Versions diff --git a/build-system/integration-test/application/src/test/resources/com/android/build/gradle/integration/model/PrivacySandboxSdkConsumerAppModelTest_Versions.txt b/build-system/integration-test/application/src/test/resources/com/android/build/gradle/integration/model/PrivacySandboxSdkConsumerAppModelTest_Versions.txt index 9244e28a45..90f7819470 100644 --- a/build-system/integration-test/application/src/test/resources/com/android/build/gradle/integration/model/PrivacySandboxSdkConsumerAppModelTest_Versions.txt +++ b/build-system/integration-test/application/src/test/resources/com/android/build/gradle/integration/model/PrivacySandboxSdkConsumerAppModelTest_Versions.txt @@ -1,20 +1,25 @@ > Versions: > versions: - android_dsl: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) - android_project: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) - basic_android_project: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) - native_module: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) - variant_dependencies: - - major = 0 - - minor = 1 + - major = 0 + - minor = 1 + - humanReadable = (null) < versions - agp = DEFAULT_AGP_REVISION < Versions diff --git a/build-system/integration-test/connected/BUILD.bazel b/build-system/integration-test/connected/BUILD.bazel index c0f292283f..5f2b8c5964 100644 --- a/build-system/integration-test/connected/BUILD.bazel +++ b/build-system/integration-test/connected/BUILD.bazel @@ -510,8 +510,8 @@ gradle_connected_test( srcs = "src/test/java/com/android/build/gradle/integration/connected/application/", avd = ":avd", data = TEST_DATA + [ - "//tools/base/build-system/integration-test:test-projects/mlModelBinding", "//prebuilts/tools/common/mlkit/testData", + "//tools/base/build-system/integration-test:test-projects/mlModelBinding", ], flaky = True, # b/148626301 flaky emulator connectivity maven_repo_zips = MAVEN_REPO_ZIPS, @@ -799,6 +799,18 @@ gradle_connected_test( deps = TEST_DEPS, ) +gradle_connected_test( + name = "KotlinMultiplatformAndroidConnectedTest", + srcs = "src/test/java/com/android/build/gradle/integration/connected/library/", + avd = ":avd", + data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/kotlinMultiplatform"], + maven_repo_zips = MAVEN_REPO_ZIPS + [ + "//tools/base/build-system:kmp_prototype", + ], + maven_repos = TEST_MAVEN_REPOS, + deps = TEST_DEPS, +) + # Maven repo with all the dependencies required by test projects. # # Quick way of updating this list: @@ -821,12 +833,13 @@ maven_repository( "@maven//:androidx.compose.material.material_1.3.0", "@maven//:androidx.compose.ui.ui-tooling_1.3.0", "@maven//:androidx.core.core-ktx_1.1.0", - "@maven//:androidx.lifecycle.lifecycle-common-java8_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-livedata-ktx_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-viewmodel-ktx_2.4.0", + "@maven//:androidx.lifecycle.lifecycle-common-java8_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-livedata-ktx_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-viewmodel-ktx_2.6.1", "@maven//:androidx.privacysandbox.tools.tools-apipackager_1.0.0-alpha02", "@maven//:androidx.privacysandbox.tools.tools_1.0.0-alpha02", "@maven//:androidx.test.core_1.4.0-alpha06", + "@maven//:androidx.test.core_1.5.0", "@maven//:androidx.test.espresso.espresso-core_3.2.0", "@maven//:androidx.test.ext.junit_1.1.2", "@maven//:androidx.test.ext.junit_1.1.3-alpha02", @@ -869,13 +882,14 @@ maven_repository( "@maven//:androidx.appcompat.appcompat_1.0.2", "@maven//:androidx.cardview.cardview_1.0.0", "@maven//:androidx.lifecycle.lifecycle-extensions_2.2.0", - "@maven//:androidx.lifecycle.lifecycle-livedata-ktx_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-livedata_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-process_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-runtime-ktx_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-runtime_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-service_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-viewmodel_2.4.0", + "@maven//:androidx.lifecycle.lifecycle-livedata-ktx_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-livedata_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-process_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-runtime-ktx_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-runtime_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-service_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-viewmodel-savedstate_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-viewmodel_2.6.1", "@maven//:androidx.test.espresso.espresso-core_3.1.0", "@maven//:com.android.support.appcompat-v7_26.1.0", "@maven//:com.android.support.test.espresso.espresso-core_3.0.1", diff --git a/build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/application/JacocoConnectedTest.java b/build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/application/JacocoConnectedTest.java index bcc9881bd2..969e1dda99 100644 --- a/build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/application/JacocoConnectedTest.java +++ b/build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/application/JacocoConnectedTest.java @@ -101,9 +101,9 @@ public class JacocoConnectedTest { + "android.defaultConfig.testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'\n" + "android.defaultConfig.testInstrumentationRunnerArguments package: 'com.example.helloworld'\n" + (enableClearPackageDataOption - ? "android.defaultConfig.testInstrumentationRunnerArguments clearPackageData: 'true'\n" - + "android.defaultConfig.testInstrumentationRunnerArguments useTestStorageService: 'true'\n" - : "") + ? "android.defaultConfig.testInstrumentationRunnerArguments clearPackageData: 'true'\n" + + "android.defaultConfig.testInstrumentationRunnerArguments useTestStorageService: 'true'\n" + : "") + "android.testOptions.execution 'ANDROIDX_TEST_ORCHESTRATOR'\n" // Orchestrator requires some setup time and it usually takes // about an minute. Increase the timeout for running "am instrument" command diff --git a/build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/library/KotlinMultiplatformAndroidConnectedTest.kt b/build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/library/KotlinMultiplatformAndroidConnectedTest.kt new file mode 100644 index 0000000000..292942517f --- /dev/null +++ b/build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/library/KotlinMultiplatformAndroidConnectedTest.kt @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2023 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.build.gradle.integration.connected.library + +import com.android.build.gradle.integration.common.fixture.BaseGradleExecutor +import com.android.build.gradle.integration.common.fixture.GradleTestProjectBuilder +import com.android.build.gradle.integration.common.utils.TestFileUtils +import com.android.build.gradle.integration.connected.utils.getEmulator +import com.android.utils.FileUtils +import com.google.common.truth.Truth +import org.junit.Before +import org.junit.ClassRule +import org.junit.Rule +import org.junit.Test + +class KotlinMultiplatformAndroidConnectedTest { + + companion object { + @JvmField + @ClassRule + val emulator = getEmulator() + } + + @Suppress("DEPRECATION") // kmp doesn't support configuration caching for now (b/276472789) + @get:Rule + val project = GradleTestProjectBuilder() + .fromTestProject("kotlinMultiplatform") + .withConfigurationCaching(BaseGradleExecutor.ConfigurationCaching.OFF) + .create() + + @Before + fun setUp() { + TestFileUtils.appendToFile( + project.getSubproject("kmpFirstLib").ktsBuildFile, + """ + android.enableInstrumentedTestCoverage = true + + kotlin.sourceSets.getByName("androidInstrumentedTest").dependencies { + implementation("androidx.core:core-ktx:1.1.0") + implementation("androidx.test.espresso:espresso-core:3.2.0") + } + """.trimIndent() + ) + + // fail fast if no response + project.addAdbTimeout() + // run the uninstall tasks in order to (1) make sure nothing is installed at the beginning + // of each test and (2) check the adb connection before taking the time to build anything. + project.execute("uninstallAll") + } + + @Test + fun connectedKmpLibraryTests() { + project.executor().run(":kmpFirstLib:connectedCheck") + + val testResultFolder = FileUtils.join( + project.getSubproject("kmpFirstLib").buildDir, + "reports", "androidTests", "connected", "kotlinAndroid" + ) + + Truth.assertThat(testResultFolder.exists()).isTrue() + + Truth.assertThat(testResultFolder.listFiles()!!.map { it.name }).containsAtLeast( + "com.example.kmpfirstlib.test.html", + "com.example.kmpfirstlib.test.KmpAndroidFirstLibActivityTest.html", + ) + + val coveragePackageFolder = FileUtils.join( + project.getSubproject("kmpFirstLib").buildDir, + "reports", "coverage", "androidTest", "main", "connected", "com.example.kmpfirstlib" + ) + + Truth.assertThat(coveragePackageFolder.exists()).isTrue() + + Truth.assertThat(coveragePackageFolder.listFiles()!!.map { it.name }).containsExactly( + "index.html", + "index.source.html", + + "KmpCommonFirstLibClass.html", + "KmpCommonFirstLibClass.kt.html", + + "KmpAndroidActivity.html", + "KmpAndroidActivity.kt.html", + + "KmpAndroidFirstLibClass.html", + "KmpAndroidFirstLibClass.kt.html", + ) + + val packageCoverageReport = FileUtils.join( + coveragePackageFolder, + "index.html" + ) + + val generatedCoverageReportHTML = packageCoverageReport.readLines().joinToString("\n") + + val totalCoverageMetricsContents = Regex("<tfoot>(.*?)</tfoot>") + .find(generatedCoverageReportHTML) + val totalCoverageInfo = Regex("<td class=\"ctr2\">(.*?)</td>") + .find(totalCoverageMetricsContents?.groups?.first()!!.value) + + val packageCoveragePercentage = totalCoverageInfo!!.groups[1]!!.value + + Truth.assertThat(packageCoveragePercentage.trimEnd('%').toInt() > 0).isTrue() + } +} diff --git a/build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/nativebuild/CmakeJniLibConnectedTest.java b/build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/nativebuild/CmakeJniLibConnectedTest.java index 36f8260d19..d2cace531f 100644 --- a/build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/nativebuild/CmakeJniLibConnectedTest.java +++ b/build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/nativebuild/CmakeJniLibConnectedTest.java @@ -52,8 +52,8 @@ public class CmakeJniLibConnectedTest { "\n" + "apply plugin: 'com.android.library'\n" + "android {\n" - + " compileSdkVersion rootProject.latestCompileSdk\n" - + " buildToolsVersion = rootProject.buildToolsVersion\n" + + " compileSdkVersion libs.versions.latestCompileSdk.get().toInteger()\n" + + " buildToolsVersion = libs.versions.buildToolsVersion.get()\n" + "}\n"); // Convert externalNativeBuild { ndkbuild { path "Android.mk" } } to diff --git a/build-system/integration-test/databinding/BUILD.bazel b/build-system/integration-test/databinding/BUILD.bazel index 0a32553567..86a215b9ec 100644 --- a/build-system/integration-test/databinding/BUILD.bazel +++ b/build-system/integration-test/databinding/BUILD.bazel @@ -115,12 +115,13 @@ maven_repository( "@maven//:androidx.collection.collection_1.0.0", "@maven//:androidx.lifecycle.lifecycle-extensions_2.2.0", "@maven//:androidx.lifecycle.lifecycle-livedata-ktx_2.3.1", - "@maven//:androidx.lifecycle.lifecycle-livedata-ktx_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-process_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-runtime-ktx_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-runtime_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-service_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-viewmodel-ktx_2.4.0", + "@maven//:androidx.lifecycle.lifecycle-livedata-ktx_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-process_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-runtime-ktx_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-runtime_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-service_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-viewmodel-ktx_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-viewmodel-savedstate_2.6.1", "@maven//:androidx.preference.preference_1.0.0", "@maven//:androidx.test.espresso.espresso-core_3.1.0", "@maven//:com.android.support.appcompat-v7_26.1.0", diff --git a/build-system/integration-test/databinding/incremental/BUILD.bazel b/build-system/integration-test/databinding/incremental/BUILD.bazel index 9fc1e0e105..7acf0f8aa9 100644 --- a/build-system/integration-test/databinding/incremental/BUILD.bazel +++ b/build-system/integration-test/databinding/incremental/BUILD.bazel @@ -57,13 +57,14 @@ maven_repository( "@maven//:androidx.appcompat.appcompat_1.0.0", "@maven//:androidx.constraintlayout.constraintlayout_1.1.3", "@maven//:androidx.lifecycle.lifecycle-extensions_2.2.0", - "@maven//:androidx.lifecycle.lifecycle-livedata-ktx_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-livedata_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-process_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-runtime-ktx_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-runtime_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-service_2.4.0", - "@maven//:androidx.lifecycle.lifecycle-viewmodel_2.4.0", + "@maven//:androidx.lifecycle.lifecycle-livedata-ktx_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-livedata_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-process_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-runtime-ktx_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-runtime_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-service_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-viewmodel-savedstate_2.6.1", + "@maven//:androidx.lifecycle.lifecycle-viewmodel_2.6.1", "@maven//:org.jetbrains.kotlinx.kotlinx-coroutines-android_1.4.1", ], ) diff --git a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleBuildResult.kt b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleBuildResult.kt index 6533947041..a4de9e6c36 100644 --- a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleBuildResult.kt +++ b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleBuildResult.kt @@ -16,6 +16,7 @@ package com.android.build.gradle.integration.common.fixture +import com.android.build.gradle.integration.common.truth.ScannerSubject import com.android.build.gradle.integration.common.truth.TaskStateList import com.google.common.base.Preconditions import com.google.common.base.Throwables @@ -151,4 +152,16 @@ class GradleBuildResult( private fun isPlaceholderEx(throwableType: String) = throwableType == PlaceholderException::class.java.name || throwableType == ContextualPlaceholderException::class.java.name + + fun assertOutputContains(text: String) { + stdout.use { + ScannerSubject.assertThat(it).contains(text) + } + } + + fun assertOutputDoesNotContain(text: String) { + stdout.use { + ScannerSubject.assertThat(it).doesNotContain(text) + } + } } diff --git a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleTaskExecutor.java b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleTaskExecutor.java index 2565f644f8..49f9020246 100644 --- a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleTaskExecutor.java +++ b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleTaskExecutor.java @@ -89,7 +89,6 @@ public final class GradleTaskExecutor extends BaseGradleExecutor<GradleTaskExecu public GradleBuildResult run(@NonNull List<String> tasksList) throws IOException, InterruptedException { - assertThat(tasksList).named("tasks list").isNotEmpty(); TestUtils.waitForFileSystemTick(); diff --git a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleTestProject.kt b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleTestProject.kt index 9c575a3ba6..07c24f5c0b 100644 --- a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleTestProject.kt +++ b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleTestProject.kt @@ -156,6 +156,7 @@ class GradleTestProject @JvmOverloads internal constructor( internal const val COMMON_LOCAL_REPO = "commonLocalRepo.gradle" private const val COMMON_BUILD_SCRIPT = "commonBuildScript.gradle" private const val COMMON_VERSIONS = "commonVersions.gradle" + private const val VERSION_CATALOG = "versionCatalog.gradle" const val DEFAULT_TEST_PROJECT_NAME = "project" @JvmStatic @@ -276,29 +277,6 @@ class GradleTestProject @JvmOverloads internal constructor( ) } - private fun generateVersionsForVersionCatalog(): String { - return String.format( - Locale.US, - "// Generated by GradleTestProject::generateVersionsForVersionCatalog%n" - + "version('buildVersion', '%s')%n" - + "version('baseVersion', '%s')%n" - + "version('supportLibVersion', '%s')%n" - + "version('testSupportLibVersion', '%s')%n" - + "version('playServicesVersion', '%s')%n" - + "version('supportLibMinSdk', '%d')%n" - + "version('ndk19SupportLibMinSdk', '%d')%n" - + "version('constraintLayoutVersion', '%s')%n", - Version.ANDROID_GRADLE_PLUGIN_VERSION, - Version.ANDROID_TOOLS_BASE_VERSION, - SUPPORT_LIB_VERSION, - TEST_SUPPORT_LIB_VERSION, - PLAY_SERVICES_VERSION, - SUPPORT_LIB_MIN_SDK, - NDK_19_SUPPORT_LIB_MIN_SDK, - SdkConstants.LATEST_CONSTRAINT_LAYOUT_VERSION - ) - } - /** * Returns a string that contains the gradle buildscript content */ @@ -378,6 +356,9 @@ class GradleTestProject @JvmOverloads internal constructor( val buildFile: File get() = File(location.projectDir, "build.gradle") + val ktsBuildFile: File + get() = File(location.projectDir, "build.gradle.kts") + val projectDir: File get() = location.projectDir @@ -579,6 +560,7 @@ class GradleTestProject @JvmOverloads internal constructor( val projectParentDir = projectDir.parent File(projectParentDir, COMMON_VERSIONS).writeText(generateVersions()) + File(projectParentDir, VERSION_CATALOG).writeText(generateVersionCatalog()) val projectRepoScript = generateProjectRepoScript() File(projectParentDir, COMMON_LOCAL_REPO).writeText(projectRepoScript) File(projectParentDir, COMMON_HEADER).writeText(generateCommonHeader()) @@ -1529,13 +1511,7 @@ dependencyResolutionManagement { settingsContent += """ -dependencyResolutionManagement { - versionCatalogs { - libs { - ${generateVersionsForVersionCatalog()} - } - } -} + apply from: "${File(projectDir.parent, "versionCatalog.gradle").toURI()}" """.trimIndent() @@ -1568,6 +1544,51 @@ buildCache { } } + private fun generateVersionCatalog(): String { + return """ + dependencyResolutionManagement { + versionCatalogs { + libs { + ${generateVersionsForVersionCatalog()} + } + } + } + """.trimIndent() + } + + private fun generateVersionsForVersionCatalog(): String { + return String.format( + Locale.US, + "// Generated by GradleTestProject::generateVersionsForVersionCatalog%n" + + "version('buildVersion', '%s')%n" + + "version('baseVersion', '%s')%n" + + "version('supportLibVersion', '%s')%n" + + "version('testSupportLibVersion', '%s')%n" + + "version('playServicesVersion', '%s')%n" + + "version('supportLibMinSdk', '%d')%n" + + "version('ndk19SupportLibMinSdk', '%d')%n" + + "version('constraintLayoutVersion', '%s')%n" + + "version('buildToolsVersion', '%s')%n" + + "version('latestCompileSdk', '%s')%n" + + "version('kotlinVersion', '%s')%n" + + "version('composeVersion', '%s')%n" + + "version('composeCompilerVersion', '%s')%n", + Version.ANDROID_GRADLE_PLUGIN_VERSION, + Version.ANDROID_TOOLS_BASE_VERSION, + SUPPORT_LIB_VERSION, + TEST_SUPPORT_LIB_VERSION, + PLAY_SERVICES_VERSION, + SUPPORT_LIB_MIN_SDK, + NDK_19_SUPPORT_LIB_MIN_SDK, + SdkConstants.LATEST_CONSTRAINT_LAYOUT_VERSION, + DEFAULT_BUILD_TOOL_VERSION, + compileSdkVersion, + kotlinVersion, + TaskManager.COMPOSE_UI_VERSION, + TaskManager.COMPOSE_KOTLIN_COMPILER_EXTENSION_VERSION, + ) + } + private fun createGradleProp() { if (gradleProperties.isEmpty()) { return diff --git a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/app/KotlinHelloWorldApp.java b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/app/KotlinHelloWorldApp.java index 3bdc7118d2..0374b1cd42 100644 --- a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/app/KotlinHelloWorldApp.java +++ b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/app/KotlinHelloWorldApp.java @@ -71,7 +71,7 @@ public class KotlinHelloWorldApp extends HelloWorldApp { + " apply from: '../commonHeader.gradle'\n" // for $kotlinVersion + " dependencies {\n" + " // Provides the 'android-kotlin' build plugin for the app:\n" - + " classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion\"\n" + + " classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}\"\n" + " }\n" + "}\n" + "apply plugin: '" @@ -82,8 +82,8 @@ public class KotlinHelloWorldApp extends HelloWorldApp { + " namespace \"" + NAMESPACE + "\"\n" - + " compileSdkVersion rootProject.latestCompileSdk\n" - + " buildToolsVersion = rootProject.buildToolsVersion\n" + + " compileSdkVersion libs.versions.latestCompileSdk.get().toInteger()\n" + + " buildToolsVersion = libs.versions.buildToolsVersion.get()\n" + " defaultConfig {\n" + " minSdkVersion libs.versions.supportLibMinSdk.get()\n" + " testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'\n" @@ -96,7 +96,7 @@ public class KotlinHelloWorldApp extends HelloWorldApp { + " }\n" + "}\n" + "dependencies {\n" - + " api \"org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion\"\n" + + " api \"org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}\"\n" + " androidTestImplementation \"com.android.support.test:runner:${libs.versions.testSupportLibVersion.get()}\"\n" + " androidTestImplementation \"com.android.support.test:rules:${libs.versions.testSupportLibVersion.get()}\"\n" + "}\n"); diff --git a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/gradle_project/BuildSystem.kt b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/gradle_project/BuildSystem.kt index 1eac01ac6d..5c41d2650d 100644 --- a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/gradle_project/BuildSystem.kt +++ b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/gradle_project/BuildSystem.kt @@ -76,7 +76,7 @@ internal enum class BuildSystem { } if (withKotlinGradlePlugin) { script.append( - " classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:\$rootProject.kotlinVersion\"\n" + " classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:\${libs.versions.kotlinVersion.get()}\"\n" ) } if (withDeviceProvider) { diff --git a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/model/Snapshotters.kt b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/model/Snapshotters.kt index 925763d303..d72c5d0063 100644 --- a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/model/Snapshotters.kt +++ b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/model/Snapshotters.kt @@ -78,8 +78,8 @@ internal fun ModelSnapshotter<Versions>.snapshotVersions() { ) { item("major", Version::major) item("minor", Version::minor) + item("humanReadable", Version::humanReadable) } - item("agp", Versions::agp) { version -> version?.let { normalizeAgpVersion(it) } } diff --git a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/testprojects/AndroidProjectBuilderImpl.kt b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/testprojects/AndroidProjectBuilderImpl.kt index abcb6e43ef..80577ce7fa 100644 --- a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/testprojects/AndroidProjectBuilderImpl.kt +++ b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/testprojects/AndroidProjectBuilderImpl.kt @@ -19,6 +19,7 @@ package com.android.build.gradle.integration.common.fixture.testprojects import com.android.build.api.dsl.AndroidResources import com.android.build.api.dsl.CompileOptions import com.android.build.gradle.integration.common.fixture.GradleTestProject +import com.android.build.gradle.integration.common.fixture.testprojects.CompileOptionsImpl.Companion.JAVA_VERSION_NOT_SET import com.google.common.base.Charsets import org.gradle.api.JavaVersion @@ -227,8 +228,14 @@ internal class AndroidProjectBuilderImpl( compileOptions?.let { options -> sb.append(" compileOptions {\n") + if (options.sourceCompatibility != JAVA_VERSION_NOT_SET) { + sb.append(" sourceCompatibility = ${options.sourceCompatibility}\n") + } + if (options.targetCompatibility != JAVA_VERSION_NOT_SET) { + sb.append(" targetCompatibility = ${options.targetCompatibility}\n") + } if (options.isCoreLibraryDesugaringEnabled) { - sb.append(" coreLibraryDesugaringEnabled = true") + sb.append(" coreLibraryDesugaringEnabled = true\n") } sb.append(" }\n") // COMPILE-OPTIONS } @@ -475,13 +482,22 @@ internal class AndroidResourcesImpl : AndroidResources { internal class CompileOptionsImpl: CompileOptions { + companion object { + + /** + * Special version to indicate that the value is not yet explicitly set (used as a + * substitute for null in places where the value must be not-null). + */ + val JAVA_VERSION_NOT_SET = JavaVersion.VERSION_1_1 + } + override var isCoreLibraryDesugaringEnabled: Boolean = false override var encoding: String = Charsets.UTF_8.name() - override var sourceCompatibility: JavaVersion = JavaVersion.VERSION_1_8 + override var sourceCompatibility: JavaVersion = JAVA_VERSION_NOT_SET - override var targetCompatibility: JavaVersion = JavaVersion.VERSION_1_8 + override var targetCompatibility: JavaVersion = JAVA_VERSION_NOT_SET override fun sourceCompatibility(sourceCompatibility: Any) { throw RuntimeException("Not yet implemented") diff --git a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/testprojects/TestProjectBuilder.kt b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/testprojects/TestProjectBuilder.kt index 2a32277293..780c28c2af 100644 --- a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/testprojects/TestProjectBuilder.kt +++ b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/testprojects/TestProjectBuilder.kt @@ -37,19 +37,26 @@ fun createProject(action: TestProjectBuilder.() -> Unit): TestProject { /** * Creates a [GradleTestProject] with the provided configuration action */ -fun createGradleProject(action: TestProjectBuilder.() -> Unit): GradleTestProject { - return createGradleProjectBuilder(action).create() +fun createGradleProject( + name: String? = null, + action: TestProjectBuilder.() -> Unit +): GradleTestProject { + return createGradleProjectBuilder(name, action).create() } /** * Creates a [GradleTestProjectBuilder] with the provided configuration action */ -fun createGradleProjectBuilder(action: TestProjectBuilder.() -> Unit): GradleTestProjectBuilder { +fun createGradleProjectBuilder( + name: String? = null, + action: TestProjectBuilder.() -> Unit +): GradleTestProjectBuilder { val builder = RootTestProjectBuilderImpl() action(builder) return GradleTestProject .builder() + .apply { name?.let { withName(it) } } .fromTestApp(builder) .withKotlinGradlePlugin(builder.withKotlinPlugin) .withAdditionalMavenRepo(builder.mavenRepoGenerator) diff --git a/build-system/integration-test/managed-devices/BUILD.bazel b/build-system/integration-test/managed-devices/BUILD.bazel index 06037b0bfb..e8479fa8fe 100644 --- a/build-system/integration-test/managed-devices/BUILD.bazel +++ b/build-system/integration-test/managed-devices/BUILD.bazel @@ -66,6 +66,19 @@ TEST_MAVEN_REPOS = [ ] gradle_connected_test( + name = "FirebaseTestLabDeviceTest", + srcs = "src/test/java/com/android/build/gradle/integration/manageddevice/application/", + avd = None, + data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/utp"], + maven_repo_zips = MAVEN_REPO_ZIPS + [ + "//tools/base/firebase/testlab/testlab-gradle-plugin:maven_dependencies", + "//tools/base/firebase/testlab/testlab-gradle-plugin:testlab-gradle-plugin", + ], + maven_repos = TEST_MAVEN_REPOS, + deps = TEST_DEPS, +) + +gradle_connected_test( name = "ManagedDeviceExtensionTest", srcs = "src/test/java/com/android/build/gradle/integration/manageddevice/application/", avd = None, diff --git a/build-system/integration-test/managed-devices/src/test/java/com/android/build/gradle/integration/manageddevice/application/FirebaseTestLabDeviceTest.kt b/build-system/integration-test/managed-devices/src/test/java/com/android/build/gradle/integration/manageddevice/application/FirebaseTestLabDeviceTest.kt new file mode 100644 index 0000000000..7d02656311 --- /dev/null +++ b/build-system/integration-test/managed-devices/src/test/java/com/android/build/gradle/integration/manageddevice/application/FirebaseTestLabDeviceTest.kt @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2023 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.build.gradle.integration.manageddevice.application + +import com.android.build.gradle.integration.common.fixture.GradleTaskExecutor +import com.android.build.gradle.integration.common.fixture.GradleTestProjectBuilder +import com.android.build.gradle.integration.common.truth.ScannerSubject.Companion.assertThat +import org.junit.Before +import org.junit.Rule +import org.junit.Test + +class FirebaseTestLabDeviceTest { + @get:Rule + val project = GradleTestProjectBuilder() + .fromTestProject("utp") + .enableProfileOutput() + .create() + + private val executor: GradleTaskExecutor + get() = project.executor() + + @Before + fun setUp() { + project.rootProject.buildFile.appendText(""" + buildscript { + dependencies { + classpath "com.google.firebase.testlab:testlab-gradle-plugin:0.0.1-dev" + } + } + project.buildscript { + dependencies { + classpath "com.google.firebase.testlab:testlab-gradle-plugin:0.0.1-dev" + } + } + """.trimIndent()) + project.gradlePropertiesFile.appendText(""" + android.experimental.testOptions.managedDevices.customDevice=true + """.trimIndent()) + + val appBuildFileContent = project.getSubproject("app").buildFile.readText() + project.getSubproject("app").buildFile.writeText(""" + apply plugin: 'com.google.firebase.testlab' + """.trimIndent()+"\n$appBuildFileContent") + project.getSubproject("app").buildFile.appendText(""" + firebaseTestLab { + managedDevices { + myFtlDevice1 { + device = "Pixel2" + apiLevel = 29 + } + myFtlDevice2 { + device = "Pixel3" + apiLevel = 30 + orientation = "landscape" + locale = "en-US" + } + } + } + """) + + val ktBuildFileContent = project.getSubproject("kotlinDslApp").ktsBuildFile.readText() + project.getSubproject("kotlinDslApp").ktsBuildFile.writeText( + ktBuildFileContent.replace( + "plugins {", + "plugins { id(\"com.google.firebase.testlab\")")) + project.getSubproject("kotlinDslApp").ktsBuildFile.appendText(""" + firebaseTestLab { + managedDevices { + create("myFtlDevice3") { + device = "Pixel2" + apiLevel = 29 + } + create("myFtlDevice4") { + device = "Pixel3" + apiLevel = 30 + orientation = "landscape" + locale = "en-US" + } + } + } + """) + } + + @Test + fun ftlManagedDeviceTasks() { + val result = executor.run("tasks") + result.stdout.use { + assertThat(it).contains("myFtlDevice1Check") + assertThat(it).contains("myFtlDevice1DebugAndroidTest") + assertThat(it).contains("myFtlDevice2Check") + assertThat(it).contains("myFtlDevice2DebugAndroidTest") + assertThat(it).contains("myFtlDevice3Check") + assertThat(it).contains("myFtlDevice3DebugAndroidTest") + assertThat(it).contains("myFtlDevice4Check") + assertThat(it).contains("myFtlDevice4DebugAndroidTest") + } + } + + @Test + fun dsl() { + project.getSubproject("app").buildFile.appendText(""" + firebaseTestLab { + serviceAccountCredentials = file("test.json") + testOptions { + fixture { + grantedPermissions = "none" + extraDeviceFiles["/sdcard/Android/data/com.example.myapplication/myAdditionalText.txt"] = "app/myAdditionalText.txt" + networkProfile = "LTE" + } + results { + cloudStorageBucket = "my_example_custom_bucket" + resultsHistoryName = "MyCustomHistoryName" + directoriesToPull.addAll("/sdcard/Android/data/com.example.myapplication") + } + } + } + task("printDslProperties") { + println("orientation = " + firebaseTestLab.managedDevices.getByName("myFtlDevice2").orientation) + println("serviceAccountCredentials = " + firebaseTestLab.serviceAccountCredentials.asFile.get().name) + println("grantedPermissions = " + firebaseTestLab.testOptions.fixture.grantedPermissions) + println("extraDeviceFiles = " + firebaseTestLab.testOptions.fixture.extraDeviceFiles.get()) + println("networkProfile = " + firebaseTestLab.testOptions.fixture.networkProfile) + println("cloudStorageBucket = " + firebaseTestLab.testOptions.results.cloudStorageBucket) + println("resultsHistoryName = " + firebaseTestLab.testOptions.results.resultsHistoryName) + println("directoriesToPull = " + firebaseTestLab.testOptions.results.directoriesToPull.get()) + doLast { /* no-op */ } + } + """) + val result = executor.run(":app:printDslProperties") + result.stdout.use { + assertThat(it).contains("orientation = LANDSCAPE") + assertThat(it).contains("serviceAccountCredentials = test.json") + assertThat(it).contains("grantedPermissions = NONE") + assertThat(it).contains("extraDeviceFiles = [/sdcard/Android/data/com.example.myapplication/myAdditionalText.txt:app/myAdditionalText.txt]") + assertThat(it).contains("networkProfile = LTE") + assertThat(it).contains("cloudStorageBucket = my_example_custom_bucket") + assertThat(it).contains("resultsHistoryName = MyCustomHistoryName") + assertThat(it).contains("directoriesToPull = [/sdcard/Android/data/com.example.myapplication]") + } + } + + @Test + fun kotlinDsl() { + project.getSubproject("kotlinDslApp").ktsBuildFile.appendText(""" + firebaseTestLab { + serviceAccountCredentials.set(file("test.json")) + testOptions { + fixture { + grantedPermissions = "none" + extraDeviceFiles.put("/sdcard/Android/data/com.example.myapplication/myAdditionalText.txt", "app/myAdditionalText.txt") + networkProfile = "LTE" + } + results { + cloudStorageBucket = "my_example_custom_bucket" + resultsHistoryName = "MyCustomHistoryName" + directoriesToPull.addAll("/sdcard/Android/data/com.example.myapplication") + } + } + } + task("printDslProperties") { + println("orientation = " + firebaseTestLab.managedDevices.getByName("myFtlDevice4").orientation) + println("serviceAccountCredentials = " + firebaseTestLab.serviceAccountCredentials.asFile.get().name) + println("grantedPermissions = " + firebaseTestLab.testOptions.fixture.grantedPermissions) + println("extraDeviceFiles = " + firebaseTestLab.testOptions.fixture.extraDeviceFiles.get()) + println("networkProfile = " + firebaseTestLab.testOptions.fixture.networkProfile) + println("cloudStorageBucket = " + firebaseTestLab.testOptions.results.cloudStorageBucket) + println("resultsHistoryName = " + firebaseTestLab.testOptions.results.resultsHistoryName) + println("directoriesToPull = " + firebaseTestLab.testOptions.results.directoriesToPull.get()) + doLast { /* no-op */ } + } + """) + val result = executor.run(":kotlinDslApp:printDslProperties") + result.stdout.use { + assertThat(it).contains("orientation = LANDSCAPE") + assertThat(it).contains("serviceAccountCredentials = test.json") + assertThat(it).contains("grantedPermissions = NONE") + assertThat(it).contains("extraDeviceFiles = {/sdcard/Android/data/com.example.myapplication/myAdditionalText.txt=app/myAdditionalText.txt}") + assertThat(it).contains("networkProfile = LTE") + assertThat(it).contains("cloudStorageBucket = my_example_custom_bucket") + assertThat(it).contains("resultsHistoryName = MyCustomHistoryName") + assertThat(it).contains("directoriesToPull = [/sdcard/Android/data/com.example.myapplication]") + } + } +} diff --git a/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/nativebuild/CmakeJniLibTest.java b/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/nativebuild/CmakeJniLibTest.java index 70678cb291..afe517bee8 100644 --- a/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/nativebuild/CmakeJniLibTest.java +++ b/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/nativebuild/CmakeJniLibTest.java @@ -65,8 +65,8 @@ public class CmakeJniLibTest { + "apply plugin: 'com.android.library'\n" + "android {\n" + " namespace \"com.example.hellojni\"\n" - + " compileSdkVersion rootProject.latestCompileSdk\n" - + " buildToolsVersion = rootProject.buildToolsVersion\n" + + " compileSdkVersion libs.versions.latestCompileSdk.get().toInteger()\n" + + " buildToolsVersion = libs.versions.buildToolsVersion.get()\n" + "}\n"); // Convert externalNativeBuild { ndkbuild { path "Android.mk" } } to diff --git a/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/nativebuild/NdkBuildJniLibTest.java b/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/nativebuild/NdkBuildJniLibTest.java index cf3d7dcc72..dd3157c1d0 100644 --- a/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/nativebuild/NdkBuildJniLibTest.java +++ b/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/nativebuild/NdkBuildJniLibTest.java @@ -77,8 +77,8 @@ public class NdkBuildJniLibTest { + "apply plugin: 'com.android.library'\n" + "android {\n" + " namespace \"com.example.hellojni.lib\"\n" - + " compileSdkVersion rootProject.latestCompileSdk\n" - + " buildToolsVersion = rootProject.buildToolsVersion\n" + + " compileSdkVersion libs.versions.latestCompileSdk.get().toInteger()\n" + + " buildToolsVersion = libs.versions.buildToolsVersion.get()\n" + " defaultConfig {\n" + " minSdkVersion 21\n" + " }\n" diff --git a/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/ndk/PrefabPublishingTest.kt b/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/ndk/PrefabPublishingTest.kt index fa25a5fba9..41c99e54bd 100644 --- a/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/ndk/PrefabPublishingTest.kt +++ b/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/ndk/PrefabPublishingTest.kt @@ -324,12 +324,13 @@ class PrefabPublishingTest( android { namespace "com.example.foo" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 16 - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() + externalNativeBuild { if (!project.hasProperty("ndkBuild")) { @@ -456,12 +457,13 @@ class PrefabPublishingTest( android { namespace "com.example.foo" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 16 - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() + externalNativeBuild { if (!project.hasProperty("ndkBuild")) { diff --git a/build-system/integration-test/test-projects/BasicRenderScript/build.gradle b/build-system/integration-test/test-projects/BasicRenderScript/build.gradle index 897506ed6d..04461d0e3b 100644 --- a/build-system/integration-test/test-projects/BasicRenderScript/build.gradle +++ b/build-system/integration-test/test-projects/BasicRenderScript/build.gradle @@ -25,8 +25,8 @@ List<String> dirs = [ android { namespace "com.example.android.basicrenderscript" testNamespace "com.example.android.basicrenderscript.tests" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 14 diff --git a/build-system/integration-test/test-projects/additionalTestOutput/build.gradle b/build-system/integration-test/test-projects/additionalTestOutput/build.gradle index cf7c264002..34631435b8 100644 --- a/build-system/integration-test/test-projects/additionalTestOutput/build.gradle +++ b/build-system/integration-test/test-projects/additionalTestOutput/build.gradle @@ -21,8 +21,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion libs.versions.buildToolsVersion.get() testBuildType "debug" diff --git a/build-system/integration-test/test-projects/additionalTestOutputOverride/build.gradle b/build-system/integration-test/test-projects/additionalTestOutputOverride/build.gradle index 48df42c533..64367003fa 100644 --- a/build-system/integration-test/test-projects/additionalTestOutputOverride/build.gradle +++ b/build-system/integration-test/test-projects/additionalTestOutputOverride/build.gradle @@ -21,8 +21,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion libs.versions.buildToolsVersion.get() testBuildType "debug" diff --git a/build-system/integration-test/test-projects/androidManifestInTest/build.gradle b/build-system/integration-test/test-projects/androidManifestInTest/build.gradle index d127062427..ee6f69815e 100644 --- a/build-system/integration-test/test-projects/androidManifestInTest/build.gradle +++ b/build-system/integration-test/test-projects/androidManifestInTest/build.gradle @@ -16,8 +16,8 @@ dependencies { android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion libs.versions.buildToolsVersion.get() testBuildType "debug" diff --git a/build-system/integration-test/test-projects/androidTestLibDep/build.gradle b/build-system/integration-test/test-projects/androidTestLibDep/build.gradle index a54b4eb7b2..279b9538a0 100644 --- a/build-system/integration-test/test-projects/androidTestLibDep/build.gradle +++ b/build-system/integration-test/test-projects/androidTestLibDep/build.gradle @@ -14,8 +14,8 @@ dependencies { android { namespace "com.android.tests.libdeps" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/api/app/build.gradle b/build-system/integration-test/test-projects/api/app/build.gradle index acbb760a8f..51614202c2 100644 --- a/build-system/integration-test/test-projects/api/app/build.gradle +++ b/build-system/integration-test/test-projects/api/app/build.gradle @@ -6,8 +6,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/api/lib/build.gradle b/build-system/integration-test/test-projects/api/lib/build.gradle index d5942f6778..61f1786d0c 100644 --- a/build-system/integration-test/test-projects/api/lib/build.gradle +++ b/build-system/integration-test/test-projects/api/lib/build.gradle @@ -6,8 +6,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.libstest.lib2" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/appWithTests/build.gradle b/build-system/integration-test/test-projects/appWithTests/build.gradle index 1ffd9d7c1a..75d723f349 100644 --- a/build-system/integration-test/test-projects/appWithTests/build.gradle +++ b/build-system/integration-test/test-projects/appWithTests/build.gradle @@ -19,8 +19,8 @@ apply plugin: 'com.android.application' android { namespace "android.testing.testapp" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/applibtest/app/build.gradle b/build-system/integration-test/test-projects/applibtest/app/build.gradle index 96058d9e3a..29326d924e 100644 --- a/build-system/integration-test/test-projects/applibtest/app/build.gradle +++ b/build-system/integration-test/test-projects/applibtest/app/build.gradle @@ -4,8 +4,8 @@ apply from: "../../commonHeader.gradle" android { namespace "com.android.tests.testprojecttest.app" testNamespace "com.android.tests.testprojecttest.test" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/applibtest/lib/build.gradle b/build-system/integration-test/test-projects/applibtest/lib/build.gradle index 106312fb2e..6ff3ebf7e2 100644 --- a/build-system/integration-test/test-projects/applibtest/lib/build.gradle +++ b/build-system/integration-test/test-projects/applibtest/lib/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.testprojecttest.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { testApplicationId = "com.android.tests.testprojecttest.testlib" diff --git a/build-system/integration-test/test-projects/applicationIdInLibsTest/app/build.gradle b/build-system/integration-test/test-projects/applicationIdInLibsTest/app/build.gradle index 2feecb661c..670c25c461 100644 --- a/build-system/integration-test/test-projects/applicationIdInLibsTest/app/build.gradle +++ b/build-system/integration-test/test-projects/applicationIdInLibsTest/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.manifest_merger_example" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { applicationId "com.example.manifest_merger_example" diff --git a/build-system/integration-test/test-projects/applicationIdInLibsTest/examplelibrary/build.gradle b/build-system/integration-test/test-projects/applicationIdInLibsTest/examplelibrary/build.gradle index ab6c92406d..9e24cfbfcb 100644 --- a/build-system/integration-test/test-projects/applicationIdInLibsTest/examplelibrary/build.gradle +++ b/build-system/integration-test/test-projects/applicationIdInLibsTest/examplelibrary/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.mylibrary" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 diff --git a/build-system/integration-test/test-projects/artifactApi/build.gradle b/build-system/integration-test/test-projects/artifactApi/build.gradle index d7de5ee42a..b8edb94453 100644 --- a/build-system/integration-test/test-projects/artifactApi/build.gradle +++ b/build-system/integration-test/test-projects/artifactApi/build.gradle @@ -60,8 +60,8 @@ dependencies { android { namespace "com.android.tests.overlay2" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() flavorDimensions "pricing", "releaseType" diff --git a/build-system/integration-test/test-projects/asmTransformApi/app/build.gradle b/build-system/integration-test/test-projects/asmTransformApi/app/build.gradle index 09f923578f..f0b14f5f2a 100644 --- a/build-system/integration-test/test-projects/asmTransformApi/app/build.gradle +++ b/build-system/integration-test/test-projects/asmTransformApi/app/build.gradle @@ -8,8 +8,8 @@ plugins { android { namespace "com.example.myapplication" dynamicFeatures = [":feature"] - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 26 @@ -35,7 +35,7 @@ dependencies { implementation(fileTree("libs") { include("*.jar", "*.aar") }) implementation project(':instrumentationLib') implementation project(':lib') - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" testImplementation 'junit:junit:4.12' } diff --git a/build-system/integration-test/test-projects/asmTransformApi/build.gradle b/build-system/integration-test/test-projects/asmTransformApi/build.gradle index 32eaaa98ae..087c4ec594 100644 --- a/build-system/integration-test/test-projects/asmTransformApi/build.gradle +++ b/build-system/integration-test/test-projects/asmTransformApi/build.gradle @@ -4,6 +4,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } -}
\ No newline at end of file +} diff --git a/build-system/integration-test/test-projects/asmTransformApi/buildSrc/build.gradle b/build-system/integration-test/test-projects/asmTransformApi/buildSrc/build.gradle index 6fd1829bec..39afb67dad 100644 --- a/build-system/integration-test/test-projects/asmTransformApi/buildSrc/build.gradle +++ b/build-system/integration-test/test-projects/asmTransformApi/buildSrc/build.gradle @@ -4,7 +4,7 @@ buildscript { apply from: "../../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/asmTransformApi/buildSrc/settings.gradle b/build-system/integration-test/test-projects/asmTransformApi/buildSrc/settings.gradle new file mode 100644 index 0000000000..5efb45ea97 --- /dev/null +++ b/build-system/integration-test/test-projects/asmTransformApi/buildSrc/settings.gradle @@ -0,0 +1 @@ +apply from: "../../versionCatalog.gradle" diff --git a/build-system/integration-test/test-projects/asmTransformApi/feature/build.gradle b/build-system/integration-test/test-projects/asmTransformApi/feature/build.gradle index aa83b19f73..b7040bea41 100644 --- a/build-system/integration-test/test-projects/asmTransformApi/feature/build.gradle +++ b/build-system/integration-test/test-projects/asmTransformApi/feature/build.gradle @@ -22,7 +22,7 @@ plugins { android { namespace "com.example.feature" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/asmTransformApi/instrumentationLib/build.gradle b/build-system/integration-test/test-projects/asmTransformApi/instrumentationLib/build.gradle index 48852c2583..e1a50e85ea 100644 --- a/build-system/integration-test/test-projects/asmTransformApi/instrumentationLib/build.gradle +++ b/build-system/integration-test/test-projects/asmTransformApi/instrumentationLib/build.gradle @@ -14,5 +14,5 @@ compileKotlin { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/asmTransformApi/lib/build.gradle b/build-system/integration-test/test-projects/asmTransformApi/lib/build.gradle index b6d8182e39..99b6fd08bc 100644 --- a/build-system/integration-test/test-projects/asmTransformApi/lib/build.gradle +++ b/build-system/integration-test/test-projects/asmTransformApi/lib/build.gradle @@ -6,7 +6,7 @@ plugins { android { namespace "com.example.lib" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8 } @@ -15,5 +15,5 @@ android { apply from: "../../commonHeader.gradle" // for $kotlinVersion dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/assets/app/build.gradle b/build-system/integration-test/test-projects/assets/app/build.gradle index 8c775ec006..24f486dffb 100644 --- a/build-system/integration-test/test-projects/assets/app/build.gradle +++ b/build-system/integration-test/test-projects/assets/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.assets.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/assets/lib/build.gradle b/build-system/integration-test/test-projects/assets/lib/build.gradle index 118fbc0f9e..842d6fabc1 100644 --- a/build-system/integration-test/test-projects/assets/lib/build.gradle +++ b/build-system/integration-test/test-projects/assets/lib/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.assets.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/attrOrder/app/build.gradle b/build-system/integration-test/test-projects/attrOrder/app/build.gradle index ea01102268..6b6c28849a 100644 --- a/build-system/integration-test/test-projects/attrOrder/app/build.gradle +++ b/build-system/integration-test/test-projects/attrOrder/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/attrOrder/lib/build.gradle b/build-system/integration-test/test-projects/attrOrder/lib/build.gradle index 063f30a1f1..4a28da2e49 100644 --- a/build-system/integration-test/test-projects/attrOrder/lib/build.gradle +++ b/build-system/integration-test/test-projects/attrOrder/lib/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.libstest.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/basic/build.gradle b/build-system/integration-test/test-projects/basic/build.gradle index 3d3fe3936a..6a44f83850 100644 --- a/build-system/integration-test/test-projects/basic/build.gradle +++ b/build-system/integration-test/test-projects/basic/build.gradle @@ -23,8 +23,8 @@ dependencies { android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() testBuildType "debug" diff --git a/build-system/integration-test/test-projects/basicMultiFlavors/build.gradle b/build-system/integration-test/test-projects/basicMultiFlavors/build.gradle index 9c0e9d415b..a353258384 100644 --- a/build-system/integration-test/test-projects/basicMultiFlavors/build.gradle +++ b/build-system/integration-test/test-projects/basicMultiFlavors/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.flavored" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { maxSdkVersion 15 diff --git a/build-system/integration-test/test-projects/builderTestingApiUse/app/build.gradle b/build-system/integration-test/test-projects/builderTestingApiUse/app/build.gradle index 4597bfe41a..c54a994330 100644 --- a/build-system/integration-test/test-projects/builderTestingApiUse/app/build.gradle +++ b/build-system/integration-test/test-projects/builderTestingApiUse/app/build.gradle @@ -6,8 +6,8 @@ project.ext.fakeServer = new com.android.tests.basic.buildscript.FakeServer() android { namespace "com.android.tests.testprojecttest.app" testNamespace "com.android.tests.testprojecttest.test" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() deviceProvider project.fakeProvider testServer project.fakeServer diff --git a/build-system/integration-test/test-projects/builderTestingApiUse/lib/build.gradle b/build-system/integration-test/test-projects/builderTestingApiUse/lib/build.gradle index 2b0934392a..e3154ee358 100644 --- a/build-system/integration-test/test-projects/builderTestingApiUse/lib/build.gradle +++ b/build-system/integration-test/test-projects/builderTestingApiUse/lib/build.gradle @@ -5,8 +5,8 @@ project.ext.fakeServer = new com.android.tests.basic.buildscript.FakeServer() android { namespace "com.android.tests.testprojecttest.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() deviceProvider project.fakeProvider testServer project.fakeServer diff --git a/build-system/integration-test/test-projects/butterknife/build.gradle b/build-system/integration-test/test-projects/butterknife/build.gradle index 1d46b83bb8..e90f6143c2 100644 --- a/build-system/integration-test/test-projects/butterknife/build.gradle +++ b/build-system/integration-test/test-projects/butterknife/build.gradle @@ -21,13 +21,14 @@ apply plugin: 'com.android.application' android { namespace "com.example.bk" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() + } } diff --git a/build-system/integration-test/test-projects/bytecodeGenerationHooks/app/build.gradle b/build-system/integration-test/test-projects/bytecodeGenerationHooks/app/build.gradle index bbac9b01db..721a7da787 100644 --- a/build-system/integration-test/test-projects/bytecodeGenerationHooks/app/build.gradle +++ b/build-system/integration-test/test-projects/bytecodeGenerationHooks/app/build.gradle @@ -3,8 +3,8 @@ apply plugin: 'com.example.compiler' android { namespace "com.example.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/bytecodeGenerationHooks/library/build.gradle b/build-system/integration-test/test-projects/bytecodeGenerationHooks/library/build.gradle index fd09d3d9af..d411af33b8 100644 --- a/build-system/integration-test/test-projects/bytecodeGenerationHooks/library/build.gradle +++ b/build-system/integration-test/test-projects/bytecodeGenerationHooks/library/build.gradle @@ -3,8 +3,8 @@ apply plugin: 'com.example.compiler' android { namespace "com.example.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/bytecodeGenerationHooks/test/build.gradle b/build-system/integration-test/test-projects/bytecodeGenerationHooks/test/build.gradle index 29a157fc4d..63ec38ca5f 100644 --- a/build-system/integration-test/test-projects/bytecodeGenerationHooks/test/build.gradle +++ b/build-system/integration-test/test-projects/bytecodeGenerationHooks/test/build.gradle @@ -3,8 +3,8 @@ apply plugin: 'com.example.compiler' android { namespace "com.android.tests.basic.test" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/combinedAbiDensitySplits/build.gradle b/build-system/integration-test/test-projects/combinedAbiDensitySplits/build.gradle index abed8da216..970392f3dc 100644 --- a/build-system/integration-test/test-projects/combinedAbiDensitySplits/build.gradle +++ b/build-system/integration-test/test-projects/combinedAbiDensitySplits/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.combinedSplits" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 21 diff --git a/build-system/integration-test/test-projects/combinedDensityAndLanguageSplits/build.gradle b/build-system/integration-test/test-projects/combinedDensityAndLanguageSplits/build.gradle index 5a76242781..4b4bd579ff 100644 --- a/build-system/integration-test/test-projects/combinedDensityAndLanguageSplits/build.gradle +++ b/build-system/integration-test/test-projects/combinedDensityAndLanguageSplits/build.gradle @@ -6,8 +6,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/composeHelloWorld/app/build.gradle b/build-system/integration-test/test-projects/composeHelloWorld/app/build.gradle index 6968996f5f..cc0db5a41e 100644 --- a/build-system/integration-test/test-projects/composeHelloWorld/app/build.gradle +++ b/build-system/integration-test/test-projects/composeHelloWorld/app/build.gradle @@ -3,13 +3,13 @@ apply plugin: 'kotlin-android' android { namespace "com.example.helloworldcompose" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() defaultConfig { applicationId "com.example.helloworldcompose" minSdkVersion 21 - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -33,7 +33,7 @@ android { ] } composeOptions { - kotlinCompilerExtensionVersion = "${rootProject.composeCompilerVersion}" + kotlinCompilerExtensionVersion = "${libs.versions.composeCompilerVersion.get()}" } } dependencies { @@ -43,9 +43,9 @@ dependencies { implementation 'androidx.fragment:fragment:1.3.+' implementation 'androidx.core:core-ktx:1.1.0' implementation "androidx.activity:activity-compose:1.5.1" - implementation "androidx.compose.ui:ui:${rootProject.composeVersion}" - implementation "androidx.compose.material:material:${rootProject.composeVersion}" - implementation "androidx.compose.ui:ui-tooling:${rootProject.composeVersion}" + implementation "androidx.compose.ui:ui:${libs.versions.composeVersion.get()}" + implementation "androidx.compose.material:material:${libs.versions.composeVersion.get()}" + implementation "androidx.compose.ui:ui-tooling:${libs.versions.composeVersion.get()}" implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-common:+' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.3-alpha02' diff --git a/build-system/integration-test/test-projects/conditionalApiUse/build.gradle b/build-system/integration-test/test-projects/conditionalApiUse/build.gradle index 42d726c2cc..18d46f7cba 100644 --- a/build-system/integration-test/test-projects/conditionalApiUse/build.gradle +++ b/build-system/integration-test/test-projects/conditionalApiUse/build.gradle @@ -6,7 +6,7 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.conditionalApiUse" compileSdkVersion 24 - buildToolsVersion = rootProject.buildToolsVersion + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { applicationId "com.android.tests.conditionalApiUse" minSdkVersion 19 diff --git a/build-system/integration-test/test-projects/customArtifactDep/app/build.gradle b/build-system/integration-test/test-projects/customArtifactDep/app/build.gradle index 2f94f51245..ef10a3d8da 100644 --- a/build-system/integration-test/test-projects/customArtifactDep/app/build.gradle +++ b/build-system/integration-test/test-projects/customArtifactDep/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.android.multiproject" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } dependencies { diff --git a/build-system/integration-test/test-projects/dagger-hilt-flavored-project/app/build.gradle b/build-system/integration-test/test-projects/dagger-hilt-flavored-project/app/build.gradle index b96609b141..f13aabc847 100644 --- a/build-system/integration-test/test-projects/dagger-hilt-flavored-project/app/build.gradle +++ b/build-system/integration-test/test-projects/dagger-hilt-flavored-project/app/build.gradle @@ -21,7 +21,7 @@ plugins { android { namespace "simple.app" - compileSdkVersion = rootProject.latestCompileSdk + compileSdkVersion = libs.versions.latestCompileSdk.get().toInteger() flavorDimensions 'api', 'version' productFlavors { diff --git a/build-system/integration-test/test-projects/dagger-hilt-flavored-project/feature/build.gradle b/build-system/integration-test/test-projects/dagger-hilt-flavored-project/feature/build.gradle index 33f5ee4014..c9c53a5739 100644 --- a/build-system/integration-test/test-projects/dagger-hilt-flavored-project/feature/build.gradle +++ b/build-system/integration-test/test-projects/dagger-hilt-flavored-project/feature/build.gradle @@ -21,7 +21,7 @@ plugins { android { namespace "simple.library" - compileSdkVersion = rootProject.latestCompileSdk + compileSdkVersion = libs.versions.latestCompileSdk.get().toInteger() flavorDimensions 'api', 'version' productFlavors { diff --git a/build-system/integration-test/test-projects/daggerOne/build.gradle b/build-system/integration-test/test-projects/daggerOne/build.gradle index 0cd705cd7f..73c6e669d5 100644 --- a/build-system/integration-test/test-projects/daggerOne/build.gradle +++ b/build-system/integration-test/test-projects/daggerOne/build.gradle @@ -21,8 +21,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } dependencies { diff --git a/build-system/integration-test/test-projects/daggerTwo/build.gradle b/build-system/integration-test/test-projects/daggerTwo/build.gradle index ed6625a874..1e19eb4e14 100644 --- a/build-system/integration-test/test-projects/daggerTwo/build.gradle +++ b/build-system/integration-test/test-projects/daggerTwo/build.gradle @@ -25,8 +25,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } dependencies { diff --git a/build-system/integration-test/test-projects/databinding/build.forexperimental.gradle b/build-system/integration-test/test-projects/databinding/build.forexperimental.gradle index 4159aee252..4b7b89af79 100644 --- a/build-system/integration-test/test-projects/databinding/build.forexperimental.gradle +++ b/build-system/integration-test/test-projects/databinding/build.forexperimental.gradle @@ -21,8 +21,8 @@ apply plugin: 'com.android.model.application' model { android { namespace = "android.databinding.testapp" - compileSdkVersion = rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion = libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } android.dataBinding { diff --git a/build-system/integration-test/test-projects/databinding/build.gradle b/build-system/integration-test/test-projects/databinding/build.gradle index 620685a749..cd5386fc95 100644 --- a/build-system/integration-test/test-projects/databinding/build.gradle +++ b/build-system/integration-test/test-projects/databinding/build.gradle @@ -19,8 +19,8 @@ apply plugin: 'com.android.application' android { namespace "android.databinding.testapp" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig.minSdkVersion libs.versions.supportLibMinSdk.get() buildFeatures { dataBinding = true diff --git a/build-system/integration-test/test-projects/databinding/build.library-withoutadapters.gradle b/build-system/integration-test/test-projects/databinding/build.library-withoutadapters.gradle index 90e455ec34..5cfb764294 100644 --- a/build-system/integration-test/test-projects/databinding/build.library-withoutadapters.gradle +++ b/build-system/integration-test/test-projects/databinding/build.library-withoutadapters.gradle @@ -19,8 +19,8 @@ apply plugin: 'com.android.library' android { namespace "android.databinding.testapp" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig.minSdkVersion libs.versions.supportLibMinSdk.get() buildFeatures { dataBinding = true diff --git a/build-system/integration-test/test-projects/databinding/build.library.gradle b/build-system/integration-test/test-projects/databinding/build.library.gradle index d6223e0316..fe10660d68 100644 --- a/build-system/integration-test/test-projects/databinding/build.library.gradle +++ b/build-system/integration-test/test-projects/databinding/build.library.gradle @@ -19,8 +19,8 @@ apply plugin: 'com.android.library' android { namespace "android.databinding.testapp" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig.minSdkVersion libs.versions.supportLibMinSdk.get() buildFeatures { dataBinding = true diff --git a/build-system/integration-test/test-projects/databinding/build.withoutadapters.gradle b/build-system/integration-test/test-projects/databinding/build.withoutadapters.gradle index 763df2b0bf..6f3ab966c0 100644 --- a/build-system/integration-test/test-projects/databinding/build.withoutadapters.gradle +++ b/build-system/integration-test/test-projects/databinding/build.withoutadapters.gradle @@ -19,8 +19,8 @@ apply plugin: 'com.android.application' android { namespace "android.databinding.testapp" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion libs.versions.buildToolsVersion.get() defaultConfig.minSdkVersion libs.versions.supportLibMinSdk.get() buildFeatures { dataBinding = true diff --git a/build-system/integration-test/test-projects/databindingAndDagger/build.gradle b/build-system/integration-test/test-projects/databindingAndDagger/build.gradle index 2eb870aa7b..89d10c5424 100644 --- a/build-system/integration-test/test-projects/databindingAndDagger/build.gradle +++ b/build-system/integration-test/test-projects/databindingAndDagger/build.gradle @@ -24,8 +24,8 @@ apply plugin: 'com.android.application' android { namespace "android.databinding.testapp" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() buildFeatures { dataBinding = true } diff --git a/build-system/integration-test/test-projects/databindingAndDagger/build.specifyprocessor.gradle b/build-system/integration-test/test-projects/databindingAndDagger/build.specifyprocessor.gradle index 1fe2e885ee..66d0f100d9 100644 --- a/build-system/integration-test/test-projects/databindingAndDagger/build.specifyprocessor.gradle +++ b/build-system/integration-test/test-projects/databindingAndDagger/build.specifyprocessor.gradle @@ -24,8 +24,8 @@ apply plugin: 'com.android.application' android { namespace "android.databinding.testapp" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() buildFeatures { dataBinding = true } diff --git a/build-system/integration-test/test-projects/databindingAndJetifier/app/build.gradle b/build-system/integration-test/test-projects/databindingAndJetifier/app/build.gradle index a589c264d6..333bda11ef 100644 --- a/build-system/integration-test/test-projects/databindingAndJetifier/app/build.gradle +++ b/build-system/integration-test/test-projects/databindingAndJetifier/app/build.gradle @@ -2,12 +2,12 @@ apply plugin: 'com.android.application' android { namespace "com.example.app" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() defaultConfig { minSdkVersion 23 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } buildFeatures { diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/app/build.gradle b/build-system/integration-test/test-projects/databindingAndKotlin/app/build.gradle index 94fc891f58..982b04ff73 100644 --- a/build-system/integration-test/test-projects/databindingAndKotlin/app/build.gradle +++ b/build-system/integration-test/test-projects/databindingAndKotlin/app/build.gradle @@ -21,13 +21,13 @@ apply plugin: 'kotlin-kapt' android { namespace "com.example.android.kotlin" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } sourceSets { @@ -49,5 +49,5 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KaptGenerateStubs.class).config dependencies { implementation project(':library') - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/build.gradle b/build-system/integration-test/test-projects/databindingAndKotlin/build.gradle index fbd330e45c..327446f181 100644 --- a/build-system/integration-test/test-projects/databindingAndKotlin/build.gradle +++ b/build-system/integration-test/test-projects/databindingAndKotlin/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/databindingAndKotlin/library/build.gradle b/build-system/integration-test/test-projects/databindingAndKotlin/library/build.gradle index 834b936b44..71a998a089 100644 --- a/build-system/integration-test/test-projects/databindingAndKotlin/library/build.gradle +++ b/build-system/integration-test/test-projects/databindingAndKotlin/library/build.gradle @@ -20,13 +20,13 @@ apply plugin: 'kotlin-kapt' android { namespace "com.example.android.kotlin.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } sourceSets { @@ -47,5 +47,5 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KaptGenerateStubs.class).config } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/databindingIncremental/build.forexperimental.gradle b/build-system/integration-test/test-projects/databindingIncremental/build.forexperimental.gradle index 7deb458a92..188cbf619a 100644 --- a/build-system/integration-test/test-projects/databindingIncremental/build.forexperimental.gradle +++ b/build-system/integration-test/test-projects/databindingIncremental/build.forexperimental.gradle @@ -21,8 +21,8 @@ apply plugin: 'com.android.model.application' model { android { namespace "android.databinding.testapp" - compileSdkVersion = rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion = libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() } diff --git a/build-system/integration-test/test-projects/databindingIncremental/build.gradle b/build-system/integration-test/test-projects/databindingIncremental/build.gradle index 47aede29a9..a2e9fe64dd 100644 --- a/build-system/integration-test/test-projects/databindingIncremental/build.gradle +++ b/build-system/integration-test/test-projects/databindingIncremental/build.gradle @@ -19,8 +19,8 @@ apply plugin: 'com.android.application' android { namespace "android.databinding.testapp" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() } diff --git a/build-system/integration-test/test-projects/databindingMultiModule/app/build.gradle b/build-system/integration-test/test-projects/databindingMultiModule/app/build.gradle index a59698e3e3..3837ef1314 100644 --- a/build-system/integration-test/test-projects/databindingMultiModule/app/build.gradle +++ b/build-system/integration-test/test-projects/databindingMultiModule/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "android.databinding.multimodule.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { applicationId "android.databinding.multimodule.app" diff --git a/build-system/integration-test/test-projects/databindingMultiModule/inherited/build.gradle b/build-system/integration-test/test-projects/databindingMultiModule/inherited/build.gradle index e535f88a9f..566d334455 100644 --- a/build-system/integration-test/test-projects/databindingMultiModule/inherited/build.gradle +++ b/build-system/integration-test/test-projects/databindingMultiModule/inherited/build.gradle @@ -18,8 +18,8 @@ apply plugin: 'com.android.library' android { namespace "android.databinding.multimodule.inherited" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 23 versionCode 1 diff --git a/build-system/integration-test/test-projects/databindingMultiModule/library/build.gradle b/build-system/integration-test/test-projects/databindingMultiModule/library/build.gradle index 1af13b97e4..b2f6bc3e06 100644 --- a/build-system/integration-test/test-projects/databindingMultiModule/library/build.gradle +++ b/build-system/integration-test/test-projects/databindingMultiModule/library/build.gradle @@ -18,8 +18,8 @@ apply plugin: 'com.android.library' android { namespace "android.databinding.multimodule.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 23 versionCode 1 diff --git a/build-system/integration-test/test-projects/databindingWithDynamicFeatures/app/build.gradle b/build-system/integration-test/test-projects/databindingWithDynamicFeatures/app/build.gradle index 17b69bff50..b17e751de7 100644 --- a/build-system/integration-test/test-projects/databindingWithDynamicFeatures/app/build.gradle +++ b/build-system/integration-test/test-projects/databindingWithDynamicFeatures/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() dynamicFeatures = [':featureA', ':featureB'] diff --git a/build-system/integration-test/test-projects/databindingWithDynamicFeatures/featureA/build.gradle b/build-system/integration-test/test-projects/databindingWithDynamicFeatures/featureA/build.gradle index f42dd5e4da..e4594ec462 100644 --- a/build-system/integration-test/test-projects/databindingWithDynamicFeatures/featureA/build.gradle +++ b/build-system/integration-test/test-projects/databindingWithDynamicFeatures/featureA/build.gradle @@ -18,8 +18,8 @@ apply plugin: 'com.android.dynamic-feature' android { namespace "com.example.featureA" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 23 versionCode 1 diff --git a/build-system/integration-test/test-projects/databindingWithDynamicFeatures/featureB/build.gradle b/build-system/integration-test/test-projects/databindingWithDynamicFeatures/featureB/build.gradle index c0a8c0a22d..f3c40d8e3d 100644 --- a/build-system/integration-test/test-projects/databindingWithDynamicFeatures/featureB/build.gradle +++ b/build-system/integration-test/test-projects/databindingWithDynamicFeatures/featureB/build.gradle @@ -18,8 +18,8 @@ apply plugin: 'com.android.dynamic-feature' android { namespace "com.example.featureB" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 23 versionCode 1 diff --git a/build-system/integration-test/test-projects/databindingWithDynamicFeatures/libraryModule/build.gradle b/build-system/integration-test/test-projects/databindingWithDynamicFeatures/libraryModule/build.gradle index 87bbe34673..72656c2a5a 100644 --- a/build-system/integration-test/test-projects/databindingWithDynamicFeatures/libraryModule/build.gradle +++ b/build-system/integration-test/test-projects/databindingWithDynamicFeatures/libraryModule/build.gradle @@ -18,8 +18,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.libraryModule" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() buildFeatures { dataBinding = true } diff --git a/build-system/integration-test/test-projects/densitySplit/build.gradle b/build-system/integration-test/test-projects/densitySplit/build.gradle index e7a17acd30..679b124a68 100644 --- a/build-system/integration-test/test-projects/densitySplit/build.gradle +++ b/build-system/integration-test/test-projects/densitySplit/build.gradle @@ -7,8 +7,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/dependencies/build.gradle b/build-system/integration-test/test-projects/dependencies/build.gradle index 01ec4885b0..6d52abd2c2 100644 --- a/build-system/integration-test/test-projects/dependencies/build.gradle +++ b/build-system/integration-test/test-projects/dependencies/build.gradle @@ -16,8 +16,8 @@ dependencies { android { namespace "com.android.tests.dependencies" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/dependenciesWithVariants/build.gradle b/build-system/integration-test/test-projects/dependenciesWithVariants/build.gradle index 1d21dffa3b..035f557635 100644 --- a/build-system/integration-test/test-projects/dependenciesWithVariants/build.gradle +++ b/build-system/integration-test/test-projects/dependenciesWithVariants/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.dependencies" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() flavorDimensions 'foo' defaultConfig { diff --git a/build-system/integration-test/test-projects/dynamicApp/app/build.gradle b/build-system/integration-test/test-projects/dynamicApp/app/build.gradle index 3905ddeeb0..60d2bd9ba6 100644 --- a/build-system/integration-test/test-projects/dynamicApp/app/build.gradle +++ b/build-system/integration-test/test-projects/dynamicApp/app/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { namespace "com.example.app" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() dynamicFeatures = [':feature1', ':feature2'] diff --git a/build-system/integration-test/test-projects/dynamicApp/feature1/build.gradle b/build-system/integration-test/test-projects/dynamicApp/feature1/build.gradle index 4584ebad68..63292e717c 100644 --- a/build-system/integration-test/test-projects/dynamicApp/feature1/build.gradle +++ b/build-system/integration-test/test-projects/dynamicApp/feature1/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.dynamic-feature' android { namespace "com.example.feature1" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() defaultConfig { minSdkVersion 18 diff --git a/build-system/integration-test/test-projects/dynamicApp/feature2/build.gradle b/build-system/integration-test/test-projects/dynamicApp/feature2/build.gradle index 1ba91a706f..1add7e4393 100644 --- a/build-system/integration-test/test-projects/dynamicApp/feature2/build.gradle +++ b/build-system/integration-test/test-projects/dynamicApp/feature2/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.dynamic-feature' android { namespace "com.example.feature2" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() defaultConfig { minSdkVersion 18 diff --git a/build-system/integration-test/test-projects/embedded/main/build.gradle b/build-system/integration-test/test-projects/embedded/main/build.gradle index a483b4dbb4..0d5a09b6f7 100644 --- a/build-system/integration-test/test-projects/embedded/main/build.gradle +++ b/build-system/integration-test/test-projects/embedded/main/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/embedded/micro-apps/custom/build.gradle b/build-system/integration-test/test-projects/embedded/micro-apps/custom/build.gradle index 3fd016a9c2..4f6a73577d 100644 --- a/build-system/integration-test/test-projects/embedded/micro-apps/custom/build.gradle +++ b/build-system/integration-test/test-projects/embedded/micro-apps/custom/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic.custom" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/embedded/micro-apps/default/build.gradle b/build-system/integration-test/test-projects/embedded/micro-apps/default/build.gradle index 30fa6ee617..b2c7556671 100644 --- a/build-system/integration-test/test-projects/embedded/micro-apps/default/build.gradle +++ b/build-system/integration-test/test-projects/embedded/micro-apps/default/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/embedded/micro-apps/flavor1/build.gradle b/build-system/integration-test/test-projects/embedded/micro-apps/flavor1/build.gradle index b195b39881..9b36b51e20 100644 --- a/build-system/integration-test/test-projects/embedded/micro-apps/flavor1/build.gradle +++ b/build-system/integration-test/test-projects/embedded/micro-apps/flavor1/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/emptyApp/build.gradle b/build-system/integration-test/test-projects/emptyApp/build.gradle index bfae7a36ed..0fd1756a10 100644 --- a/build-system/integration-test/test-projects/emptyApp/build.gradle +++ b/build-system/integration-test/test-projects/emptyApp/build.gradle @@ -8,11 +8,12 @@ dependencies { android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { - minSdkVersion rootProject.latestCompileSdk - targetSdkVersion rootProject.latestCompileSdk + minSdkVersion libs.versions.latestCompileSdk.get().toInteger() + targetSdkVersion libs.versions.latestCompileSdk.get() + } } diff --git a/build-system/integration-test/test-projects/emptySplit/build.gradle b/build-system/integration-test/test-projects/emptySplit/build.gradle index b363c6ad12..6eba113847 100644 --- a/build-system/integration-test/test-projects/emptySplit/build.gradle +++ b/build-system/integration-test/test-projects/emptySplit/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() // create splits but remove all split values. splits { diff --git a/build-system/integration-test/test-projects/extractAnnotations/build.gradle b/build-system/integration-test/test-projects/extractAnnotations/build.gradle index ab1422e369..bc835590d0 100644 --- a/build-system/integration-test/test-projects/extractAnnotations/build.gradle +++ b/build-system/integration-test/test-projects/extractAnnotations/build.gradle @@ -11,8 +11,8 @@ dependencies { android { namespace "com.android.tests.extractannotations" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/extractRsEnabledAnnotations/build.gradle b/build-system/integration-test/test-projects/extractRsEnabledAnnotations/build.gradle index c3b3675428..4b823bc7a2 100644 --- a/build-system/integration-test/test-projects/extractRsEnabledAnnotations/build.gradle +++ b/build-system/integration-test/test-projects/extractRsEnabledAnnotations/build.gradle @@ -11,8 +11,8 @@ dependencies { android { namespace "com.android.tests.libstest.lib1" resourcePrefix 'lib1_' - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/failureRetention/app/build.gradle b/build-system/integration-test/test-projects/failureRetention/app/build.gradle index 9d921af28a..7eab8eae3c 100644 --- a/build-system/integration-test/test-projects/failureRetention/app/build.gradle +++ b/build-system/integration-test/test-projects/failureRetention/app/build.gradle @@ -20,13 +20,13 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.kotlin" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunnerArguments clearPackageData: 'true' } @@ -48,7 +48,7 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" androidTestImplementation 'androidx.test.ext:junit:1.1.3-alpha02' androidTestImplementation 'androidx.test:runner:1.4.0-alpha06' androidTestUtil 'androidx.test:orchestrator:1.4.0-alpha06' diff --git a/build-system/integration-test/test-projects/failureRetention/build.gradle b/build-system/integration-test/test-projects/failureRetention/build.gradle index fbd330e45c..327446f181 100644 --- a/build-system/integration-test/test-projects/failureRetention/build.gradle +++ b/build-system/integration-test/test-projects/failureRetention/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/flavored/build.gradle b/build-system/integration-test/test-projects/flavored/build.gradle index 1756eb1b48..db38a641bc 100644 --- a/build-system/integration-test/test-projects/flavored/build.gradle +++ b/build-system/integration-test/test-projects/flavored/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.flavored" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() testBuildType = "staging" diff --git a/build-system/integration-test/test-projects/flavoredlib/app/build.gradle b/build-system/integration-test/test-projects/flavoredlib/app/build.gradle index 1e7cc615d6..4a3c5f7679 100644 --- a/build-system/integration-test/test-projects/flavoredlib/app/build.gradle +++ b/build-system/integration-test/test-projects/flavoredlib/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.flavorlib.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/flavoredlib/lib/build.gradle b/build-system/integration-test/test-projects/flavoredlib/lib/build.gradle index 896ff93c6c..b1cc012160 100644 --- a/build-system/integration-test/test-projects/flavoredlib/lib/build.gradle +++ b/build-system/integration-test/test-projects/flavoredlib/lib/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.flavorlib.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/flavorlib/app/build.gradle b/build-system/integration-test/test-projects/flavorlib/app/build.gradle index 465d39d816..8d8ebfc4d6 100644 --- a/build-system/integration-test/test-projects/flavorlib/app/build.gradle +++ b/build-system/integration-test/test-projects/flavorlib/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.flavorlib.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 diff --git a/build-system/integration-test/test-projects/flavorlib/lib1/build.gradle b/build-system/integration-test/test-projects/flavorlib/lib1/build.gradle index acdd0b78ca..f199fbe1df 100644 --- a/build-system/integration-test/test-projects/flavorlib/lib1/build.gradle +++ b/build-system/integration-test/test-projects/flavorlib/lib1/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.flavorlib.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/flavorlib/lib2/build.gradle b/build-system/integration-test/test-projects/flavorlib/lib2/build.gradle index acdd0b78ca..f199fbe1df 100644 --- a/build-system/integration-test/test-projects/flavorlib/lib2/build.gradle +++ b/build-system/integration-test/test-projects/flavorlib/lib2/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.flavorlib.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/flavorlibWithFailedTests/app/build.gradle b/build-system/integration-test/test-projects/flavorlibWithFailedTests/app/build.gradle index bbaa76795b..3e9a9c9027 100644 --- a/build-system/integration-test/test-projects/flavorlibWithFailedTests/app/build.gradle +++ b/build-system/integration-test/test-projects/flavorlibWithFailedTests/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.flavorlib.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 diff --git a/build-system/integration-test/test-projects/flavorlibWithFailedTests/lib1/build.gradle b/build-system/integration-test/test-projects/flavorlibWithFailedTests/lib1/build.gradle index acdd0b78ca..f199fbe1df 100644 --- a/build-system/integration-test/test-projects/flavorlibWithFailedTests/lib1/build.gradle +++ b/build-system/integration-test/test-projects/flavorlibWithFailedTests/lib1/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.flavorlib.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/flavorlibWithFailedTests/lib2/build.gradle b/build-system/integration-test/test-projects/flavorlibWithFailedTests/lib2/build.gradle index acdd0b78ca..f199fbe1df 100644 --- a/build-system/integration-test/test-projects/flavorlibWithFailedTests/lib2/build.gradle +++ b/build-system/integration-test/test-projects/flavorlibWithFailedTests/lib2/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.flavorlib.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/flavors/build.gradle b/build-system/integration-test/test-projects/flavors/build.gradle index 69cb0e414e..84034a601f 100644 --- a/build-system/integration-test/test-projects/flavors/build.gradle +++ b/build-system/integration-test/test-projects/flavors/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.flavors" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/genFolderApi/build.gradle b/build-system/integration-test/test-projects/genFolderApi/build.gradle index ff21c71d68..430b690ebc 100644 --- a/build-system/integration-test/test-projects/genFolderApi/build.gradle +++ b/build-system/integration-test/test-projects/genFolderApi/build.gradle @@ -9,8 +9,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } public class GenerateCode extends DefaultTask { diff --git a/build-system/integration-test/test-projects/genFolderApi2/build.gradle b/build-system/integration-test/test-projects/genFolderApi2/build.gradle index 265aef7211..9ab7d9144a 100644 --- a/build-system/integration-test/test-projects/genFolderApi2/build.gradle +++ b/build-system/integration-test/test-projects/genFolderApi2/build.gradle @@ -9,8 +9,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } android.applicationVariants.all { variant -> diff --git a/build-system/integration-test/test-projects/instantRunLibraryAdd/app/build.gradle b/build-system/integration-test/test-projects/instantRunLibraryAdd/app/build.gradle index 502c54d6ac..9ad569a5ce 100644 --- a/build-system/integration-test/test-projects/instantRunLibraryAdd/app/build.gradle +++ b/build-system/integration-test/test-projects/instantRunLibraryAdd/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "noapkrebuilt.tests.android.com.b220425" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion libs.versions.buildToolsVersion.get() defaultConfig { applicationId "noapkrebuilt.tests.android.com.b220425" minSdkVersion 19 diff --git a/build-system/integration-test/test-projects/instantRunLibraryAdd/mylibrary/build.gradle b/build-system/integration-test/test-projects/instantRunLibraryAdd/mylibrary/build.gradle index a61c74f957..70790e5fb1 100644 --- a/build-system/integration-test/test-projects/instantRunLibraryAdd/mylibrary/build.gradle +++ b/build-system/integration-test/test-projects/instantRunLibraryAdd/mylibrary/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'com.android.library' android { namespace "noapkrebuilt.tests.android.com.mylibrary" compileSdkVersion 24 - buildToolsVersion rootProject.buildToolsVersion + buildToolsVersion libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 19 diff --git a/build-system/integration-test/test-projects/jarjarIntegration/build.gradle b/build-system/integration-test/test-projects/jarjarIntegration/build.gradle index 8c56d39dfe..e4ebba3b59 100644 --- a/build-system/integration-test/test-projects/jarjarIntegration/build.gradle +++ b/build-system/integration-test/test-projects/jarjarIntegration/build.gradle @@ -10,8 +10,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion 24 // TODO: b/120411432 (was rootProject.latestCompileSdk) - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion 24 // TODO: b/120411432 (was libs.versions.latestCompileSdk.get()) + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/jarjarIntegrationLib/build.gradle b/build-system/integration-test/test-projects/jarjarIntegrationLib/build.gradle index fe0b66d274..4186ac9348 100644 --- a/build-system/integration-test/test-projects/jarjarIntegrationLib/build.gradle +++ b/build-system/integration-test/test-projects/jarjarIntegrationLib/build.gradle @@ -10,8 +10,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/jetifier/app/build.gradle b/build-system/integration-test/test-projects/jetifier/app/build.gradle index 59b31b2d9b..197430e2b7 100644 --- a/build-system/integration-test/test-projects/jetifier/app/build.gradle +++ b/build-system/integration-test/test-projects/jetifier/app/build.gradle @@ -2,11 +2,12 @@ apply plugin: 'com.android.application' android { namespace "com.example.app" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() defaultConfig { minSdkVersion 23 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() + } } diff --git a/build-system/integration-test/test-projects/kotlinApp/app/build.gradle b/build-system/integration-test/test-projects/kotlinApp/app/build.gradle index 2eb94cb414..b64b0e073f 100644 --- a/build-system/integration-test/test-projects/kotlinApp/app/build.gradle +++ b/build-system/integration-test/test-projects/kotlinApp/app/build.gradle @@ -20,13 +20,14 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.kotlin" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -40,7 +41,7 @@ android { dependencies { implementation project(':library') - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" androidTestImplementation 'androidx.test.ext:junit:1.1.3-alpha02' androidTestImplementation 'androidx.test:runner:1.4.0-alpha06' } diff --git a/build-system/integration-test/test-projects/kotlinApp/build.gradle b/build-system/integration-test/test-projects/kotlinApp/build.gradle index fbd330e45c..327446f181 100644 --- a/build-system/integration-test/test-projects/kotlinApp/build.gradle +++ b/build-system/integration-test/test-projects/kotlinApp/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/kotlinApp/library/build.gradle b/build-system/integration-test/test-projects/kotlinApp/library/build.gradle index 05ab3fadba..d652e8c316 100644 --- a/build-system/integration-test/test-projects/kotlinApp/library/build.gradle +++ b/build-system/integration-test/test-projects/kotlinApp/library/build.gradle @@ -19,13 +19,14 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.kotlin.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -38,7 +39,7 @@ android { } dependencies { - api "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + api "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" androidTestImplementation 'androidx.test.ext:junit:1.1.3-alpha02' androidTestImplementation 'androidx.test:runner:1.4.0-alpha06' } diff --git a/build-system/integration-test/test-projects/kotlinApp/libraryNoTests/build.gradle b/build-system/integration-test/test-projects/kotlinApp/libraryNoTests/build.gradle index ab74b6eb50..54bc491486 100644 --- a/build-system/integration-test/test-projects/kotlinApp/libraryNoTests/build.gradle +++ b/build-system/integration-test/test-projects/kotlinApp/libraryNoTests/build.gradle @@ -19,13 +19,14 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.kotlin.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -38,5 +39,5 @@ android { } dependencies { - api "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + api "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/kotlinAppWithKsp/app/build.gradle b/build-system/integration-test/test-projects/kotlinAppWithKsp/app/build.gradle index c2f6f81425..82aba812d6 100644 --- a/build-system/integration-test/test-projects/kotlinAppWithKsp/app/build.gradle +++ b/build-system/integration-test/test-projects/kotlinAppWithKsp/app/build.gradle @@ -21,13 +21,13 @@ apply plugin: 'com.google.devtools.ksp' android { namespace "com.example.android.kotlin" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } kotlinOptions { @@ -36,6 +36,6 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" ksp project(':mock-processor') } diff --git a/build-system/integration-test/test-projects/kotlinAppWithKsp/build.gradle b/build-system/integration-test/test-projects/kotlinAppWithKsp/build.gradle index fbd330e45c..327446f181 100644 --- a/build-system/integration-test/test-projects/kotlinAppWithKsp/build.gradle +++ b/build-system/integration-test/test-projects/kotlinAppWithKsp/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/androidLib/build.gradle.kts b/build-system/integration-test/test-projects/kotlinMultiplatform/androidLib/build.gradle.kts new file mode 100644 index 0000000000..e36c688310 --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/androidLib/build.gradle.kts @@ -0,0 +1,29 @@ +plugins { + id("com.android.library") +} +android { + namespace = "com.example.androidlib" + + compileSdk = property("latestCompileSdk") as Int + + defaultConfig { + minSdk = 21 + targetSdk = property("latestCompileSdk") as Int + } + + flavorDimensions("type", "mode") + productFlavors { + create("typeone") { + dimension = "type" + } + create("typetwo") { + dimension = "type" + } + create("modeone") { + dimension = "mode" + } + create("modetwo") { + dimension = "mode" + } + } +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/androidLib/src/main/AndroidManifest.xml b/build-system/integration-test/test-projects/kotlinMultiplatform/androidLib/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..108251a9b9 --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/androidLib/src/main/AndroidManifest.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.androidlib"> + +</manifest>
\ No newline at end of file diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/androidLib/src/main/java/com/example/androidlib/AndroidLib.java b/build-system/integration-test/test-projects/kotlinMultiplatform/androidLib/src/main/java/com/example/androidlib/AndroidLib.java new file mode 100644 index 0000000000..0aa00f062c --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/androidLib/src/main/java/com/example/androidlib/AndroidLib.java @@ -0,0 +1,8 @@ +package com.example.androidlib; + +public class AndroidLib { + + public String get() { + return "I'm here"; + } +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/androidLib/src/main/resources/android_lib_resource.txt b/build-system/integration-test/test-projects/kotlinMultiplatform/androidLib/src/main/resources/android_lib_resource.txt new file mode 100644 index 0000000000..6c2bcd3278 --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/androidLib/src/main/resources/android_lib_resource.txt @@ -0,0 +1 @@ +android lib resource diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/app/build.gradle.kts b/build-system/integration-test/test-projects/kotlinMultiplatform/app/build.gradle.kts new file mode 100644 index 0000000000..6d02135a37 --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/app/build.gradle.kts @@ -0,0 +1,21 @@ +plugins { + id("com.android.application") +} +android { + namespace = "com.example.app" + + compileSdk = property("latestCompileSdk") as Int + + defaultConfig { + minSdk = 22 + targetSdk = property("latestCompileSdk") as Int + missingDimensionStrategy("type", "typeone") + missingDimensionStrategy("mode", "modetwo") + } +} + +dependencies { + implementation(project(":kmpFirstLib")) + testImplementation("junit:junit:4.13.2") + testImplementation("com.google.truth:truth:0.44") +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/app/src/main/AndroidManifest.xml b/build-system/integration-test/test-projects/kotlinMultiplatform/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..f0d02cb7da --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/app/src/main/AndroidManifest.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.app"> + +</manifest> diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/app/src/main/java/com/example/app/AndroidApp.java b/build-system/integration-test/test-projects/kotlinMultiplatform/app/src/main/java/com/example/app/AndroidApp.java new file mode 100644 index 0000000000..6a7ed16012 --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/app/src/main/java/com/example/app/AndroidApp.java @@ -0,0 +1,16 @@ +package com.example.app; + +import com.example.androidlib.AndroidLib; +import com.example.kmpfirstlib.KmpAndroidFirstLibClass; + +public class AndroidApp { + + public String getFromAndroidLib() { + return new AndroidLib().get(); + } + + public String getFromKmpLib() { + KmpAndroidFirstLibClass kmp = new KmpAndroidFirstLibClass(); + return kmp.callCommonLibClass() + kmp.callKmpSecondLibClass() + kmp.callAndroidLibClass(); + } +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/app/src/test/java/com/example/app/test/AppTest.java b/build-system/integration-test/test-projects/kotlinMultiplatform/app/src/test/java/com/example/app/test/AppTest.java new file mode 100644 index 0000000000..f4be8811c0 --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/app/src/test/java/com/example/app/test/AppTest.java @@ -0,0 +1,14 @@ +package com.example.app.test; + +import com.example.app.AndroidApp; +import com.google.common.truth.Truth; +import org.junit.Test; + +public class AppTest { + + @Test + public void test() { + AndroidApp x = new AndroidApp(); + Truth.assertThat(x.getFromKmpLib()).startsWith(x.getFromAndroidLib()); + } +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/build.gradle b/build-system/integration-test/test-projects/kotlinMultiplatform/build.gradle new file mode 100644 index 0000000000..4cebef0570 --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/build.gradle @@ -0,0 +1,13 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +apply from: "../commonHeader.gradle" + +buildscript { + apply from: "../commonHeader.gradle" // for $kotlinVersion + apply from: "../commonBuildScript.gradle" + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" + classpath "com.android.tools.build:kmp-android-prototype:${libs.versions.buildVersion.get()}" + } +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/gradle.properties b/build-system/integration-test/test-projects/kotlinMultiplatform/gradle.properties new file mode 100644 index 0000000000..f20a5218ef --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/gradle.properties @@ -0,0 +1,19 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/build.gradle.kts b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/build.gradle.kts new file mode 100644 index 0000000000..2cd27c07cf --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/build.gradle.kts @@ -0,0 +1,46 @@ +plugins { + id("org.jetbrains.kotlin.multiplatform") + id("com.android.experimental.kotlin.multiplatform.library") +} + +kotlin { + androidPrototype { + sourceSets.getByName("androidMain") { + dependencies { + api(project(":androidLib")) + implementation(project(":kmpSecondLib")) + } + } + + sourceSets.getByName("androidInstrumentedTest") { + dependencies { + implementation("androidx.test:runner:1.3.0") + implementation("androidx.test:core:1.3.0") + implementation("androidx.test.ext:junit:1.1.2") + } + } + + + options { + namespace = "com.example.kmpfirstlib" + compileSdk = property("latestCompileSdk") as Int + minSdk = 22 + buildTypeMatching.add("debug") + productFlavorsMatching["type"] = mutableListOf("typeone") + productFlavorsMatching["mode"] = mutableListOf("modetwo") + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + aarMetadata.minAgpVersion = "7.2.0" + + enableUnitTest = true + enableAndroidTest = true + } + } + + sourceSets.getByName("commonTest") { + dependencies { + implementation("junit:junit:4.13.2") + } + } +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidInstrumentedTest/AndroidManifest.xml b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidInstrumentedTest/AndroidManifest.xml new file mode 100644 index 0000000000..74b7379f73 --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidInstrumentedTest/AndroidManifest.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android"> +</manifest>
\ No newline at end of file diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidInstrumentedTest/kotlin/com/example/kmpfirstlib/test/KmpAndroidFirstLibActivityTest.kt b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidInstrumentedTest/kotlin/com/example/kmpfirstlib/test/KmpAndroidFirstLibActivityTest.kt new file mode 100644 index 0000000000..4aa8be51a4 --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidInstrumentedTest/kotlin/com/example/kmpfirstlib/test/KmpAndroidFirstLibActivityTest.kt @@ -0,0 +1,40 @@ +package com.example.kmpfirstlib.test + +import androidx.test.core.app.ActivityScenario.launch +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import com.example.kmpfirstlib.KmpAndroidActivity +import com.example.kmpfirstlib.KmpAndroidFirstLibClass + +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class KmpAndroidFirstLibActivityTest { + + @Test + fun testActivityThatPasses() { + val scenario = launch(KmpAndroidActivity::class.java) + scenario.onActivity { activity -> + val x = KmpAndroidFirstLibClass() + Assert.assertTrue(x.callCommonLibClass() == x.callAndroidLibClass()) + Assert.assertTrue(x.callKmpSecondLibClass() == x.callAndroidLibClass()) + } + } + + @Test + fun testJavaResources() { + val kmpResValue = this.javaClass.classLoader.getResourceAsStream("kmp_resource.txt").use { + it!!.bufferedReader().readLine() + } + + Assert.assertTrue(kmpResValue == "kmp resource") + + val androidLibResValue = this.javaClass.classLoader.getResourceAsStream("android_lib_resource.txt").use { + it!!.bufferedReader().readLine() + } + + Assert.assertTrue(androidLibResValue == "android lib resource") + } +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidMain/AndroidManifest.xml b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidMain/AndroidManifest.xml new file mode 100644 index 0000000000..2c48b96b49 --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidMain/AndroidManifest.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android"> + <application> + <activity android:name="KmpAndroidActivity" + android:label="KmpAndroidActivity"> + </activity> + </application> +</manifest> diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidMain/kotlin/com/example/kmpfirstlib/KmpAndroidActivity.kt b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidMain/kotlin/com/example/kmpfirstlib/KmpAndroidActivity.kt new file mode 100644 index 0000000000..9642ad884e --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidMain/kotlin/com/example/kmpfirstlib/KmpAndroidActivity.kt @@ -0,0 +1,12 @@ +package com.example.kmpfirstlib + +import android.app.Activity +import android.os.Bundle + +class KmpAndroidActivity: Activity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + } +} + diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidMain/kotlin/com/example/kmpfirstlib/KmpAndroidFirstLibClass.kt b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidMain/kotlin/com/example/kmpfirstlib/KmpAndroidFirstLibClass.kt new file mode 100644 index 0000000000..18315660d9 --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidMain/kotlin/com/example/kmpfirstlib/KmpAndroidFirstLibClass.kt @@ -0,0 +1,19 @@ +package com.example.kmpfirstlib + +import com.example.androidlib.AndroidLib +import com.example.kmpsecondlib.KmpAndroidSecondLibClass + +class KmpAndroidFirstLibClass { + + fun callCommonLibClass(): String { + return KmpCommonFirstLibClass().get() + } + + fun callKmpSecondLibClass(): String { + return KmpAndroidSecondLibClass().callCommonLibClass() + } + + fun callAndroidLibClass(): String { + return AndroidLib().get() + } +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidMain/resources/kmp_resource.txt b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidMain/resources/kmp_resource.txt new file mode 100644 index 0000000000..78ad1157ae --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidMain/resources/kmp_resource.txt @@ -0,0 +1 @@ +kmp resource diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidTest/kotlin/com/example/kmpfirstlib/KmpAndroidFirstLibClassTest.kt b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidTest/kotlin/com/example/kmpfirstlib/KmpAndroidFirstLibClassTest.kt new file mode 100644 index 0000000000..9412c16cc7 --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/androidTest/kotlin/com/example/kmpfirstlib/KmpAndroidFirstLibClassTest.kt @@ -0,0 +1,13 @@ +package com.example.kmpfirstlib + +import org.junit.Test + +class KmpAndroidFirstLibClassTest { + + @Test + fun testThatPasses() { + val x = KmpAndroidFirstLibClass() + assert(x.callCommonLibClass() == x.callAndroidLibClass()) + assert(x.callKmpSecondLibClass() == x.callAndroidLibClass()) + } +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/commonMain/kotlin/com/example/kmpfirstlib/KmpCommonFirstLibClass.kt b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/commonMain/kotlin/com/example/kmpfirstlib/KmpCommonFirstLibClass.kt new file mode 100644 index 0000000000..6fe8041505 --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/commonMain/kotlin/com/example/kmpfirstlib/KmpCommonFirstLibClass.kt @@ -0,0 +1,8 @@ +package com.example.kmpfirstlib + +class KmpCommonFirstLibClass { + + fun get(): String { + return "I'm here" + } +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/commonTest/kotlin/com/example/kmpfirstlib/KmpCommonFirstLibClassTest.kt b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/commonTest/kotlin/com/example/kmpfirstlib/KmpCommonFirstLibClassTest.kt new file mode 100644 index 0000000000..20ae79bbce --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpFirstLib/src/commonTest/kotlin/com/example/kmpfirstlib/KmpCommonFirstLibClassTest.kt @@ -0,0 +1,12 @@ +package com.example.kmpfirstlib + +import org.junit.Test + +class KmpCommonFirstLibClassTest { + + @Test + fun testThatPasses() { + val x = KmpCommonFirstLibClass() + assert(x.get() == "I'm here") + } +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/kmpSecondLib/build.gradle.kts b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpSecondLib/build.gradle.kts new file mode 100644 index 0000000000..47ecd5418d --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpSecondLib/build.gradle.kts @@ -0,0 +1,14 @@ +plugins { + id("org.jetbrains.kotlin.multiplatform") + id("com.android.experimental.kotlin.multiplatform.library") +} + +kotlin { + androidPrototype { + options { + namespace = "com.example.kmpsecondlib" + compileSdk = property("latestCompileSdk") as Int + minSdk = 22 + } + } +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/kmpSecondLib/src/androidMain/kotlin/com/example/kmpsecondlib/KmpAndroidSecondLibClass.kt b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpSecondLib/src/androidMain/kotlin/com/example/kmpsecondlib/KmpAndroidSecondLibClass.kt new file mode 100644 index 0000000000..4f45ad498d --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpSecondLib/src/androidMain/kotlin/com/example/kmpsecondlib/KmpAndroidSecondLibClass.kt @@ -0,0 +1,8 @@ +package com.example.kmpsecondlib + +class KmpAndroidSecondLibClass { + + fun callCommonLibClass(): String { + return KmpCommonSecondLibClass().get() + } +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/kmpSecondLib/src/commonMain/kotlin/com/example/kmpsecondlib/KmpCommonSecondLibClass.kt b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpSecondLib/src/commonMain/kotlin/com/example/kmpsecondlib/KmpCommonSecondLibClass.kt new file mode 100644 index 0000000000..be4268ca57 --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/kmpSecondLib/src/commonMain/kotlin/com/example/kmpsecondlib/KmpCommonSecondLibClass.kt @@ -0,0 +1,8 @@ +package com.example.kmpsecondlib + +class KmpCommonSecondLibClass { + + fun get(): String { + return "I'm here" + } +} diff --git a/build-system/integration-test/test-projects/kotlinMultiplatform/settings.gradle b/build-system/integration-test/test-projects/kotlinMultiplatform/settings.gradle new file mode 100644 index 0000000000..67f0fc3a6d --- /dev/null +++ b/build-system/integration-test/test-projects/kotlinMultiplatform/settings.gradle @@ -0,0 +1,5 @@ +rootProject.name = "Kotlin Multiplatform" +include ':kmpFirstLib' +include ':kmpSecondLib' +include ':androidLib' +include ':app' diff --git a/build-system/integration-test/test-projects/kotlinWithEclipseSourceSet/app/build.gradle b/build-system/integration-test/test-projects/kotlinWithEclipseSourceSet/app/build.gradle index 00b2021d1f..d66cdd962c 100644 --- a/build-system/integration-test/test-projects/kotlinWithEclipseSourceSet/app/build.gradle +++ b/build-system/integration-test/test-projects/kotlinWithEclipseSourceSet/app/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'kotlin-android' android { namespace "com.sample.kotlin_source_leak" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() // Set source sets to match the layout of Eclipse based projects sourceSets{ @@ -20,5 +20,5 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/kotlinWithEclipseSourceSet/build.gradle b/build-system/integration-test/test-projects/kotlinWithEclipseSourceSet/build.gradle index fbd330e45c..327446f181 100644 --- a/build-system/integration-test/test-projects/kotlinWithEclipseSourceSet/build.gradle +++ b/build-system/integration-test/test-projects/kotlinWithEclipseSourceSet/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/libDependency/app/build.gradle b/build-system/integration-test/test-projects/libDependency/app/build.gradle index 32f7724d07..56bd76473f 100644 --- a/build-system/integration-test/test-projects/libDependency/app/build.gradle +++ b/build-system/integration-test/test-projects/libDependency/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.libstest.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/libDependency/lib/build.gradle b/build-system/integration-test/test-projects/libDependency/lib/build.gradle index 4b244aa457..ff2f2ca8b7 100644 --- a/build-system/integration-test/test-projects/libDependency/lib/build.gradle +++ b/build-system/integration-test/test-projects/libDependency/lib/build.gradle @@ -6,8 +6,8 @@ dependencies { android { namespace "com.android.tests.libstest.lib" resourcePrefix 'lib_' - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/libMinify/build.gradle b/build-system/integration-test/test-projects/libMinify/build.gradle index 3b2b71a68f..48334add6f 100644 --- a/build-system/integration-test/test-projects/libMinify/build.gradle +++ b/build-system/integration-test/test-projects/libMinify/build.gradle @@ -6,8 +6,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/libMinifyJarDep/app/build.gradle b/build-system/integration-test/test-projects/libMinifyJarDep/app/build.gradle index b3d104a9ed..966851d29a 100644 --- a/build-system/integration-test/test-projects/libMinifyJarDep/app/build.gradle +++ b/build-system/integration-test/test-projects/libMinifyJarDep/app/build.gradle @@ -6,8 +6,8 @@ dependencies { android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() testBuildType "proguard" diff --git a/build-system/integration-test/test-projects/libMinifyJarDep/lib/build.gradle b/build-system/integration-test/test-projects/libMinifyJarDep/lib/build.gradle index c5b6c03044..1052ccdc5a 100644 --- a/build-system/integration-test/test-projects/libMinifyJarDep/lib/build.gradle +++ b/build-system/integration-test/test-projects/libMinifyJarDep/lib/build.gradle @@ -11,8 +11,8 @@ dependencies { android { namespace "com.android.tests.basic.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/libMinifyLibDep/app/build.gradle b/build-system/integration-test/test-projects/libMinifyLibDep/app/build.gradle index 08faa9cb09..a62dc7d4cd 100644 --- a/build-system/integration-test/test-projects/libMinifyLibDep/app/build.gradle +++ b/build-system/integration-test/test-projects/libMinifyLibDep/app/build.gradle @@ -10,8 +10,8 @@ dependencies { android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() testBuildType "release" diff --git a/build-system/integration-test/test-projects/libMinifyLibDep/lib/build.gradle b/build-system/integration-test/test-projects/libMinifyLibDep/lib/build.gradle index c7eb852f9b..acec25bc10 100644 --- a/build-system/integration-test/test-projects/libMinifyLibDep/lib/build.gradle +++ b/build-system/integration-test/test-projects/libMinifyLibDep/lib/build.gradle @@ -9,8 +9,8 @@ dependencies { android { namespace "com.android.tests.basic.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/libMinifyLibDep/lib2/build.gradle b/build-system/integration-test/test-projects/libMinifyLibDep/lib2/build.gradle index 8cf97c8854..1c5275a668 100644 --- a/build-system/integration-test/test-projects/libMinifyLibDep/lib2/build.gradle +++ b/build-system/integration-test/test-projects/libMinifyLibDep/lib2/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.basic.lib2" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/libProguardConsumerFiles/build.gradle b/build-system/integration-test/test-projects/libProguardConsumerFiles/build.gradle index 70ae378c79..a2940e2cf1 100644 --- a/build-system/integration-test/test-projects/libProguardConsumerFiles/build.gradle +++ b/build-system/integration-test/test-projects/libProguardConsumerFiles/build.gradle @@ -6,8 +6,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/libTestDep/build.gradle b/build-system/integration-test/test-projects/libTestDep/build.gradle index e4916e5351..46a2fec019 100644 --- a/build-system/integration-test/test-projects/libTestDep/build.gradle +++ b/build-system/integration-test/test-projects/libTestDep/build.gradle @@ -14,8 +14,8 @@ dependencies { android { namespace "com.android.tests.libdeps" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/libsTest/app/build.gradle b/build-system/integration-test/test-projects/libsTest/app/build.gradle index e027b046a8..c4eab61c95 100644 --- a/build-system/integration-test/test-projects/libsTest/app/build.gradle +++ b/build-system/integration-test/test-projects/libsTest/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.libstest.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/libsTest/lib1/build.gradle b/build-system/integration-test/test-projects/libsTest/lib1/build.gradle index f2f503b6de..e767b6379b 100644 --- a/build-system/integration-test/test-projects/libsTest/lib1/build.gradle +++ b/build-system/integration-test/test-projects/libsTest/lib1/build.gradle @@ -11,8 +11,8 @@ dependencies { android { namespace "com.android.tests.libstest.lib1" resourcePrefix 'lib1_' - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/libsTest/lib2/build.gradle b/build-system/integration-test/test-projects/libsTest/lib2/build.gradle index 046c361e41..68edf301f8 100644 --- a/build-system/integration-test/test-projects/libsTest/lib2/build.gradle +++ b/build-system/integration-test/test-projects/libsTest/lib2/build.gradle @@ -3,8 +3,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.libstest.lib2" resourcePrefix 'lib2_' - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/libsTest/lib2b/build.gradle b/build-system/integration-test/test-projects/libsTest/lib2b/build.gradle index 65aa83bb55..f2f5114c0c 100644 --- a/build-system/integration-test/test-projects/libsTest/lib2b/build.gradle +++ b/build-system/integration-test/test-projects/libsTest/lib2b/build.gradle @@ -3,8 +3,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.libstest.lib2b" resourcePrefix 'lib2b_' - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/libsTest/libapp/build.gradle b/build-system/integration-test/test-projects/libsTest/libapp/build.gradle index 71f47cd3e0..b914d35dc6 100644 --- a/build-system/integration-test/test-projects/libsTest/libapp/build.gradle +++ b/build-system/integration-test/test-projects/libsTest/libapp/build.gradle @@ -3,8 +3,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.libstest.libapp" resourcePrefix 'libapp_' - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/lintBaseline/app/build.gradle b/build-system/integration-test/test-projects/lintBaseline/app/build.gradle index 07092a178d..0abb37c1e7 100644 --- a/build-system/integration-test/test-projects/lintBaseline/app/build.gradle +++ b/build-system/integration-test/test-projects/lintBaseline/app/build.gradle @@ -18,13 +18,13 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.lint.kotlin" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } sourceSets { @@ -45,5 +45,5 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/lintBaseline/build.gradle b/build-system/integration-test/test-projects/lintBaseline/build.gradle index fbd330e45c..327446f181 100644 --- a/build-system/integration-test/test-projects/lintBaseline/build.gradle +++ b/build-system/integration-test/test-projects/lintBaseline/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/app/build.gradle b/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/app/build.gradle index ff21085b26..a13dd80bb3 100644 --- a/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/app/build.gradle +++ b/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 16 targetSdkVersion 24 diff --git a/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library-local-only/build.gradle b/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library-local-only/build.gradle index 9300b40749..bb9f27b309 100644 --- a/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library-local-only/build.gradle +++ b/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library-local-only/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 16 diff --git a/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library-publish-only/build.gradle b/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library-publish-only/build.gradle index bbcbd42380..b0ba5676bb 100644 --- a/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library-publish-only/build.gradle +++ b/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library-publish-only/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 16 diff --git a/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library-remote/build.gradle b/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library-remote/build.gradle index 1abc85d078..315ae2e234 100644 --- a/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library-remote/build.gradle +++ b/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library-remote/build.gradle @@ -3,8 +3,8 @@ apply plugin: 'maven-publish' android { namespace "com.example.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 16 diff --git a/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library/build.gradle b/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library/build.gradle index c7df8e95a1..25b08d5b45 100644 --- a/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library/build.gradle +++ b/build-system/integration-test/test-projects/lintCustomLocalAndPublishRules/library/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 16 diff --git a/build-system/integration-test/test-projects/lintCustomRules/app/build.gradle b/build-system/integration-test/test-projects/lintCustomRules/app/build.gradle index c89fd1b3eb..401ba571d3 100644 --- a/build-system/integration-test/test-projects/lintCustomRules/app/build.gradle +++ b/build-system/integration-test/test-projects/lintCustomRules/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 16 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion diff --git a/build-system/integration-test/test-projects/lintCustomRules/library/build.gradle b/build-system/integration-test/test-projects/lintCustomRules/library/build.gradle index c138152d30..0db70ecbef 100644 --- a/build-system/integration-test/test-projects/lintCustomRules/library/build.gradle +++ b/build-system/integration-test/test-projects/lintCustomRules/library/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 16 diff --git a/build-system/integration-test/test-projects/lintDeps/androidlib/build.gradle b/build-system/integration-test/test-projects/lintDeps/androidlib/build.gradle index 209fae5fa0..0a77b1e80a 100644 --- a/build-system/integration-test/test-projects/lintDeps/androidlib/build.gradle +++ b/build-system/integration-test/test-projects/lintDeps/androidlib/build.gradle @@ -3,8 +3,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.mylibrary" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { diff --git a/build-system/integration-test/test-projects/lintDeps/app/build.gradle b/build-system/integration-test/test-projects/lintDeps/app/build.gradle index e0d7f8421d..b6d6bcd9be 100644 --- a/build-system/integration-test/test-projects/lintDeps/app/build.gradle +++ b/build-system/integration-test/test-projects/lintDeps/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.test.myapplication" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { applicationId "com.example.test.myapplication" minSdkVersion 15 diff --git a/build-system/integration-test/test-projects/lintDesugaring/app/build.gradle b/build-system/integration-test/test-projects/lintDesugaring/app/build.gradle index 882fcef6cf..b40c3487bf 100644 --- a/build-system/integration-test/test-projects/lintDesugaring/app/build.gradle +++ b/build-system/integration-test/test-projects/lintDesugaring/app/build.gradle @@ -20,13 +20,13 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.lint.kotlin" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 24 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } lintOptions { @@ -49,6 +49,6 @@ android { dependencies { implementation project(':library') - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5" } diff --git a/build-system/integration-test/test-projects/lintDesugaring/build.gradle b/build-system/integration-test/test-projects/lintDesugaring/build.gradle index fbd330e45c..327446f181 100644 --- a/build-system/integration-test/test-projects/lintDesugaring/build.gradle +++ b/build-system/integration-test/test-projects/lintDesugaring/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/lintDesugaring/library/build.gradle b/build-system/integration-test/test-projects/lintDesugaring/library/build.gradle index ade9df0680..4e4ea38f4d 100644 --- a/build-system/integration-test/test-projects/lintDesugaring/library/build.gradle +++ b/build-system/integration-test/test-projects/lintDesugaring/library/build.gradle @@ -19,13 +19,13 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.lint.desugaring.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 24 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } lintOptions { @@ -47,6 +47,6 @@ android { dependencies { api 'com.android.support:appcompat-v7:' + libs.versions.supportLibVersion.get() - api "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + api "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5" } diff --git a/build-system/integration-test/test-projects/lintInstantiate/app/build.gradle b/build-system/integration-test/test-projects/lintInstantiate/app/build.gradle index c5da7f351b..3915e390e1 100644 --- a/build-system/integration-test/test-projects/lintInstantiate/app/build.gradle +++ b/build-system/integration-test/test-projects/lintInstantiate/app/build.gradle @@ -20,13 +20,13 @@ apply plugin: 'kotlin-android' android { namespace "com.example.myapplication" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } lintOptions { @@ -48,5 +48,5 @@ android { dependencies { implementation project(':mylibrary') - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/lintInstantiate/build.gradle b/build-system/integration-test/test-projects/lintInstantiate/build.gradle index fbd330e45c..327446f181 100644 --- a/build-system/integration-test/test-projects/lintInstantiate/build.gradle +++ b/build-system/integration-test/test-projects/lintInstantiate/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/lintInstantiate/mylibrary/build.gradle b/build-system/integration-test/test-projects/lintInstantiate/mylibrary/build.gradle index cbc6ed9b09..521f0551ba 100644 --- a/build-system/integration-test/test-projects/lintInstantiate/mylibrary/build.gradle +++ b/build-system/integration-test/test-projects/lintInstantiate/mylibrary/build.gradle @@ -19,13 +19,13 @@ apply plugin: 'kotlin-android' android { namespace "com.example.mylibrary" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } kotlinOptions { @@ -35,5 +35,5 @@ android { dependencies { api 'com.android.support:appcompat-v7:' + libs.versions.supportLibVersion.get() - api "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + api "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/lintKotlin/app/build.gradle b/build-system/integration-test/test-projects/lintKotlin/app/build.gradle index 7f9181ed8d..2f3deffd4d 100644 --- a/build-system/integration-test/test-projects/lintKotlin/app/build.gradle +++ b/build-system/integration-test/test-projects/lintKotlin/app/build.gradle @@ -20,13 +20,14 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.lint.kotlin" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() + } lintOptions { @@ -46,5 +47,5 @@ android { dependencies { implementation project(':library') - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/lintKotlin/build.gradle b/build-system/integration-test/test-projects/lintKotlin/build.gradle index fbd330e45c..327446f181 100644 --- a/build-system/integration-test/test-projects/lintKotlin/build.gradle +++ b/build-system/integration-test/test-projects/lintKotlin/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/lintKotlin/library/build.gradle b/build-system/integration-test/test-projects/lintKotlin/library/build.gradle index fc7984d38e..2f492fd971 100644 --- a/build-system/integration-test/test-projects/lintKotlin/library/build.gradle +++ b/build-system/integration-test/test-projects/lintKotlin/library/build.gradle @@ -19,13 +19,14 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.lint.kotlin.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() + } kotlinOptions { @@ -35,5 +36,5 @@ android { dependencies { api 'com.android.support:appcompat-v7:' + libs.versions.supportLibVersion.get() - api "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + api "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/lintLibraryModel/app/build.gradle b/build-system/integration-test/test-projects/lintLibraryModel/app/build.gradle index 1177958774..665e38663a 100644 --- a/build-system/integration-test/test-projects/lintLibraryModel/app/build.gradle +++ b/build-system/integration-test/test-projects/lintLibraryModel/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.test.lint.libmodel.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { applicationId "com.android.test.lint.libmodel.app" minSdkVersion 15 diff --git a/build-system/integration-test/test-projects/lintLibraryModel/mylibrary/build.gradle b/build-system/integration-test/test-projects/lintLibraryModel/mylibrary/build.gradle index 903d4ff3d3..a2f307e0ee 100644 --- a/build-system/integration-test/test-projects/lintLibraryModel/mylibrary/build.gradle +++ b/build-system/integration-test/test-projects/lintLibraryModel/mylibrary/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.test.lint.libmodel.mylibrary" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 diff --git a/build-system/integration-test/test-projects/lintLibraryModel/transitiveLibrary/build.gradle b/build-system/integration-test/test-projects/lintLibraryModel/transitiveLibrary/build.gradle index fb3f7af209..5ed76ba8de 100644 --- a/build-system/integration-test/test-projects/lintLibraryModel/transitiveLibrary/build.gradle +++ b/build-system/integration-test/test-projects/lintLibraryModel/transitiveLibrary/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.test.lint.libmodel.transitiveLibrary" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 diff --git a/build-system/integration-test/test-projects/lintLibrarySkipDeps/app/build.gradle b/build-system/integration-test/test-projects/lintLibrarySkipDeps/app/build.gradle index e7a9d95b16..77cfe16379 100644 --- a/build-system/integration-test/test-projects/lintLibrarySkipDeps/app/build.gradle +++ b/build-system/integration-test/test-projects/lintLibrarySkipDeps/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.test.lint.libmodel.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { applicationId "com.android.test.lint.libmodel.app" minSdkVersion 15 diff --git a/build-system/integration-test/test-projects/lintLibrarySkipDeps/mylibrary/build.gradle b/build-system/integration-test/test-projects/lintLibrarySkipDeps/mylibrary/build.gradle index 86241a4aa1..575800b89b 100644 --- a/build-system/integration-test/test-projects/lintLibrarySkipDeps/mylibrary/build.gradle +++ b/build-system/integration-test/test-projects/lintLibrarySkipDeps/mylibrary/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.test.lint.libmodel.mylibrary" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 diff --git a/build-system/integration-test/test-projects/lintMultipleLintJars/app/build.gradle b/build-system/integration-test/test-projects/lintMultipleLintJars/app/build.gradle index 7d2b491425..b307d839c2 100644 --- a/build-system/integration-test/test-projects/lintMultipleLintJars/app/build.gradle +++ b/build-system/integration-test/test-projects/lintMultipleLintJars/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 16 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion diff --git a/build-system/integration-test/test-projects/lintMultipleLintJars/build.gradle b/build-system/integration-test/test-projects/lintMultipleLintJars/build.gradle index fbd330e45c..327446f181 100644 --- a/build-system/integration-test/test-projects/lintMultipleLintJars/build.gradle +++ b/build-system/integration-test/test-projects/lintMultipleLintJars/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/lintNoJavaClasses/app/build.gradle b/build-system/integration-test/test-projects/lintNoJavaClasses/app/build.gradle index b4651101a0..d5e48a04c3 100644 --- a/build-system/integration-test/test-projects/lintNoJavaClasses/app/build.gradle +++ b/build-system/integration-test/test-projects/lintNoJavaClasses/app/build.gradle @@ -20,13 +20,13 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.lint.kotlin" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } lintOptions { @@ -43,5 +43,5 @@ android { dependencies { implementation project(':app:mylibrary') - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/lintNoJavaClasses/app/mylibrary/build.gradle b/build-system/integration-test/test-projects/lintNoJavaClasses/app/mylibrary/build.gradle index 80a9c50664..4552cb2c8d 100644 --- a/build-system/integration-test/test-projects/lintNoJavaClasses/app/mylibrary/build.gradle +++ b/build-system/integration-test/test-projects/lintNoJavaClasses/app/mylibrary/build.gradle @@ -19,8 +19,8 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.lint.kotlin.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() buildFeatures { buildConfig = false @@ -29,7 +29,7 @@ android { defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8 @@ -38,5 +38,5 @@ android { dependencies { api 'com.android.support:appcompat-v7:' + libs.versions.supportLibVersion.get() - api "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + api "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/lintNoJavaClasses/build.gradle b/build-system/integration-test/test-projects/lintNoJavaClasses/build.gradle index fbd330e45c..327446f181 100644 --- a/build-system/integration-test/test-projects/lintNoJavaClasses/build.gradle +++ b/build-system/integration-test/test-projects/lintNoJavaClasses/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/lintRelease/app/build.gradle b/build-system/integration-test/test-projects/lintRelease/app/build.gradle index 4a7ddfb51a..ef422c5e30 100644 --- a/build-system/integration-test/test-projects/lintRelease/app/build.gradle +++ b/build-system/integration-test/test-projects/lintRelease/app/build.gradle @@ -2,14 +2,15 @@ apply plugin: 'com.android.application' android { namespace "com.android.test.lint" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { applicationId "com.android.test.project" minSdkVersion 21 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() + signingConfig signingConfigs.debug } diff --git a/build-system/integration-test/test-projects/lintRelease/appLib_Library02/build.gradle b/build-system/integration-test/test-projects/lintRelease/appLib_Library02/build.gradle index 42a4dbacd5..9ef02fd2e1 100644 --- a/build-system/integration-test/test-projects/lintRelease/appLib_Library02/build.gradle +++ b/build-system/integration-test/test-projects/lintRelease/appLib_Library02/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.test.applib_library02" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdk 21 diff --git a/build-system/integration-test/test-projects/lintRelease/appLib_Library03/build.gradle b/build-system/integration-test/test-projects/lintRelease/appLib_Library03/build.gradle index ed6ff19d07..811043902c 100644 --- a/build-system/integration-test/test-projects/lintRelease/appLib_Library03/build.gradle +++ b/build-system/integration-test/test-projects/lintRelease/appLib_Library03/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.test.applib_library03" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdk 21 diff --git a/build-system/integration-test/test-projects/lintResourceResolve/app/build.gradle b/build-system/integration-test/test-projects/lintResourceResolve/app/build.gradle index 6daa23c6c8..c4c60caecd 100644 --- a/build-system/integration-test/test-projects/lintResourceResolve/app/build.gradle +++ b/build-system/integration-test/test-projects/lintResourceResolve/app/build.gradle @@ -20,13 +20,13 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.lint.resolve" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } sourceSets { @@ -45,6 +45,6 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" implementation "com.android.support:support-annotations:${libs.versions.supportLibVersion.get()}" } diff --git a/build-system/integration-test/test-projects/lintResourceResolve/build.gradle b/build-system/integration-test/test-projects/lintResourceResolve/build.gradle index fbd330e45c..327446f181 100644 --- a/build-system/integration-test/test-projects/lintResourceResolve/build.gradle +++ b/build-system/integration-test/test-projects/lintResourceResolve/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/lintStandaloneCustomRules/app/build.gradle b/build-system/integration-test/test-projects/lintStandaloneCustomRules/app/build.gradle index 9366505b8b..1e79b5d203 100644 --- a/build-system/integration-test/test-projects/lintStandaloneCustomRules/app/build.gradle +++ b/build-system/integration-test/test-projects/lintStandaloneCustomRules/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.test.myapplication" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { applicationId "com.example.test.myapplication" minSdkVersion 19 diff --git a/build-system/integration-test/test-projects/lintSuppress/app/build.gradle b/build-system/integration-test/test-projects/lintSuppress/app/build.gradle index 370dcf39ca..2d5a741967 100644 --- a/build-system/integration-test/test-projects/lintSuppress/app/build.gradle +++ b/build-system/integration-test/test-projects/lintSuppress/app/build.gradle @@ -19,13 +19,13 @@ apply plugin: 'com.android.application' android { namespace "com.example.android.lint.suppress" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } lintOptions { diff --git a/build-system/integration-test/test-projects/localAarTest/app/build.gradle b/build-system/integration-test/test-projects/localAarTest/app/build.gradle index 3ed60b57f9..24e130d898 100644 --- a/build-system/integration-test/test-projects/localAarTest/app/build.gradle +++ b/build-system/integration-test/test-projects/localAarTest/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.libstest.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 } diff --git a/build-system/integration-test/test-projects/localAarTest/lib1/build.gradle b/build-system/integration-test/test-projects/localAarTest/lib1/build.gradle index 0a58304514..973b8b9a62 100644 --- a/build-system/integration-test/test-projects/localAarTest/lib1/build.gradle +++ b/build-system/integration-test/test-projects/localAarTest/lib1/build.gradle @@ -7,8 +7,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.libstest.lib1" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/localJars/app/build.gradle b/build-system/integration-test/test-projects/localJars/app/build.gradle index ab5e97df0b..e038d8787d 100644 --- a/build-system/integration-test/test-projects/localJars/app/build.gradle +++ b/build-system/integration-test/test-projects/localJars/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.android.multiproject" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() packagingOptions { exclude 'META-INF/exclude.txt' diff --git a/build-system/integration-test/test-projects/localJars/baseLibrary/build.gradle b/build-system/integration-test/test-projects/localJars/baseLibrary/build.gradle index db8e660fe8..e37e69d9d5 100644 --- a/build-system/integration-test/test-projects/localJars/baseLibrary/build.gradle +++ b/build-system/integration-test/test-projects/localJars/baseLibrary/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.android.multiproject.library.base" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() packagingOptions { exclude 'META-INF/exclude.txt' diff --git a/build-system/integration-test/test-projects/localJars/library/build.gradle b/build-system/integration-test/test-projects/localJars/library/build.gradle index 099895ac65..c839111f7c 100644 --- a/build-system/integration-test/test-projects/localJars/library/build.gradle +++ b/build-system/integration-test/test-projects/localJars/library/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.android.multiproject.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } dependencies { diff --git a/build-system/integration-test/test-projects/mavenLocal/app/build.gradle b/build-system/integration-test/test-projects/mavenLocal/app/build.gradle index 289612f752..d30d3c8d02 100644 --- a/build-system/integration-test/test-projects/mavenLocal/app/build.gradle +++ b/build-system/integration-test/test-projects/mavenLocal/app/build.gradle @@ -14,6 +14,6 @@ dependencies { android { namespace "com.example.android.multiproject" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } diff --git a/build-system/integration-test/test-projects/mavenLocal/baseLibrary/build.gradle b/build-system/integration-test/test-projects/mavenLocal/baseLibrary/build.gradle index 1473656083..2ac8f92d87 100644 --- a/build-system/integration-test/test-projects/mavenLocal/baseLibrary/build.gradle +++ b/build-system/integration-test/test-projects/mavenLocal/baseLibrary/build.gradle @@ -15,8 +15,8 @@ dependencies { android { namespace "com.example.android.multiproject.library.base" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } group = 'com.example.android.multiproject' diff --git a/build-system/integration-test/test-projects/mavenLocal/library/build.gradle b/build-system/integration-test/test-projects/mavenLocal/library/build.gradle index de647a5ab8..410a621eae 100644 --- a/build-system/integration-test/test-projects/mavenLocal/library/build.gradle +++ b/build-system/integration-test/test-projects/mavenLocal/library/build.gradle @@ -14,8 +14,8 @@ dependencies { android { namespace "com.example.android.multiproject.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } group = 'com.example.android.multiproject' diff --git a/build-system/integration-test/test-projects/maxSdkVersion/build.gradle b/build-system/integration-test/test-projects/maxSdkVersion/build.gradle index af95f04893..db6af8a261 100644 --- a/build-system/integration-test/test-projects/maxSdkVersion/build.gradle +++ b/build-system/integration-test/test-projects/maxSdkVersion/build.gradle @@ -10,8 +10,8 @@ dependencies { android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() testBuildType "debug" diff --git a/build-system/integration-test/test-projects/migrated/build.gradle b/build-system/integration-test/test-projects/migrated/build.gradle index f8f04241b2..4a27b3d183 100644 --- a/build-system/integration-test/test-projects/migrated/build.gradle +++ b/build-system/integration-test/test-projects/migrated/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/minify/build.gradle b/build-system/integration-test/test-projects/minify/build.gradle index a26038e902..e2a893a381 100644 --- a/build-system/integration-test/test-projects/minify/build.gradle +++ b/build-system/integration-test/test-projects/minify/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() testBuildType "minified" diff --git a/build-system/integration-test/test-projects/minifyLib/app/build.gradle b/build-system/integration-test/test-projects/minifyLib/app/build.gradle index 636d35d4c3..029d9e476c 100644 --- a/build-system/integration-test/test-projects/minifyLib/app/build.gradle +++ b/build-system/integration-test/test-projects/minifyLib/app/build.gradle @@ -9,8 +9,8 @@ dependencies { android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/minifyLib/lib/build.gradle b/build-system/integration-test/test-projects/minifyLib/lib/build.gradle index c304219b06..eb64a16ecb 100644 --- a/build-system/integration-test/test-projects/minifyLib/lib/build.gradle +++ b/build-system/integration-test/test-projects/minifyLib/lib/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.basic.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/minifyLibWithJavaRes/app/build.gradle b/build-system/integration-test/test-projects/minifyLibWithJavaRes/app/build.gradle index a6531aa907..731392f38d 100644 --- a/build-system/integration-test/test-projects/minifyLibWithJavaRes/app/build.gradle +++ b/build-system/integration-test/test-projects/minifyLibWithJavaRes/app/build.gradle @@ -10,8 +10,8 @@ dependencies { android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() signingConfigs { myConfig { diff --git a/build-system/integration-test/test-projects/minifyLibWithJavaRes/lib/build.gradle b/build-system/integration-test/test-projects/minifyLibWithJavaRes/lib/build.gradle index d48ed03a9c..8d9bf514d4 100644 --- a/build-system/integration-test/test-projects/minifyLibWithJavaRes/lib/build.gradle +++ b/build-system/integration-test/test-projects/minifyLibWithJavaRes/lib/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.basic.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/mlModelBinding/build.gradle b/build-system/integration-test/test-projects/mlModelBinding/build.gradle index 12643bb04a..12ae2adac1 100644 --- a/build-system/integration-test/test-projects/mlModelBinding/build.gradle +++ b/build-system/integration-test/test-projects/mlModelBinding/build.gradle @@ -5,12 +5,12 @@ apply plugin: 'com.android.application' android { namespace "com.example.app" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() defaultConfig { applicationId "com.example.app" minSdkVersion 26 - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() versionCode 1 versionName "1.0" diff --git a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeApp/app/build.gradle b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeApp/app/build.gradle index f0870d0078..fcd47a47aa 100644 --- a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeApp/app/build.gradle +++ b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeApp/app/build.gradle @@ -23,7 +23,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$rootProject.kotlinVersion" + implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:${libs.versions.kotlinVersion.get()}" implementation "com.android.support:appcompat-v7:${libs.versions.supportLibVersion.get()}" implementation "com.android.support.constraint:constraint-layout:${libs.versions.constraintLayoutVersion.get()}" diff --git a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeApp/build.gradle b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeApp/build.gradle index 908a0cfcec..81861d4beb 100644 --- a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeApp/build.gradle +++ b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeApp/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeApp/composite0/build.gradle b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeApp/composite0/build.gradle index de7ed263de..eb81cde2f6 100644 --- a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeApp/composite0/build.gradle +++ b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeApp/composite0/build.gradle @@ -33,6 +33,6 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "com.android.support:appcompat-v7:${libs.versions.supportLibVersion.get()}" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib1/app/build.gradle b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib1/app/build.gradle index a20d731d92..11d49b6d4e 100644 --- a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib1/app/build.gradle +++ b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib1/app/build.gradle @@ -24,7 +24,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':composite1') - implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$rootProject.kotlinVersion" + implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:${libs.versions.kotlinVersion.get()}" implementation "com.android.support:appcompat-v7:${libs.versions.supportLibVersion.get()}" implementation "com.android.support.constraint:constraint-layout:${libs.versions.constraintLayoutVersion.get()}" implementation 'com.test.composite:composite3:1.0' diff --git a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib1/build.gradle b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib1/build.gradle index 908a0cfcec..81861d4beb 100644 --- a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib1/build.gradle +++ b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib1/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib1/composite1/build.gradle b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib1/composite1/build.gradle index e43c23674e..0c86c86fbc 100644 --- a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib1/composite1/build.gradle +++ b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib1/composite1/build.gradle @@ -33,7 +33,7 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "com.android.support:appcompat-v7:${libs.versions.supportLibVersion.get()}" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${libs.versions.kotlinVersion.get()}" api 'com.test.composite:composite2:1.0' api 'com.test.composite:composite3:1.0' diff --git a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib3/app/build.gradle b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib3/app/build.gradle index 6c5c3afa5e..9527fa6478 100644 --- a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib3/app/build.gradle +++ b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib3/app/build.gradle @@ -24,7 +24,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$rootProject.kotlinVersion" + implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:${libs.versions.kotlinVersion.get()}" implementation "com.android.support:appcompat-v7:${libs.versions.supportLibVersion.get()}" implementation "com.android.support.constraint:constraint-layout:${libs.versions.constraintLayoutVersion.get()}" implementation project(':composite3') diff --git a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib3/build.gradle b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib3/build.gradle index 908a0cfcec..81861d4beb 100644 --- a/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib3/build.gradle +++ b/build-system/integration-test/test-projects/multiCompositeBuild/TestCompositeLib3/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/multiDex/build.gradle b/build-system/integration-test/test-projects/multiDex/build.gradle index e9fd48ca6e..752c5e99da 100644 --- a/build-system/integration-test/test-projects/multiDex/build.gradle +++ b/build-system/integration-test/test-projects/multiDex/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { buildConfigField "String", "FOO", "\"foo\"" diff --git a/build-system/integration-test/test-projects/multiDexWithLib/app/build.gradle b/build-system/integration-test/test-projects/multiDexWithLib/app/build.gradle index 107aeda277..ffb981cc30 100644 --- a/build-system/integration-test/test-projects/multiDexWithLib/app/build.gradle +++ b/build-system/integration-test/test-projects/multiDexWithLib/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/multiDexWithLib/lib/build.gradle b/build-system/integration-test/test-projects/multiDexWithLib/lib/build.gradle index a460578054..bb96c07af0 100644 --- a/build-system/integration-test/test-projects/multiDexWithLib/lib/build.gradle +++ b/build-system/integration-test/test-projects/multiDexWithLib/lib/build.gradle @@ -3,8 +3,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.basic.lib" testNamespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/multiproject/app/build.gradle b/build-system/integration-test/test-projects/multiproject/app/build.gradle index 5ff6bcd542..47dda216b4 100644 --- a/build-system/integration-test/test-projects/multiproject/app/build.gradle +++ b/build-system/integration-test/test-projects/multiproject/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.android.multiproject" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/multiproject/baseLibrary/build.gradle b/build-system/integration-test/test-projects/multiproject/baseLibrary/build.gradle index 63ff71d0de..ef01e3be68 100644 --- a/build-system/integration-test/test-projects/multiproject/baseLibrary/build.gradle +++ b/build-system/integration-test/test-projects/multiproject/baseLibrary/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.android.multiproject.library.base" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/multiproject/library/build.gradle b/build-system/integration-test/test-projects/multiproject/library/build.gradle index 25f4536fbc..bf7cfbd33b 100644 --- a/build-system/integration-test/test-projects/multiproject/library/build.gradle +++ b/build-system/integration-test/test-projects/multiproject/library/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.android.multiproject.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/multires/build.gradle b/build-system/integration-test/test-projects/multires/build.gradle index ec85ab0a16..83ae4a436b 100644 --- a/build-system/integration-test/test-projects/multires/build.gradle +++ b/build-system/integration-test/test-projects/multires/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/namespacedApp/build.gradle b/build-system/integration-test/test-projects/namespacedApp/build.gradle index 3eaebb42e0..ae690ce0ef 100644 --- a/build-system/integration-test/test-projects/namespacedApp/build.gradle +++ b/build-system/integration-test/test-projects/namespacedApp/build.gradle @@ -5,13 +5,13 @@ apply plugin: 'com.android.application' android { namespace "com.example.namespacedApp" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { applicationId "com.example.namespacedApp" minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() versionCode 1 versionName "1.0" } diff --git a/build-system/integration-test/test-projects/navigation/app/build.gradle b/build-system/integration-test/test-projects/navigation/app/build.gradle index ae6cd49968..62aadf8454 100644 --- a/build-system/integration-test/test-projects/navigation/app/build.gradle +++ b/build-system/integration-test/test-projects/navigation/app/build.gradle @@ -19,13 +19,13 @@ apply plugin: 'kotlin-android' android { namespace "com.android.tests.navigation" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } flavorDimensions "group1" @@ -46,7 +46,7 @@ android { dependencies { implementation project(':library') - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" implementation 'android.arch.navigation:navigation-fragment:1.0.0' implementation 'com.android.support:support-fragment:27.1.1' } diff --git a/build-system/integration-test/test-projects/navigation/build.gradle b/build-system/integration-test/test-projects/navigation/build.gradle index 150bf92525..7a44a879c3 100644 --- a/build-system/integration-test/test-projects/navigation/build.gradle +++ b/build-system/integration-test/test-projects/navigation/build.gradle @@ -21,7 +21,7 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/navigation/library/build.gradle b/build-system/integration-test/test-projects/navigation/library/build.gradle index 67145b37a4..f0d66fe397 100644 --- a/build-system/integration-test/test-projects/navigation/library/build.gradle +++ b/build-system/integration-test/test-projects/navigation/library/build.gradle @@ -19,13 +19,14 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.navigation.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() + } sourceSets { @@ -37,7 +38,7 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" implementation 'android.arch.navigation:navigation-fragment:1.0.0' implementation 'com.android.support:support-fragment:27.1.1' } diff --git a/build-system/integration-test/test-projects/ndkJniLib/app/build.gradle b/build-system/integration-test/test-projects/ndkJniLib/app/build.gradle index 50ca92a78e..fbc61c8b3f 100644 --- a/build-system/integration-test/test-projects/ndkJniLib/app/build.gradle +++ b/build-system/integration-test/test-projects/ndkJniLib/app/build.gradle @@ -17,8 +17,8 @@ ext.versionCodes = ["armeabi-v7a":1, "mips":2, "x86":3, "all":0] android { namespace "com.example.hellojni.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { // This actual the app version code. Giving ourselves 100,000 values [0, 99999] diff --git a/build-system/integration-test/test-projects/ndkJniLib/lib/build.gradle b/build-system/integration-test/test-projects/ndkJniLib/lib/build.gradle index 53c2a79cb1..e7c06b9812 100644 --- a/build-system/integration-test/test-projects/ndkJniLib/lib/build.gradle +++ b/build-system/integration-test/test-projects/ndkJniLib/lib/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.hellojni.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.ndk19SupportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/ndkLibPrebuilts/build.gradle b/build-system/integration-test/test-projects/ndkLibPrebuilts/build.gradle index e5b524679c..f7dcf24629 100644 --- a/build-system/integration-test/test-projects/ndkLibPrebuilts/build.gradle +++ b/build-system/integration-test/test-projects/ndkLibPrebuilts/build.gradle @@ -6,8 +6,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.hellojni.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/ndkPrebuilts/build.gradle b/build-system/integration-test/test-projects/ndkPrebuilts/build.gradle index 5c0f3f51af..fa8b162516 100644 --- a/build-system/integration-test/test-projects/ndkPrebuilts/build.gradle +++ b/build-system/integration-test/test-projects/ndkPrebuilts/build.gradle @@ -7,7 +7,7 @@ android { namespace "com.example.hellojni.app" // Set to a version that does not support 64-bits (b.android.com/237833) compileSdkVersion 19 - buildToolsVersion = rootProject.buildToolsVersion + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() } diff --git a/build-system/integration-test/test-projects/ndkSanAngeles/build.gradle b/build-system/integration-test/test-projects/ndkSanAngeles/build.gradle index a14b4f993f..bbab458446 100644 --- a/build-system/integration-test/test-projects/ndkSanAngeles/build.gradle +++ b/build-system/integration-test/test-projects/ndkSanAngeles/build.gradle @@ -7,8 +7,8 @@ project.ext['android.useDeprecatedNdk'] = true android { namespace "com.example.SanAngeles" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.ndk19SupportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/noPngCrunch/build.gradle b/build-system/integration-test/test-projects/noPngCrunch/build.gradle index cddac22387..24f4927618 100644 --- a/build-system/integration-test/test-projects/noPngCrunch/build.gradle +++ b/build-system/integration-test/test-projects/noPngCrunch/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion libs.versions.buildToolsVersion.get() aaptOptions { cruncherEnabled = false diff --git a/build-system/integration-test/test-projects/noPreDex/build.gradle b/build-system/integration-test/test-projects/noPreDex/build.gradle index e54af2a08f..e137e63556 100644 --- a/build-system/integration-test/test-projects/noPreDex/build.gradle +++ b/build-system/integration-test/test-projects/noPreDex/build.gradle @@ -13,8 +13,8 @@ dependencies { android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/optionalLibInLibWithProguard/app/build.gradle b/build-system/integration-test/test-projects/optionalLibInLibWithProguard/app/build.gradle index 9defb8ee38..d3a343525e 100644 --- a/build-system/integration-test/test-projects/optionalLibInLibWithProguard/app/build.gradle +++ b/build-system/integration-test/test-projects/optionalLibInLibWithProguard/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.android.optionallib.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 23 diff --git a/build-system/integration-test/test-projects/optionalLibInLibWithProguard/mylibrary/build.gradle b/build-system/integration-test/test-projects/optionalLibInLibWithProguard/mylibrary/build.gradle index ec978a8204..024e3baf7e 100644 --- a/build-system/integration-test/test-projects/optionalLibInLibWithProguard/mylibrary/build.gradle +++ b/build-system/integration-test/test-projects/optionalLibInLibWithProguard/mylibrary/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.android.optionallib.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() useLibrary 'org.apache.http.legacy' diff --git a/build-system/integration-test/test-projects/overlay1/build.gradle b/build-system/integration-test/test-projects/overlay1/build.gradle index a46da1d5a1..ec96a105cf 100644 --- a/build-system/integration-test/test-projects/overlay1/build.gradle +++ b/build-system/integration-test/test-projects/overlay1/build.gradle @@ -6,8 +6,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.overlay1" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/overlay2/build.gradle b/build-system/integration-test/test-projects/overlay2/build.gradle index 866f0a4906..ed42807ca7 100644 --- a/build-system/integration-test/test-projects/overlay2/build.gradle +++ b/build-system/integration-test/test-projects/overlay2/build.gradle @@ -6,8 +6,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.overlay2" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/overlay3/build.gradle b/build-system/integration-test/test-projects/overlay3/build.gradle index 840febc0df..38c0a35fb1 100644 --- a/build-system/integration-test/test-projects/overlay3/build.gradle +++ b/build-system/integration-test/test-projects/overlay3/build.gradle @@ -6,8 +6,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.overlay2" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/packagingOptions/build.gradle b/build-system/integration-test/test-projects/packagingOptions/build.gradle index 5125c627b3..d31404f1b3 100644 --- a/build-system/integration-test/test-projects/packagingOptions/build.gradle +++ b/build-system/integration-test/test-projects/packagingOptions/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/pkgOverride/build.gradle b/build-system/integration-test/test-projects/pkgOverride/build.gradle index 69f26a717b..f54155dd1b 100644 --- a/build-system/integration-test/test-projects/pkgOverride/build.gradle +++ b/build-system/integration-test/test-projects/pkgOverride/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { applicationId "com.android.tests.basic.foo" diff --git a/build-system/integration-test/test-projects/placeholderInLibsTest/app/build.gradle b/build-system/integration-test/test-projects/placeholderInLibsTest/app/build.gradle index 0c31b04a70..e70888b43a 100644 --- a/build-system/integration-test/test-projects/placeholderInLibsTest/app/build.gradle +++ b/build-system/integration-test/test-projects/placeholderInLibsTest/app/build.gradle @@ -3,8 +3,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.manifest_merger_example" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { applicationId "com.example.manifest_merger_example" diff --git a/build-system/integration-test/test-projects/placeholderInLibsTest/examplelibrary/build.gradle b/build-system/integration-test/test-projects/placeholderInLibsTest/examplelibrary/build.gradle index 33654dbe89..4c0c2a58fe 100644 --- a/build-system/integration-test/test-projects/placeholderInLibsTest/examplelibrary/build.gradle +++ b/build-system/integration-test/test-projects/placeholderInLibsTest/examplelibrary/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.mylibrary" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 diff --git a/build-system/integration-test/test-projects/prefabApp/app/build.gradle b/build-system/integration-test/test-projects/prefabApp/app/build.gradle index 689547db8b..a4d6099f41 100644 --- a/build-system/integration-test/test-projects/prefabApp/app/build.gradle +++ b/build-system/integration-test/test-projects/prefabApp/app/build.gradle @@ -3,12 +3,13 @@ apply plugin: 'kotlin-android' android { namespace "com.android.prefabaartest" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 16 - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() + } buildFeatures { @@ -21,7 +22,7 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" implementation project(':curl') implementation project(':jsoncpp') implementation project(':openssl') diff --git a/build-system/integration-test/test-projects/prefabApp/build.gradle b/build-system/integration-test/test-projects/prefabApp/build.gradle index 14bb55ac52..a28f44de32 100644 --- a/build-system/integration-test/test-projects/prefabApp/build.gradle +++ b/build-system/integration-test/test-projects/prefabApp/build.gradle @@ -5,7 +5,7 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/prefabNoDeps/app/build.gradle b/build-system/integration-test/test-projects/prefabNoDeps/app/build.gradle index a1d3acdfa9..387b2f3322 100644 --- a/build-system/integration-test/test-projects/prefabNoDeps/app/build.gradle +++ b/build-system/integration-test/test-projects/prefabNoDeps/app/build.gradle @@ -3,12 +3,12 @@ apply plugin: 'kotlin-android' android { namespace "com.android.prefabaartest" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 16 - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } buildFeatures { @@ -21,5 +21,5 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/prefabNoDeps/build.gradle b/build-system/integration-test/test-projects/prefabNoDeps/build.gradle index 14bb55ac52..a28f44de32 100644 --- a/build-system/integration-test/test-projects/prefabNoDeps/build.gradle +++ b/build-system/integration-test/test-projects/prefabNoDeps/build.gradle @@ -5,7 +5,7 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/prefabPublishing/build.gradle b/build-system/integration-test/test-projects/prefabPublishing/build.gradle index 14bb55ac52..a28f44de32 100644 --- a/build-system/integration-test/test-projects/prefabPublishing/build.gradle +++ b/build-system/integration-test/test-projects/prefabPublishing/build.gradle @@ -5,7 +5,7 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/prefabPublishing/foo/build.gradle b/build-system/integration-test/test-projects/prefabPublishing/foo/build.gradle index e324c8991c..ac0cd832a7 100644 --- a/build-system/integration-test/test-projects/prefabPublishing/foo/build.gradle +++ b/build-system/integration-test/test-projects/prefabPublishing/foo/build.gradle @@ -4,12 +4,12 @@ plugins { android { namespace "com.example.foo" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 16 - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() } buildFeatures { diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/build.gradle b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/build.gradle index a5a7957e08..12052dd028 100644 --- a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/build.gradle +++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/build.gradle @@ -6,6 +6,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/privateResources/app/build.gradle b/build-system/integration-test/test-projects/privateResources/app/build.gradle index 445a76406f..19a5076fc1 100644 --- a/build-system/integration-test/test-projects/privateResources/app/build.gradle +++ b/build-system/integration-test/test-projects/privateResources/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tools.test.publicsymbols" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { applicationId "com.android.tools.test.publicsymbols" diff --git a/build-system/integration-test/test-projects/privateResources/mylibrary/build.gradle b/build-system/integration-test/test-projects/privateResources/mylibrary/build.gradle index 3d8cf315f4..c7ff96b447 100644 --- a/build-system/integration-test/test-projects/privateResources/mylibrary/build.gradle +++ b/build-system/integration-test/test-projects/privateResources/mylibrary/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tools.test.mylibrary" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() resourcePrefix 'mylib_' defaultConfig { diff --git a/build-system/integration-test/test-projects/privateResources/mylibrary2/build.gradle b/build-system/integration-test/test-projects/privateResources/mylibrary2/build.gradle index 084cf82d75..3f92b574a4 100644 --- a/build-system/integration-test/test-projects/privateResources/mylibrary2/build.gradle +++ b/build-system/integration-test/test-projects/privateResources/mylibrary2/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tools.test.mylibrary2" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() resourcePrefix 'mylib2_' defaultConfig { diff --git a/build-system/integration-test/test-projects/projectWithClassifierDep/build.gradle b/build-system/integration-test/test-projects/projectWithClassifierDep/build.gradle index 6f32bfaab7..17c1c56ca4 100644 --- a/build-system/integration-test/test-projects/projectWithClassifierDep/build.gradle +++ b/build-system/integration-test/test-projects/projectWithClassifierDep/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.test.ivyapp" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } dependencies { diff --git a/build-system/integration-test/test-projects/projectWithIvyDependency/build.gradle b/build-system/integration-test/test-projects/projectWithIvyDependency/build.gradle index 4fc1ca629c..04d9899de1 100644 --- a/build-system/integration-test/test-projects/projectWithIvyDependency/build.gradle +++ b/build-system/integration-test/test-projects/projectWithIvyDependency/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.test.ivyapp" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } dependencies { diff --git a/build-system/integration-test/test-projects/projectWithModules/app/build.gradle b/build-system/integration-test/test-projects/projectWithModules/app/build.gradle index e79cafc3be..4b516d65e8 100644 --- a/build-system/integration-test/test-projects/projectWithModules/app/build.gradle +++ b/build-system/integration-test/test-projects/projectWithModules/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.android.multiproject" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() as Integer diff --git a/build-system/integration-test/test-projects/projectWithModules/library/build.gradle b/build-system/integration-test/test-projects/projectWithModules/library/build.gradle index eafdc07add..504c05cf10 100644 --- a/build-system/integration-test/test-projects/projectWithModules/library/build.gradle +++ b/build-system/integration-test/test-projects/projectWithModules/library/build.gradle @@ -2,6 +2,6 @@ apply plugin: 'com.android.library' android { namespace "com.example.android.multiproject.library.base" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } diff --git a/build-system/integration-test/test-projects/projectWithModules/library2/build.gradle b/build-system/integration-test/test-projects/projectWithModules/library2/build.gradle index ef8fcf360a..a787aad14c 100644 --- a/build-system/integration-test/test-projects/projectWithModules/library2/build.gradle +++ b/build-system/integration-test/test-projects/projectWithModules/library2/build.gradle @@ -2,6 +2,6 @@ apply plugin: 'com.android.library' android { namespace "com.example.android.multiproject.library2.base" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } diff --git a/build-system/integration-test/test-projects/projectWithModules/library3/build.gradle b/build-system/integration-test/test-projects/projectWithModules/library3/build.gradle index a69d8f1be4..460fd344db 100644 --- a/build-system/integration-test/test-projects/projectWithModules/library3/build.gradle +++ b/build-system/integration-test/test-projects/projectWithModules/library3/build.gradle @@ -2,6 +2,6 @@ apply plugin: 'com.android.library' android { namespace "com.example.android.multiproject.library3.base" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } diff --git a/build-system/integration-test/test-projects/projectWithModules/test/build.gradle b/build-system/integration-test/test-projects/projectWithModules/test/build.gradle index 2d09e3d408..4c9ae9313f 100644 --- a/build-system/integration-test/test-projects/projectWithModules/test/build.gradle +++ b/build-system/integration-test/test-projects/projectWithModules/test/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.test' android { namespace "com.android.tests.basic.test" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 16 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion diff --git a/build-system/integration-test/test-projects/pseudolocalized/build.gradle b/build-system/integration-test/test-projects/pseudolocalized/build.gradle index 1254beb48c..196f56a89f 100644 --- a/build-system/integration-test/test-projects/pseudolocalized/build.gradle +++ b/build-system/integration-test/test-projects/pseudolocalized/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion libs.versions.buildToolsVersion.get() testBuildType "debug" diff --git a/build-system/integration-test/test-projects/renamedApk/build.gradle b/build-system/integration-test/test-projects/renamedApk/build.gradle index c92f23905e..b5d68f726a 100644 --- a/build-system/integration-test/test-projects/renamedApk/build.gradle +++ b/build-system/integration-test/test-projects/renamedApk/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/renderscript/build.gradle b/build-system/integration-test/test-projects/renderscript/build.gradle index 322a3154f6..34e37607ee 100644 --- a/build-system/integration-test/test-projects/renderscript/build.gradle +++ b/build-system/integration-test/test-projects/renderscript/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.android.rs.hellocompute" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 17 diff --git a/build-system/integration-test/test-projects/renderscriptInLib/app/build.gradle b/build-system/integration-test/test-projects/renderscriptInLib/app/build.gradle index 139a02209c..b151adf972 100644 --- a/build-system/integration-test/test-projects/renderscriptInLib/app/build.gradle +++ b/build-system/integration-test/test-projects/renderscriptInLib/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.android.rs.hellocompute" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 17 diff --git a/build-system/integration-test/test-projects/renderscriptInLib/lib/build.gradle b/build-system/integration-test/test-projects/renderscriptInLib/lib/build.gradle index 7c67258c2d..d67d01f626 100644 --- a/build-system/integration-test/test-projects/renderscriptInLib/lib/build.gradle +++ b/build-system/integration-test/test-projects/renderscriptInLib/lib/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.android.rs.hellocompute.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig.minSdkVersion = 17 buildFeatures { diff --git a/build-system/integration-test/test-projects/renderscriptMultiSrc/build.gradle b/build-system/integration-test/test-projects/renderscriptMultiSrc/build.gradle index 322a3154f6..34e37607ee 100644 --- a/build-system/integration-test/test-projects/renderscriptMultiSrc/build.gradle +++ b/build-system/integration-test/test-projects/renderscriptMultiSrc/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.android.rs.hellocompute" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 17 diff --git a/build-system/integration-test/test-projects/renderscriptNdk/build.gradle b/build-system/integration-test/test-projects/renderscriptNdk/build.gradle index bcdd025240..96af1bb50a 100644 --- a/build-system/integration-test/test-projects/renderscriptNdk/build.gradle +++ b/build-system/integration-test/test-projects/renderscriptNdk/build.gradle @@ -32,9 +32,9 @@ dependencies { android { namespace "com.example.android.basicrenderscript" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() - buildToolsVersion rootProject.buildToolsVersion + buildToolsVersion libs.versions.buildToolsVersion.get() defaultConfig { applicationId "com.example.basicrenderscript" diff --git a/build-system/integration-test/test-projects/repo/app/build.gradle b/build-system/integration-test/test-projects/repo/app/build.gradle index 403222f55b..31f1e77c54 100644 --- a/build-system/integration-test/test-projects/repo/app/build.gradle +++ b/build-system/integration-test/test-projects/repo/app/build.gradle @@ -9,7 +9,7 @@ dependencies { android { namespace "com.example.android.multiproject" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() } diff --git a/build-system/integration-test/test-projects/repo/baseLibrary/build.gradle b/build-system/integration-test/test-projects/repo/baseLibrary/build.gradle index 144ce8553d..869c286844 100644 --- a/build-system/integration-test/test-projects/repo/baseLibrary/build.gradle +++ b/build-system/integration-test/test-projects/repo/baseLibrary/build.gradle @@ -16,8 +16,8 @@ dependencies { android { namespace "com.example.android.multiproject.library.base" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() publishing { singleVariant("release") diff --git a/build-system/integration-test/test-projects/repo/library/build.gradle b/build-system/integration-test/test-projects/repo/library/build.gradle index 245b759649..2f90c33e7f 100644 --- a/build-system/integration-test/test-projects/repo/library/build.gradle +++ b/build-system/integration-test/test-projects/repo/library/build.gradle @@ -16,8 +16,8 @@ dependencies { android { namespace "com.example.android.multiproject.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() flavorDimensions 'price' productFlavors { free {} diff --git a/build-system/integration-test/test-projects/rsSupportMode/build.gradle b/build-system/integration-test/test-projects/rsSupportMode/build.gradle index d867d64440..69a1918d1a 100644 --- a/build-system/integration-test/test-projects/rsSupportMode/build.gradle +++ b/build-system/integration-test/test-projects/rsSupportMode/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.rs.image2" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/sameNamedLibs/app/build.gradle b/build-system/integration-test/test-projects/sameNamedLibs/app/build.gradle index b4384e30b1..b7ab48c0ce 100644 --- a/build-system/integration-test/test-projects/sameNamedLibs/app/build.gradle +++ b/build-system/integration-test/test-projects/sameNamedLibs/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.libstest.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/sameNamedLibs/lib1/libs/build.gradle b/build-system/integration-test/test-projects/sameNamedLibs/lib1/libs/build.gradle index 3e212d3825..088a5575de 100644 --- a/build-system/integration-test/test-projects/sameNamedLibs/lib1/libs/build.gradle +++ b/build-system/integration-test/test-projects/sameNamedLibs/lib1/libs/build.gradle @@ -10,8 +10,8 @@ dependencies { android { namespace "com.android.tests.libstest.lib1" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/sameNamedLibs/lib2/libs/build.gradle b/build-system/integration-test/test-projects/sameNamedLibs/lib2/libs/build.gradle index 68085e302a..73910203bf 100644 --- a/build-system/integration-test/test-projects/sameNamedLibs/lib2/libs/build.gradle +++ b/build-system/integration-test/test-projects/sameNamedLibs/lib2/libs/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.libstest.lib2" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/sameNamedLibs/lib2b/libs/build.gradle b/build-system/integration-test/test-projects/sameNamedLibs/lib2b/libs/build.gradle index fba0e930fa..a659f12bce 100644 --- a/build-system/integration-test/test-projects/sameNamedLibs/lib2b/libs/build.gradle +++ b/build-system/integration-test/test-projects/sameNamedLibs/lib2b/libs/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.libstest.lib2b" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/sameNamedLibs/libapp/libs/build.gradle b/build-system/integration-test/test-projects/sameNamedLibs/libapp/libs/build.gradle index 8abea7b8a7..7549721c5e 100644 --- a/build-system/integration-test/test-projects/sameNamedLibs/libapp/libs/build.gradle +++ b/build-system/integration-test/test-projects/sameNamedLibs/libapp/libs/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.libstest.libapp" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/separateTestModule/app/build.gradle b/build-system/integration-test/test-projects/separateTestModule/app/build.gradle index 2120e257c4..9ab4972886 100644 --- a/build-system/integration-test/test-projects/separateTestModule/app/build.gradle +++ b/build-system/integration-test/test-projects/separateTestModule/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() publishNonDefault true diff --git a/build-system/integration-test/test-projects/separateTestModule/test/build.gradle b/build-system/integration-test/test-projects/separateTestModule/test/build.gradle index c7af5be02c..682cb6d603 100644 --- a/build-system/integration-test/test-projects/separateTestModule/test/build.gradle +++ b/build-system/integration-test/test-projects/separateTestModule/test/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.test' android { namespace 'com.example.android.testing.blueprint.test' - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/separateTestModuleWithDependencies/app/build.gradle b/build-system/integration-test/test-projects/separateTestModuleWithDependencies/app/build.gradle index c27dfdb6ec..e1a69ab1e6 100644 --- a/build-system/integration-test/test-projects/separateTestModuleWithDependencies/app/build.gradle +++ b/build-system/integration-test/test-projects/separateTestModuleWithDependencies/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() publishNonDefault true diff --git a/build-system/integration-test/test-projects/separateTestModuleWithDependencies/lib/build.gradle b/build-system/integration-test/test-projects/separateTestModuleWithDependencies/lib/build.gradle index 3b5111889c..91e00835ce 100644 --- a/build-system/integration-test/test-projects/separateTestModuleWithDependencies/lib/build.gradle +++ b/build-system/integration-test/test-projects/separateTestModuleWithDependencies/lib/build.gradle @@ -10,8 +10,8 @@ dependencies { android { namespace "com.android.tests.basic.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/separateTestModuleWithDependencies/test/build.gradle b/build-system/integration-test/test-projects/separateTestModuleWithDependencies/test/build.gradle index abc99ad37b..cbd49874be 100644 --- a/build-system/integration-test/test-projects/separateTestModuleWithDependencies/test/build.gradle +++ b/build-system/integration-test/test-projects/separateTestModuleWithDependencies/test/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.test' android { namespace "com.android.tests.basic.test" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() targetProjectPath ':app' buildTypes { diff --git a/build-system/integration-test/test-projects/separateTestModuleWithMinifiedApp/app/build.gradle b/build-system/integration-test/test-projects/separateTestModuleWithMinifiedApp/app/build.gradle index 3e966572ba..859c3e96ed 100644 --- a/build-system/integration-test/test-projects/separateTestModuleWithMinifiedApp/app/build.gradle +++ b/build-system/integration-test/test-projects/separateTestModuleWithMinifiedApp/app/build.gradle @@ -26,8 +26,8 @@ dependencies { android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/separateTestModuleWithMinifiedApp/test/build.gradle b/build-system/integration-test/test-projects/separateTestModuleWithMinifiedApp/test/build.gradle index 7096c41bff..cfa400f660 100644 --- a/build-system/integration-test/test-projects/separateTestModuleWithMinifiedApp/test/build.gradle +++ b/build-system/integration-test/test-projects/separateTestModuleWithMinifiedApp/test/build.gradle @@ -18,8 +18,8 @@ apply plugin: 'com.android.test' android { namespace "com.android.tests.basic.test" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/separateTestWithMinificationButNoObfuscation/app/build.gradle b/build-system/integration-test/test-projects/separateTestWithMinificationButNoObfuscation/app/build.gradle index c914772440..95c1090f6a 100644 --- a/build-system/integration-test/test-projects/separateTestWithMinificationButNoObfuscation/app/build.gradle +++ b/build-system/integration-test/test-projects/separateTestWithMinificationButNoObfuscation/app/build.gradle @@ -26,8 +26,8 @@ dependencies { android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() publishNonDefault true diff --git a/build-system/integration-test/test-projects/separateTestWithMinificationButNoObfuscation/test/build.gradle b/build-system/integration-test/test-projects/separateTestWithMinificationButNoObfuscation/test/build.gradle index a26e52a748..eebb0a15f2 100644 --- a/build-system/integration-test/test-projects/separateTestWithMinificationButNoObfuscation/test/build.gradle +++ b/build-system/integration-test/test-projects/separateTestWithMinificationButNoObfuscation/test/build.gradle @@ -18,8 +18,8 @@ apply plugin: 'com.android.test' android { namespace "com.android.tests.basic.test" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/shrink/abisplits/build.gradle b/build-system/integration-test/test-projects/shrink/abisplits/build.gradle index c6ddd328c3..db7b5fa803 100644 --- a/build-system/integration-test/test-projects/shrink/abisplits/build.gradle +++ b/build-system/integration-test/test-projects/shrink/abisplits/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.shrink" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/shrink/build.gradle b/build-system/integration-test/test-projects/shrink/build.gradle index 37821d15d7..45e7fc9cfd 100644 --- a/build-system/integration-test/test-projects/shrink/build.gradle +++ b/build-system/integration-test/test-projects/shrink/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.shrink" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/shrink/keep/build.gradle b/build-system/integration-test/test-projects/shrink/keep/build.gradle index dc5d17e259..2d00ad9cc3 100644 --- a/build-system/integration-test/test-projects/shrink/keep/build.gradle +++ b/build-system/integration-test/test-projects/shrink/keep/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.shrink.keep" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/shrink/lib/build.gradle b/build-system/integration-test/test-projects/shrink/lib/build.gradle index 7c83885539..1e95752c49 100644 --- a/build-system/integration-test/test-projects/shrink/lib/build.gradle +++ b/build-system/integration-test/test-projects/shrink/lib/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.shrink.lib" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/shrink/webview/build.gradle b/build-system/integration-test/test-projects/shrink/webview/build.gradle index 7713809712..8a31f360d7 100644 --- a/build-system/integration-test/test-projects/shrink/webview/build.gradle +++ b/build-system/integration-test/test-projects/shrink/webview/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.shrink.webview" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/shrinkDynamicFeatureModules/base/build.gradle b/build-system/integration-test/test-projects/shrinkDynamicFeatureModules/base/build.gradle index 4b60dcfd33..b12182806a 100644 --- a/build-system/integration-test/test-projects/shrinkDynamicFeatureModules/base/build.gradle +++ b/build-system/integration-test/test-projects/shrinkDynamicFeatureModules/base/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.shrink" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion libs.versions.buildToolsVersion.get() defaultConfig { applicationId "com.android.tests.shrink" diff --git a/build-system/integration-test/test-projects/shrinkDynamicFeatureModules/feature/build.gradle b/build-system/integration-test/test-projects/shrinkDynamicFeatureModules/feature/build.gradle index 7843ea40ca..8f60437f52 100644 --- a/build-system/integration-test/test-projects/shrinkDynamicFeatureModules/feature/build.gradle +++ b/build-system/integration-test/test-projects/shrinkDynamicFeatureModules/feature/build.gradle @@ -3,8 +3,8 @@ apply plugin: 'com.android.dynamic-feature' android { namespace "com.android.tests.shrink.feature" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 26 diff --git a/build-system/integration-test/test-projects/simpleCompositeBuild/app/build.gradle b/build-system/integration-test/test-projects/simpleCompositeBuild/app/build.gradle index dfdb4c9e09..af0998f39a 100644 --- a/build-system/integration-test/test-projects/simpleCompositeBuild/app/build.gradle +++ b/build-system/integration-test/test-projects/simpleCompositeBuild/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.libstest.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 15 } diff --git a/build-system/integration-test/test-projects/simpleMicroApp/main/build.gradle b/build-system/integration-test/test-projects/simpleMicroApp/main/build.gradle index 6e8a23c5d0..a0528d386e 100644 --- a/build-system/integration-test/test-projects/simpleMicroApp/main/build.gradle +++ b/build-system/integration-test/test-projects/simpleMicroApp/main/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/simpleMicroApp/wear/build.gradle b/build-system/integration-test/test-projects/simpleMicroApp/wear/build.gradle index 8d4549ed36..f673f85b14 100644 --- a/build-system/integration-test/test-projects/simpleMicroApp/wear/build.gradle +++ b/build-system/integration-test/test-projects/simpleMicroApp/wear/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/sourceDependency/app/build.gradle b/build-system/integration-test/test-projects/sourceDependency/app/build.gradle index 36aa733da9..23fa293b7c 100644 --- a/build-system/integration-test/test-projects/sourceDependency/app/build.gradle +++ b/build-system/integration-test/test-projects/sourceDependency/app/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { namespace "com.example.android.multiproject" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/splitAwareSeparateTestModule/app/build.gradle b/build-system/integration-test/test-projects/splitAwareSeparateTestModule/app/build.gradle index 760f7ce2e9..b15f24562c 100644 --- a/build-system/integration-test/test-projects/splitAwareSeparateTestModule/app/build.gradle +++ b/build-system/integration-test/test-projects/splitAwareSeparateTestModule/app/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() publishNonDefault true generatePureSplits true diff --git a/build-system/integration-test/test-projects/splitAwareSeparateTestModule/test/build.gradle b/build-system/integration-test/test-projects/splitAwareSeparateTestModule/test/build.gradle index a82ab954ca..93ee6fc11f 100644 --- a/build-system/integration-test/test-projects/splitAwareSeparateTestModule/test/build.gradle +++ b/build-system/integration-test/test-projects/splitAwareSeparateTestModule/test/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.test' android { namespace "com.android.tests.basic.test" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/build-system/integration-test/test-projects/testDependency/build.gradle b/build-system/integration-test/test-projects/testDependency/build.gradle index c97feea2f9..bb95ee7d6c 100644 --- a/build-system/integration-test/test-projects/testDependency/build.gradle +++ b/build-system/integration-test/test-projects/testDependency/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/testFixturesApp/app/build.gradle b/build-system/integration-test/test-projects/testFixturesApp/app/build.gradle index cef9a5c56c..fccbdf421e 100644 --- a/build-system/integration-test/test-projects/testFixturesApp/app/build.gradle +++ b/build-system/integration-test/test-projects/testFixturesApp/app/build.gradle @@ -20,8 +20,8 @@ plugins { android { namespace "com.example.app" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/testFixturesApp/appTests/build.gradle b/build-system/integration-test/test-projects/testFixturesApp/appTests/build.gradle index 84db25ad61..456cb2b2fd 100644 --- a/build-system/integration-test/test-projects/testFixturesApp/appTests/build.gradle +++ b/build-system/integration-test/test-projects/testFixturesApp/appTests/build.gradle @@ -4,8 +4,8 @@ plugins { android { namespace = "com.example.apptests" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() targetProjectPath ':app' diff --git a/build-system/integration-test/test-projects/testFixturesApp/lib/build.gradle b/build-system/integration-test/test-projects/testFixturesApp/lib/build.gradle index 88b54952be..632588f0ff 100644 --- a/build-system/integration-test/test-projects/testFixturesApp/lib/build.gradle +++ b/build-system/integration-test/test-projects/testFixturesApp/lib/build.gradle @@ -21,7 +21,7 @@ plugins { android { namespace "com.example.lib" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() testFixtures { enable true androidResources true diff --git a/build-system/integration-test/test-projects/testFixturesApp/lib2/build.gradle b/build-system/integration-test/test-projects/testFixturesApp/lib2/build.gradle index 8dcaee9761..2865c1b6b2 100644 --- a/build-system/integration-test/test-projects/testFixturesApp/lib2/build.gradle +++ b/build-system/integration-test/test-projects/testFixturesApp/lib2/build.gradle @@ -20,7 +20,7 @@ plugins { android { namespace "com.example.lib2" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() } dependencies { diff --git a/build-system/integration-test/test-projects/testWithDep/build.gradle b/build-system/integration-test/test-projects/testWithDep/build.gradle index a535b96789..46a7a2b396 100644 --- a/build-system/integration-test/test-projects/testWithDep/build.gradle +++ b/build-system/integration-test/test-projects/testWithDep/build.gradle @@ -13,8 +13,8 @@ dependencies { android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/tictactoe/app/build.gradle b/build-system/integration-test/test-projects/tictactoe/app/build.gradle index 1b5d7e4044..662d24857b 100644 --- a/build-system/integration-test/test-projects/tictactoe/app/build.gradle +++ b/build-system/integration-test/test-projects/tictactoe/app/build.gradle @@ -6,8 +6,8 @@ dependencies { android { namespace "com.example.android.tictactoe" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() } diff --git a/build-system/integration-test/test-projects/tictactoe/lib/build.gradle b/build-system/integration-test/test-projects/tictactoe/lib/build.gradle index bc3d5c808a..04672e4492 100644 --- a/build-system/integration-test/test-projects/tictactoe/lib/build.gradle +++ b/build-system/integration-test/test-projects/tictactoe/lib/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' android { namespace "com.example.android.tictactoe.library" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/transformApiTest/androidproject/build.gradle b/build-system/integration-test/test-projects/transformApiTest/androidproject/build.gradle index 086a9a5e1d..ab919aeca2 100644 --- a/build-system/integration-test/test-projects/transformApiTest/androidproject/build.gradle +++ b/build-system/integration-test/test-projects/transformApiTest/androidproject/build.gradle @@ -19,8 +19,8 @@ apply plugin: 'com.example.android.build.transform.jarjar' android { namespace "com.android.tests.basic" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { versionCode 12 diff --git a/build-system/integration-test/test-projects/unitTesting/build.gradle b/build-system/integration-test/test-projects/unitTesting/build.gradle index 9e732f8c42..b399ee9ef1 100644 --- a/build-system/integration-test/test-projects/unitTesting/build.gradle +++ b/build-system/integration-test/test-projects/unitTesting/build.gradle @@ -5,7 +5,7 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } @@ -14,8 +14,8 @@ apply plugin: 'kotlin-android' android { namespace "com.android.tests" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() testOptions { unitTests.all { @@ -28,7 +28,7 @@ android { } dependencies { - api "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + api "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:4.8.0' diff --git a/build-system/integration-test/test-projects/unitTestingAndroidResources/build.gradle b/build-system/integration-test/test-projects/unitTestingAndroidResources/build.gradle index 83faa0886c..29c5a85ac8 100644 --- a/build-system/integration-test/test-projects/unitTestingAndroidResources/build.gradle +++ b/build-system/integration-test/test-projects/unitTestingAndroidResources/build.gradle @@ -21,8 +21,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig.minSdkVersion libs.versions.supportLibMinSdk.get() diff --git a/build-system/integration-test/test-projects/unitTestingAndroidResources/lib/build.gradle b/build-system/integration-test/test-projects/unitTestingAndroidResources/lib/build.gradle index 14d10655ed..f764b93679 100644 --- a/build-system/integration-test/test-projects/unitTestingAndroidResources/lib/build.gradle +++ b/build-system/integration-test/test-projects/unitTestingAndroidResources/lib/build.gradle @@ -20,6 +20,6 @@ apply plugin: 'com.android.library' android { namespace "com.android.tests.lib" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() } diff --git a/build-system/integration-test/test-projects/unitTestingBuildTypes/build.gradle b/build-system/integration-test/test-projects/unitTestingBuildTypes/build.gradle index e4d00dc8cd..0a3ef22b20 100644 --- a/build-system/integration-test/test-projects/unitTestingBuildTypes/build.gradle +++ b/build-system/integration-test/test-projects/unitTestingBuildTypes/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() buildTypes { buildTypeWithResource diff --git a/build-system/integration-test/test-projects/unitTestingComplexProject/app/build.gradle b/build-system/integration-test/test-projects/unitTestingComplexProject/app/build.gradle index 33f6dad356..6e844d01a4 100644 --- a/build-system/integration-test/test-projects/unitTestingComplexProject/app/build.gradle +++ b/build-system/integration-test/test-projects/unitTestingComplexProject/app/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'kotlin-android' android { namespace "com.example.app" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() testOptions { unitTests.all { @@ -20,7 +20,7 @@ dependencies { implementation project(":util-lib") implementation project(":javalib") - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${libs.versions.kotlinVersion.get()}" testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:4.8.0' diff --git a/build-system/integration-test/test-projects/unitTestingComplexProject/build.gradle b/build-system/integration-test/test-projects/unitTestingComplexProject/build.gradle index fbd330e45c..327446f181 100644 --- a/build-system/integration-test/test-projects/unitTestingComplexProject/build.gradle +++ b/build-system/integration-test/test-projects/unitTestingComplexProject/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/unitTestingComplexProject/javalib/build.gradle b/build-system/integration-test/test-projects/unitTestingComplexProject/javalib/build.gradle index b9e3145425..0fe05ae9e9 100644 --- a/build-system/integration-test/test-projects/unitTestingComplexProject/javalib/build.gradle +++ b/build-system/integration-test/test-projects/unitTestingComplexProject/javalib/build.gradle @@ -3,7 +3,7 @@ apply plugin: "kotlin" dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${libs.versions.kotlinVersion.get()}" testImplementation "junit:junit:4.12" } diff --git a/build-system/integration-test/test-projects/unitTestingComplexProject/lib/build.gradle b/build-system/integration-test/test-projects/unitTestingComplexProject/lib/build.gradle index a8d9396b6c..e4fe688ac3 100644 --- a/build-system/integration-test/test-projects/unitTestingComplexProject/lib/build.gradle +++ b/build-system/integration-test/test-projects/unitTestingComplexProject/lib/build.gradle @@ -19,7 +19,7 @@ apply plugin: 'kotlin-android' android { namespace "com.example.lib" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() testOptions { unitTests.all { @@ -36,7 +36,7 @@ dependencies { implementation project(":util-lib") implementation project(":javalib") - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${libs.versions.kotlinVersion.get()}" testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:4.8.0' diff --git a/build-system/integration-test/test-projects/unitTestingComplexProject/util-lib/build.gradle b/build-system/integration-test/test-projects/unitTestingComplexProject/util-lib/build.gradle index 0a5afdf186..e5f1d409d2 100644 --- a/build-system/integration-test/test-projects/unitTestingComplexProject/util-lib/build.gradle +++ b/build-system/integration-test/test-projects/unitTestingComplexProject/util-lib/build.gradle @@ -19,7 +19,7 @@ apply plugin: 'kotlin-android' android { namespace "com.example.util_lib" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8 @@ -27,5 +27,5 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${libs.versions.kotlinVersion.get()}" } diff --git a/build-system/integration-test/test-projects/unitTestingDefaultValues/build.gradle b/build-system/integration-test/test-projects/unitTestingDefaultValues/build.gradle index b3c9887036..b24ac74266 100644 --- a/build-system/integration-test/test-projects/unitTestingDefaultValues/build.gradle +++ b/build-system/integration-test/test-projects/unitTestingDefaultValues/build.gradle @@ -21,8 +21,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() testOptions { unitTests.returnDefaultValues = true diff --git a/build-system/integration-test/test-projects/unitTestingFlavors/build.gradle b/build-system/integration-test/test-projects/unitTestingFlavors/build.gradle index e19c219fd5..0804f922c2 100644 --- a/build-system/integration-test/test-projects/unitTestingFlavors/build.gradle +++ b/build-system/integration-test/test-projects/unitTestingFlavors/build.gradle @@ -21,8 +21,8 @@ apply plugin: 'com.android.application' android { namespace "com.android.tests" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() flavorDimensions "buildStatus", "testStatus" diff --git a/build-system/integration-test/test-projects/utp/app/build.gradle b/build-system/integration-test/test-projects/utp/app/build.gradle index eeab3bbd33..e54407cc66 100644 --- a/build-system/integration-test/test-projects/utp/app/build.gradle +++ b/build-system/integration-test/test-projects/utp/app/build.gradle @@ -20,13 +20,14 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.kotlin" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 21 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -39,7 +40,7 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" androidTestImplementation 'androidx.test:core:1.4.0-alpha06' androidTestImplementation 'androidx.test.ext:junit:1.1.3-alpha02' androidTestImplementation 'androidx.test:monitor:1.4.0-alpha06' diff --git a/build-system/integration-test/test-projects/utp/appWithTestFailures/build.gradle b/build-system/integration-test/test-projects/utp/appWithTestFailures/build.gradle index be7166db7d..1a23c39cb2 100644 --- a/build-system/integration-test/test-projects/utp/appWithTestFailures/build.gradle +++ b/build-system/integration-test/test-projects/utp/appWithTestFailures/build.gradle @@ -20,13 +20,14 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.kotlin" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 21 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get() + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -39,7 +40,7 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" androidTestImplementation 'androidx.test.ext:junit:1.1.3-alpha02' androidTestImplementation 'androidx.test:runner:1.4.0-alpha06' } diff --git a/build-system/integration-test/test-projects/utp/build.gradle b/build-system/integration-test/test-projects/utp/build.gradle index fbd330e45c..327446f181 100644 --- a/build-system/integration-test/test-projects/utp/build.gradle +++ b/build-system/integration-test/test-projects/utp/build.gradle @@ -5,6 +5,6 @@ buildscript { apply from: "../commonBuildScript.gradle" dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}" } } diff --git a/build-system/integration-test/test-projects/utp/dynamicfeature1/build.gradle b/build-system/integration-test/test-projects/utp/dynamicfeature1/build.gradle index 6e685d856f..b0e74671a0 100644 --- a/build-system/integration-test/test-projects/utp/dynamicfeature1/build.gradle +++ b/build-system/integration-test/test-projects/utp/dynamicfeature1/build.gradle @@ -20,8 +20,8 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.kotlin" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 21 @@ -38,7 +38,7 @@ android { dependencies { implementation project(":app") - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" androidTestImplementation 'androidx.test:core:1.4.0-alpha06' androidTestImplementation 'androidx.test.ext:junit:1.1.3-alpha02' androidTestImplementation 'androidx.test:monitor:1.4.0-alpha06' diff --git a/build-system/integration-test/test-projects/utp/kotlinDslApp/build.gradle.kts b/build-system/integration-test/test-projects/utp/kotlinDslApp/build.gradle.kts new file mode 100644 index 0000000000..904c5b8498 --- /dev/null +++ b/build-system/integration-test/test-projects/utp/kotlinDslApp/build.gradle.kts @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2023 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. + */ + +plugins { + id("com.android.application") + id("kotlin-android") +} + +android { + namespace = "com.example.android.kotlin" + compileSdk = libs.versions.latestCompileSdk.get().toInt() + buildToolsVersion = libs.versions.buildToolsVersion.get() + + defaultConfig { + minSdk = 21 + //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion + targetSdk = libs.versions.latestCompileSdk.get().toInt() + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } +} + +dependencies { + implementation("org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}") + androidTestImplementation("androidx.test:core:1.4.0-alpha06") + androidTestImplementation("androidx.test.ext:junit:1.1.3-alpha02") + androidTestImplementation("androidx.test:monitor:1.4.0-alpha06") + androidTestImplementation("androidx.test:rules:1.4.0-alpha06") + androidTestImplementation("androidx.test:runner:1.4.0-alpha06") +} diff --git a/build-system/integration-test/test-projects/utp/kotlinDslApp/src/androidTest/kotlin/com/example/android/kotlin/InstrumentedTest.kt b/build-system/integration-test/test-projects/utp/kotlinDslApp/src/androidTest/kotlin/com/example/android/kotlin/InstrumentedTest.kt new file mode 100644 index 0000000000..4f2be30eb8 --- /dev/null +++ b/build-system/integration-test/test-projects/utp/kotlinDslApp/src/androidTest/kotlin/com/example/android/kotlin/InstrumentedTest.kt @@ -0,0 +1,34 @@ +/* + * 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 com.example.android.kotlin + +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import java.util.logging.Logger.getLogger + +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + private val logger = getLogger("TestLogger") + + @Test + fun useAppContext() { + logger.info("test logs") + MainActivity.stubFuncForTestingCodeCoverage() + } +} diff --git a/build-system/integration-test/test-projects/utp/kotlinDslApp/src/main/AndroidManifest.xml b/build-system/integration-test/test-projects/utp/kotlinDslApp/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..c844c4a362 --- /dev/null +++ b/build-system/integration-test/test-projects/utp/kotlinDslApp/src/main/AndroidManifest.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1"> + + <application android:label="Kotlin app test"> + <activity android:name=".MainActivity" android:exported="true" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + +</manifest> diff --git a/build-system/integration-test/test-projects/utp/kotlinDslApp/src/main/kotlin/com/example/android/kotlin/MainActivity.kt b/build-system/integration-test/test-projects/utp/kotlinDslApp/src/main/kotlin/com/example/android/kotlin/MainActivity.kt new file mode 100644 index 0000000000..9b95b70912 --- /dev/null +++ b/build-system/integration-test/test-projects/utp/kotlinDslApp/src/main/kotlin/com/example/android/kotlin/MainActivity.kt @@ -0,0 +1,12 @@ +package com.example.android.kotlin + +import android.app.Activity +import java.util.logging.Logger.getLogger + +class MainActivity : Activity() { + companion object { + fun stubFuncForTestingCodeCoverage() { + getLogger("MainActivity").info("stubFuncForTestingCodeCoverage()") + } + } +} diff --git a/build-system/integration-test/test-projects/utp/kotlinDslApp/src/main/res/layout/activity_layout.xml b/build-system/integration-test/test-projects/utp/kotlinDslApp/src/main/res/layout/activity_layout.xml new file mode 100644 index 0000000000..16a7fa59ea --- /dev/null +++ b/build-system/integration-test/test-projects/utp/kotlinDslApp/src/main/res/layout/activity_layout.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context="com.example.android.kotlin.MainActivity" + tools:showIn="@layout/activity_"> + + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" + android:text="Some Text" + android:id="@+id/someText" + android:layout_alignParentTop="true" + android:layout_centerHorizontal="true" /> + + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Click" + android:id="@+id/click" + android:layout_below="@+id/someText" + android:layout_centerHorizontal="true" /> +</RelativeLayout> diff --git a/build-system/integration-test/test-projects/utp/kotlinDslApp/src/main/res/values/strings.xml b/build-system/integration-test/test-projects/utp/kotlinDslApp/src/main/res/values/strings.xml new file mode 100644 index 0000000000..52d32c41a3 --- /dev/null +++ b/build-system/integration-test/test-projects/utp/kotlinDslApp/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="title_dynamicfeature1">dynamicfeature1</string> +</resources>
\ No newline at end of file diff --git a/build-system/integration-test/test-projects/utp/settings.gradle b/build-system/integration-test/test-projects/utp/settings.gradle index 65dc53887a..05923e3e17 100644 --- a/build-system/integration-test/test-projects/utp/settings.gradle +++ b/build-system/integration-test/test-projects/utp/settings.gradle @@ -1 +1 @@ -include 'app', 'appWithTestFailures', 'testOnlyModule', 'dynamicfeature1' +include 'app', 'appWithTestFailures', 'testOnlyModule', 'dynamicfeature1', 'kotlinDslApp' diff --git a/build-system/integration-test/test-projects/utp/testOnlyModule/build.gradle b/build-system/integration-test/test-projects/utp/testOnlyModule/build.gradle index 76a5301576..bb40f83f7e 100644 --- a/build-system/integration-test/test-projects/utp/testOnlyModule/build.gradle +++ b/build-system/integration-test/test-projects/utp/testOnlyModule/build.gradle @@ -20,13 +20,14 @@ apply plugin: 'kotlin-android' android { namespace "com.example.android.kotlin.test" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 21 //noinspection ExpiringTargetSdkVersion,ExpiredTargetSdkVersion - targetSdkVersion rootProject.latestCompileSdk + targetSdkVersion libs.versions.latestCompileSdk.get().toInteger() + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -42,7 +43,7 @@ android { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${libs.versions.kotlinVersion.get()}" implementation 'androidx.test.ext:junit:1.1.3-alpha02' implementation 'androidx.test:runner:1.4.0-alpha06' } diff --git a/build-system/integration-test/test-projects/vectorDrawables/build.gradle b/build-system/integration-test/test-projects/vectorDrawables/build.gradle index a7008f2810..a92afd0c7d 100644 --- a/build-system/integration-test/test-projects/vectorDrawables/build.gradle +++ b/build-system/integration-test/test-projects/vectorDrawables/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'com.android.application' android { namespace "com.example.test.vectors" - compileSdkVersion rootProject.latestCompileSdk - buildToolsVersion = rootProject.buildToolsVersion + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() + buildToolsVersion = libs.versions.buildToolsVersion.get() defaultConfig { minSdkVersion 19 diff --git a/build-system/integration-test/test-projects/vulkan/build.gradle b/build-system/integration-test/test-projects/vulkan/build.gradle index 3a789aac42..0f7dda90fa 100644 --- a/build-system/integration-test/test-projects/vulkan/build.gradle +++ b/build-system/integration-test/test-projects/vulkan/build.gradle @@ -8,7 +8,7 @@ apply plugin: 'com.android.application' android { namespace "com.google.vulkan.tutorials.five" - compileSdkVersion rootProject.latestCompileSdk + compileSdkVersion libs.versions.latestCompileSdk.get().toInteger() defaultConfig { applicationId "com.google.vulkan.tutorials.five" diff --git a/build-system/kmp-android-prototype/BUILD b/build-system/kmp-android-prototype/BUILD new file mode 100644 index 0000000000..ae031e1b95 --- /dev/null +++ b/build-system/kmp-android-prototype/BUILD @@ -0,0 +1,8 @@ +filegroup( + name = "agp_gradle_build_files", + srcs = glob([ + "src/main/**/*.kt", + "src/main/resources/**", + ]) + ["build.gradle"], + visibility = ["//tools/base/build-system:__pkg__"], +) diff --git a/build-system/kmp-android-prototype/build.gradle b/build-system/kmp-android-prototype/build.gradle index 6e5df9d5e3..0196d251db 100644 --- a/build-system/kmp-android-prototype/build.gradle +++ b/build-system/kmp-android-prototype/build.gradle @@ -1,12 +1,56 @@ plugins { id 'com.android.tools.java-library' id 'com.android.tools.kotlin' + id 'java-gradle-plugin' } dependencies { implementation(project(':base:build-system:gradle-core')) + implementation project(':base:build-system:gradle-settings-api') implementation libs.com.android.tools.analyticsLibrary.shared implementation libs.com.android.tools.common implementation libs.com.android.tools.repository + + compileOnly libs.kotlin_gradle_plugin +} + +kotlin { + sourceSets.configureEach { + languageSettings.optIn("org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi") + } +} + +gradlePlugin { + plugins { + comAndroidExperimentalKotlinMultiplatformLibrary { + id = "com.android.experimental.kotlin.multiplatform.library" + implementationClass = + "com.android.build.gradle.internal.plugins.KotlinMultiplatformAndroidPlugin" + } + } +} + +group = 'com.android.tools.build' +version = rootProject.ext.buildVersion + +apply plugin:'com.android.tools.publish' + +publishing { + publications { + withType(MavenPublication) { + artifactId = 'kmp-android-prototype' + } + } +} + +project.ext.pomName = 'Gradle Plug-in for Android' +project.ext.pomDesc = 'Gradle plug-in to build Android applications.' +project.ext.customArtifactId = 'kmp-android-prototype' + +tasks.register('zipKmpJar', Zip) { + it.from(rootProject.ext.localRepo) + it.destinationDirectory = rootProject.ext.androidHostDist + it.archiveFileName = "kmp_prototype.zip" + it.dependsOn(tasks.getByName("publish")) } diff --git a/build-system/kmp-android-prototype/src/main/kotlin/com/android/build/api/variant/impl/KotlinMultiplatformAndroidCompilationFactory.kt b/build-system/kmp-android-prototype/src/main/kotlin/com/android/build/api/variant/impl/KotlinMultiplatformAndroidCompilationFactory.kt new file mode 100644 index 0000000000..937f19c1fd --- /dev/null +++ b/build-system/kmp-android-prototype/src/main/kotlin/com/android/build/api/variant/impl/KotlinMultiplatformAndroidCompilationFactory.kt @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2023 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.build.api.variant.impl + +import com.android.utils.appendCapitalized +import org.gradle.api.NamedDomainObjectFactory +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinCompilationDescriptor +import org.jetbrains.kotlin.gradle.plugin.mpp.external.createCompilation + +class KotlinMultiplatformAndroidCompilationFactory( + private val target: KotlinMultiplatformAndroidTargetImpl, + private val kotlinExtension: KotlinMultiplatformExtension +): NamedDomainObjectFactory<KotlinMultiplatformAndroidCompilationImpl> { + + override fun create(name: String): KotlinMultiplatformAndroidCompilationImpl { + return target.createCompilation { + compilationName = name + defaultSourceSet = kotlinExtension.sourceSets.getByName( + target.targetName.appendCapitalized(name) + ) + decoratedKotlinCompilationFactory = + ExternalKotlinCompilationDescriptor.DecoratedKotlinCompilationFactory( + ::KotlinMultiplatformAndroidCompilationImpl + ) + compileTaskName = "compile".appendCapitalized( + target.targetName.appendCapitalized(name) + ) + } + } +} diff --git a/build-system/kmp-android-prototype/src/main/kotlin/com/android/build/api/variant/impl/KotlinMultiplatformAndroidCompilationImpl.kt b/build-system/kmp-android-prototype/src/main/kotlin/com/android/build/api/variant/impl/KotlinMultiplatformAndroidCompilationImpl.kt new file mode 100644 index 0000000000..5ecdc84352 --- /dev/null +++ b/build-system/kmp-android-prototype/src/main/kotlin/com/android/build/api/variant/impl/KotlinMultiplatformAndroidCompilationImpl.kt @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2023 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.build.api.variant.impl + +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions +import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions +import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalDecoratedKotlinCompilation + +class KotlinMultiplatformAndroidCompilationImpl( + delegate: Delegate +) : ExternalDecoratedKotlinCompilation(delegate), KotlinMultiplatformAndroidCompilation { + + // This is a workaround for non-removable parametrization for compiler options, it should be + // safe to cast as the type will always be KotlinJvmCompilerOptions + @Suppress("UNCHECKED_CAST") + override val compilerOptions + get() = super.compilerOptions as HasCompilerOptions<KotlinJvmCompilerOptions> +} + +internal enum class KmpPredefinedAndroidCompilation(val compilationName: String) { + MAIN("main"), + TEST("test"), + INSTRUMENTED_TEST("instrumentedTest") +} diff --git a/build-system/kmp-android-prototype/src/main/kotlin/com/android/build/api/variant/impl/KotlinMultiplatformAndroidTargetImpl.kt b/build-system/kmp-android-prototype/src/main/kotlin/com/android/build/api/variant/impl/KotlinMultiplatformAndroidTargetImpl.kt new file mode 100644 index 0000000000..222622943c --- /dev/null +++ b/build-system/kmp-android-prototype/src/main/kotlin/com/android/build/api/variant/impl/KotlinMultiplatformAndroidTargetImpl.kt @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2023 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.build.api.variant.impl + +import com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension +import org.gradle.api.Action +import org.gradle.api.NamedDomainObjectContainer +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.mpp.external.DecoratedExternalKotlinTarget + +class KotlinMultiplatformAndroidTargetImpl( + delegate: Delegate, + kotlinExtension: KotlinMultiplatformExtension, + private val androidExtension: KotlinMultiplatformAndroidExtension +) : DecoratedExternalKotlinTarget(delegate), KotlinMultiplatformAndroidTarget { + + override val options: KotlinMultiplatformAndroidExtension + get() = androidExtension + + override val compilations: NamedDomainObjectContainer<KotlinMultiplatformAndroidCompilationImpl> = + project.objects.domainObjectContainer( + KotlinMultiplatformAndroidCompilationImpl::class.java, + KotlinMultiplatformAndroidCompilationFactory( + this, + kotlinExtension + ) + ) + + private val compilationOperations = mapOf( + KmpPredefinedAndroidCompilation.MAIN to mutableListOf<Action<KotlinMultiplatformAndroidCompilation>>(), + KmpPredefinedAndroidCompilation.TEST to mutableListOf(), + KmpPredefinedAndroidCompilation.INSTRUMENTED_TEST to mutableListOf(), + ) + + private fun onCompilation( + type: KmpPredefinedAndroidCompilation, + action: KotlinMultiplatformAndroidCompilation.() -> Unit + ) { + compilations.findByName(type.compilationName)?.let(action) ?: + compilationOperations[type]!!.add(action) + } + + override fun onMainCompilation(action: KotlinMultiplatformAndroidCompilation.() -> Unit) { + onCompilation(KmpPredefinedAndroidCompilation.MAIN, action) + } + + override fun onUnitTestCompilation(action: KotlinMultiplatformAndroidCompilation.() -> Unit) { + onCompilation(KmpPredefinedAndroidCompilation.TEST, action) + } + + override fun onInstrumentedTestCompilation(action: KotlinMultiplatformAndroidCompilation.() -> Unit) { + onCompilation(KmpPredefinedAndroidCompilation.INSTRUMENTED_TEST, action) + } + + internal fun executeCompilationOperations() { + compilationOperations.forEach { (type, actions) -> + compilations.findByName(type.compilationName)?.let { compilation -> + actions.forEach { + it.execute(compilation) + } + } + } + } + + override fun options(action: KotlinMultiplatformAndroidExtension.() -> Unit) { + androidExtension.action() + } +} diff --git a/build-system/kmp-android-prototype/src/main/kotlin/com/android/build/gradle/internal/plugins/KotlinMultiplatformAndroidPlugin.kt b/build-system/kmp-android-prototype/src/main/kotlin/com/android/build/gradle/internal/plugins/KotlinMultiplatformAndroidPlugin.kt index 19a6dc8ac7..2b14ffb193 100644 --- a/build-system/kmp-android-prototype/src/main/kotlin/com/android/build/gradle/internal/plugins/KotlinMultiplatformAndroidPlugin.kt +++ b/build-system/kmp-android-prototype/src/main/kotlin/com/android/build/gradle/internal/plugins/KotlinMultiplatformAndroidPlugin.kt @@ -21,19 +21,32 @@ import com.android.build.api.attributes.AgpVersionAttr import com.android.build.api.attributes.BuildTypeAttr import com.android.build.api.attributes.ProductFlavorAttr import com.android.build.api.component.analytics.AnalyticsEnabledKotlinMultiplatformAndroidVariant +import com.android.build.api.component.impl.KmpAndroidTestImpl +import com.android.build.api.component.impl.KmpUnitTestImpl +import com.android.build.api.dsl.SettingsExtension +import com.android.build.api.variant.impl.KmpPredefinedAndroidCompilation import com.android.build.api.variant.impl.KmpVariantImpl +import com.android.build.api.variant.impl.KotlinMultiplatformAndroidCompilation +import com.android.build.api.variant.impl.KotlinMultiplatformAndroidCompilationImpl +import com.android.build.api.variant.impl.KotlinMultiplatformAndroidTarget +import com.android.build.api.variant.impl.KotlinMultiplatformAndroidTargetImpl +import com.android.build.gradle.internal.CompileOptions import com.android.build.gradle.internal.DependencyConfigurator import com.android.build.gradle.internal.SdkComponentsBuildService import com.android.build.gradle.internal.TaskManager import com.android.build.gradle.internal.core.dsl.KmpComponentDslInfo +import com.android.build.gradle.internal.core.dsl.impl.KmpAndroidTestDslInfoImpl +import com.android.build.gradle.internal.core.dsl.impl.KmpUnitTestDslInfoImpl import com.android.build.gradle.internal.core.dsl.impl.KmpVariantDslInfoImpl import com.android.build.gradle.internal.dependency.AgpVersionCompatibilityRule +import com.android.build.gradle.internal.dependency.JacocoInstrumentationService import com.android.build.gradle.internal.dependency.SingleVariantBuildTypeRule import com.android.build.gradle.internal.dependency.SingleVariantProductFlavorRule import com.android.build.gradle.internal.dependency.VariantDependencies import com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtension import com.android.build.gradle.internal.dsl.KotlinMultiplatformAndroidExtensionImpl import com.android.build.gradle.internal.dsl.decorator.androidPluginDslDecorator +import com.android.build.gradle.internal.manifest.LazyManifestParser import com.android.build.gradle.internal.scope.KotlinMultiplatformBuildFeaturesValuesImpl import com.android.build.gradle.internal.scope.MutableTaskContainer import com.android.build.gradle.internal.services.Aapt2DaemonBuildService @@ -47,19 +60,30 @@ import com.android.build.gradle.internal.services.VariantServices import com.android.build.gradle.internal.services.VariantServicesImpl import com.android.build.gradle.internal.services.VersionedSdkLoaderService import com.android.build.gradle.internal.tasks.KmpTaskManager +import com.android.build.gradle.internal.tasks.SigningConfigUtils.Companion.createSigningOverride import com.android.build.gradle.internal.tasks.factory.BootClasspathConfigImpl import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfig import com.android.build.gradle.internal.tasks.factory.KmpGlobalTaskCreationConfigImpl import com.android.build.gradle.internal.utils.validatePreviewTargetValue import com.android.build.gradle.internal.variant.VariantPathHelper +import com.android.build.gradle.options.BooleanOption import com.android.builder.core.ComponentTypeImpl import com.android.repository.Revision import com.android.utils.FileUtils +import com.android.utils.appendCapitalized import com.google.wireless.android.sdk.stats.GradleBuildProject import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration +import org.gradle.api.plugins.ExtensionAware import org.gradle.api.provider.Provider import org.gradle.build.event.BuildEventsListenerRegistry +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet.Companion.COMMON_MAIN_SOURCE_SET_NAME +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet.Companion.COMMON_TEST_SOURCE_SET_NAME +import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinTargetDescriptor +import org.jetbrains.kotlin.gradle.plugin.mpp.external.createExternalKotlinTarget import javax.inject.Inject abstract class KotlinMultiplatformAndroidPlugin @Inject constructor( @@ -67,7 +91,10 @@ abstract class KotlinMultiplatformAndroidPlugin @Inject constructor( ): AndroidPluginBaseServices(listenerRegistry), Plugin<Project> { private lateinit var global: GlobalTaskCreationConfig + + private lateinit var kotlinExtension: KotlinMultiplatformExtension private lateinit var androidExtension: KotlinMultiplatformAndroidExtensionImpl + private lateinit var androidTarget: KotlinMultiplatformAndroidTargetImpl private val dslServices by lazy { withProject("dslServices") { project -> @@ -99,6 +126,7 @@ abstract class KotlinMultiplatformAndroidPlugin @Inject constructor( Aapt2ThreadPoolBuildService.RegistrationAction(project, projectServices.projectOptions).execute() Aapt2DaemonBuildService.RegistrationAction(project, projectServices.projectOptions).execute() ClassesHierarchyBuildService.RegistrationAction(project).execute() + JacocoInstrumentationService.RegistrationAction(project).execute() val versionedSdkLoaderService: VersionedSdkLoaderService by lazy { withProject("versionedSdkLoaderService") { project -> @@ -129,7 +157,8 @@ abstract class KotlinMultiplatformAndroidPlugin @Inject constructor( ::getCompileSdkVersion, ::getBuildToolsVersion, BasePlugin.createAndroidJarConfig(project), - dslServices + dslServices, + createSettingsOptions(dslServices) ) TaskManager.createTasksBeforeEvaluate( @@ -157,6 +186,66 @@ abstract class KotlinMultiplatformAndroidPlugin @Inject constructor( extensionImplClass, dslServices ) as KotlinMultiplatformAndroidExtensionImpl + + settingsExtension?.let { + androidExtension.initExtensionFromSettings(it) + } + + project.pluginManager.withPlugin("org.jetbrains.kotlin.multiplatform") { + kotlinExtension = project.extensions.getByName("kotlin") as KotlinMultiplatformExtension + + androidTarget = kotlinExtension.createExternalKotlinTarget { + targetName = "android" + platformType = KotlinPlatformType.jvm + targetFactory = ExternalKotlinTargetDescriptor.TargetFactory { delegate -> + KotlinMultiplatformAndroidTargetImpl( + delegate, kotlinExtension, androidExtension + ) + } + } + + (kotlinExtension as ExtensionAware).extensions.add( + KotlinMultiplatformAndroidTarget::class.java, + "androidPrototype", + androidTarget + ) + + createSourceSetsEagerly() + } + } + + protected open fun KotlinMultiplatformAndroidExtension.initExtensionFromSettings( + settings: SettingsExtension + ) { + settings.compileSdk?.let { compileSdk -> + this.compileSdk = compileSdk + + settings.compileSdkExtension?.let { compileSdkExtension -> + this.compileSdkExtension = compileSdkExtension + } + } + + settings.compileSdkPreview?.let { compileSdkPreview -> + this.compileSdkPreview = compileSdkPreview + } + + settings.minSdk?.let { minSdk -> + this.minSdk = minSdk + } + + settings.minSdkPreview?.let { minSdkPreview -> + this.minSdkPreview = minSdkPreview + } + + settings.buildToolsVersion.let { buildToolsVersion -> + this.buildToolsVersion = buildToolsVersion + } + } + + private fun createSourceSetsEagerly() { + listOf("main", "test", "instrumentedTest").forEach { name -> + kotlinExtension.sourceSets.maybeCreate(androidTarget.targetName.appendCapitalized(name)) + } } private fun getCompileSdkVersion(): String = @@ -188,20 +277,46 @@ abstract class KotlinMultiplatformAndroidPlugin @Inject constructor( val variantServices = VariantServicesImpl(projectServices) val taskServices = TaskCreationServicesImpl(projectServices) - val taskManager = KmpTaskManager() + val taskManager = KmpTaskManager( + project, global + ) val mainVariant = createVariant( project, global, variantServices, - taskServices + taskServices, + androidTarget + ) + + val unitTest = createUnitTestComponent( + project, + global, + variantServices, + taskServices, + androidTarget, + mainVariant + ) + + val androidTest = createAndroidTestComponent( + project, + global, + variantServices, + taskServices, + taskManager, + androidTarget, + mainVariant ) + mainVariant.unitTest = unitTest + mainVariant.androidTest = androidTest + val stats = configuratorService.getVariantBuilder( project.path, mainVariant.name ) + androidTarget.executeCompilationOperations() androidExtension.executeVariantOperations( stats?.let { variantServices.newInstance( @@ -211,35 +326,71 @@ abstract class KotlinMultiplatformAndroidPlugin @Inject constructor( ) } ?: mainVariant ) + listOfNotNull(mainVariant, unitTest, androidTest).forEach { + it.syncAndroidAndKmpClasspathAndSources() + } + + (global.compileOptions as CompileOptions).finalizeSourceAndTargetCompatibility(project) dependencyConfigurator.configureVariantTransforms( variants = listOf(mainVariant), - nestedComponents = listOf(), + nestedComponents = mainVariant.nestedComponents, bootClasspathConfig = global ) + if (androidTest?.isAndroidTestCoverageEnabled == true) { + dependencyConfigurator.configureJacocoTransforms() + } + taskManager.createTasks( project, - createVariant( - project, - global, - variantServices, - taskServices - ) + mainVariant, + unitTest, + androidTest ) } - // TODO: implement - abstract fun createVariantDependencies( - project: Project, + private fun Configuration.forMainVariantConfiguration( dslInfo: KmpComponentDslInfo - ): VariantDependencies + ): Configuration? { + return this.takeIf { + !dslInfo.componentType.isTestComponent + } + } + + private fun createVariantDependencies( + project: Project, + dslInfo: KmpComponentDslInfo, + androidKotlinCompilation: KotlinMultiplatformAndroidCompilationImpl, + androidTarget: KotlinMultiplatformAndroidTargetImpl + ): VariantDependencies = VariantDependencies.createForKotlinMultiplatform( + project = project, + projectOptions = projectServices.projectOptions, + dslInfo = dslInfo, + apiClasspath = androidKotlinCompilation.configurations.apiConfiguration, + compileClasspath = androidKotlinCompilation.configurations.compileDependencyConfiguration, + runtimeClasspath = androidKotlinCompilation.configurations.runtimeDependencyConfiguration!!, + apiElements = androidTarget.apiElementsConfiguration.forMainVariantConfiguration(dslInfo), + runtimeElements = androidTarget.runtimeElementsConfiguration.forMainVariantConfiguration(dslInfo), + apiPublication = androidTarget.apiElementsPublishedConfiguration.forMainVariantConfiguration(dslInfo), + runtimePublication = androidTarget.runtimeElementsPublishedConfiguration.forMainVariantConfiguration(dslInfo), + ) + + private fun getAndroidManifestDefaultLocation( + compilation: KotlinMultiplatformAndroidCompilation + ) = FileUtils.join( + compilation.project.projectDir, + "src", + compilation.defaultSourceSet.name, + "AndroidManifest.xml" + ) private fun createVariant( project: Project, global: GlobalTaskCreationConfig, variantServices: VariantServices, taskCreationServices: TaskCreationServices, + androidTarget: KotlinMultiplatformAndroidTargetImpl ): KmpVariantImpl { val dslInfo = KmpVariantDslInfoImpl( @@ -256,20 +407,138 @@ abstract class KotlinMultiplatformAndroidPlugin @Inject constructor( val artifacts = ArtifactsImpl(project, dslInfo.componentIdentity.name) + val kotlinCompilation = androidTarget.compilations.maybeCreate( + KmpPredefinedAndroidCompilation.MAIN.compilationName + ).also { + it.defaultSourceSet.dependsOn( + kotlinExtension.sourceSets.getByName(COMMON_MAIN_SOURCE_SET_NAME) + ) + } + return KmpVariantImpl( dslInfo = dslInfo, internalServices = variantServices, buildFeatures = KotlinMultiplatformBuildFeaturesValuesImpl(), - variantDependencies = createVariantDependencies(project, dslInfo), + variantDependencies = createVariantDependencies(project, dslInfo, kotlinCompilation, androidTarget), + paths = paths, + artifacts = artifacts, + taskContainer = MutableTaskContainer(), + services = taskCreationServices, + global = global, + androidKotlinCompilation = kotlinCompilation, + manifestFile = getAndroidManifestDefaultLocation(kotlinCompilation) + ) + } + + private fun createUnitTestComponent( + project: Project, + global: GlobalTaskCreationConfig, + variantServices: VariantServices, + taskCreationServices: TaskCreationServices, + androidTarget: KotlinMultiplatformAndroidTargetImpl, + mainVariant: KmpVariantImpl + ): KmpUnitTestImpl? { + if (!mainVariant.dslInfo.enabledUnitTest) { + return null + } + + val dslInfo = KmpUnitTestDslInfoImpl( + androidExtension, + variantServices, + mainVariant.dslInfo, + ) + + val paths = VariantPathHelper( + project.layout.buildDirectory, + dslInfo, + dslServices + ) + + val artifacts = ArtifactsImpl(project, dslInfo.componentIdentity.name) + + val kotlinCompilation = androidTarget.compilations.maybeCreate( + KmpPredefinedAndroidCompilation.TEST.compilationName + ).also { + it.defaultSourceSet.dependsOn( + kotlinExtension.sourceSets.getByName(COMMON_TEST_SOURCE_SET_NAME) + ) + } + + return KmpUnitTestImpl( + dslInfo = dslInfo, + internalServices = variantServices, + buildFeatures = KotlinMultiplatformBuildFeaturesValuesImpl(), + variantDependencies = createVariantDependencies(project, dslInfo, kotlinCompilation, androidTarget), paths = paths, artifacts = artifacts, taskContainer = MutableTaskContainer(), services = taskCreationServices, global = global, - // TODO: Search for the manifest in the kotlin source directories - manifestFile = FileUtils.join( - project.projectDir, "src", "androidMain", "AndroidManifest.xml" + androidKotlinCompilation = kotlinCompilation, + mainVariant = mainVariant, + manifestFile = getAndroidManifestDefaultLocation(kotlinCompilation) + ) + } + + private fun createAndroidTestComponent( + project: Project, + global: GlobalTaskCreationConfig, + variantServices: VariantServices, + taskCreationServices: TaskCreationServices, + taskManager: KmpTaskManager, + androidTarget: KotlinMultiplatformAndroidTargetImpl, + mainVariant: KmpVariantImpl + ): KmpAndroidTestImpl? { + if (!mainVariant.dslInfo.enableAndroidTest) { + return null + } + + val kotlinCompilation = androidTarget.compilations.maybeCreate( + KmpPredefinedAndroidCompilation.INSTRUMENTED_TEST.compilationName + ) + + val manifestLocation = getAndroidManifestDefaultLocation(kotlinCompilation) + + val manifestParser = LazyManifestParser( + manifestFile = projectServices.objectFactory.fileProperty().fileValue(manifestLocation), + manifestFileRequired = true, + projectServices = projectServices + ) { + taskManager.hasCreatedTasks || !projectServices.projectOptions.get( + BooleanOption.DISABLE_EARLY_MANIFEST_PARSING ) + } + + val dslInfo = KmpAndroidTestDslInfoImpl( + androidExtension, + variantServices, + manifestParser, + mainVariant.dslInfo, + createSigningOverride(dslServices), + dslServices + ) + + val paths = VariantPathHelper( + project.layout.buildDirectory, + dslInfo, + dslServices + ) + + val artifacts = ArtifactsImpl(project, dslInfo.componentIdentity.name) + + return KmpAndroidTestImpl( + dslInfo = dslInfo, + internalServices = variantServices, + buildFeatures = KotlinMultiplatformBuildFeaturesValuesImpl(), + variantDependencies = createVariantDependencies(project, dslInfo, kotlinCompilation, androidTarget), + paths = paths, + artifacts = artifacts, + taskContainer = MutableTaskContainer(), + services = taskCreationServices, + global = global, + androidKotlinCompilation = kotlinCompilation, + mainVariant = mainVariant, + manifestFile = manifestLocation ) } diff --git a/build-system/kmp-android-prototype/src/main/resources/META-INF/gradle-plugins/com.android.experimental.kotlin.multiplatform.library.properties b/build-system/kmp-android-prototype/src/main/resources/META-INF/gradle-plugins/com.android.experimental.kotlin.multiplatform.library.properties new file mode 100644 index 0000000000..296878b796 --- /dev/null +++ b/build-system/kmp-android-prototype/src/main/resources/META-INF/gradle-plugins/com.android.experimental.kotlin.multiplatform.library.properties @@ -0,0 +1,16 @@ +# +# Copyright (C) 2022 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. +# +implementation-class=com.android.build.gradle.internal.plugins.KotlinMultiplatformAndroidPlugin diff --git a/build-system/manifest-merger/src/main/java/com/android/manifmerger/ManifestMerger2.java b/build-system/manifest-merger/src/main/java/com/android/manifmerger/ManifestMerger2.java index 94f35e4496..db025a4e9d 100644 --- a/build-system/manifest-merger/src/main/java/com/android/manifmerger/ManifestMerger2.java +++ b/build-system/manifest-merger/src/main/java/com/android/manifmerger/ManifestMerger2.java @@ -265,9 +265,6 @@ public class ManifestMerger2 { mergingReportBuilder, enforceUniquePackageName); } - // perform system property injection - performSystemPropertiesInjection(mergingReportBuilder, - loadedMainManifestInfo.getXmlDocument()); // invariant : xmlDocumentOptional holds the higher priority document and we try to // merge in lower priority documents. @@ -360,6 +357,9 @@ public class ManifestMerger2 { } xmlDocumentOptional = newMergedDocument.get(); + // perform system property injection + performSystemPropertiesInjection(mergingReportBuilder, xmlDocumentOptional); + // force main manifest package into resulting merged file when creating a library manifest. if (mMergeType == MergeType.LIBRARY) { // extract the package name... @@ -427,9 +427,6 @@ public class ManifestMerger2 { mProcessCancellationChecker.check(); - // perform system property injection again. - performSystemPropertiesInjection(mergingReportBuilder, xmlDocumentOptional); - // if it's a library of any kind - need to remove targetSdk if (!mOptionalFeatures.contains(Invoker.Feature.DISABLE_STRIP_LIBRARY_TARGET_SDK) && mMergeType != MergeType.APPLICATION) { @@ -644,11 +641,6 @@ public class ManifestMerger2 { optionalAddApplicationTagIfMissing(xmlDocument); } - if (mMergeType == MergeType.APPLICATION - && mOptionalFeatures.contains(Invoker.Feature.DO_NOT_EXTRACT_NATIVE_LIBS)) { - maybeAddExtractNativeLibAttribute(xmlDocument); - } - if (mOptionalFeatures.contains( Invoker.Feature.ADD_ANDROIDX_MULTIDEX_APPLICATION_IF_NO_NAME)) { addMultiDexApplicationIfNoName( @@ -751,23 +743,6 @@ public class ManifestMerger2 { } /** - * Set android:extractNativeLibs="false" unless it's already explicitly set. - * - * @param document the document for which the extractNativeLibs attribute should be set to - * false. - */ - private static void maybeAddExtractNativeLibAttribute(@NonNull XmlDocument document) { - XmlElement manifest = document.getRootNode(); - manifest.applyToFirstChildElementOfType( - ManifestModel.NodeTypes.APPLICATION, - application -> - setAndroidAttributeIfMissing( - application, - SdkConstants.ATTR_EXTRACT_NATIVE_LIBS, - SdkConstants.VALUE_FALSE)); - } - - /** * Set the {@code featureSplit} attribute to {@code featureName} for the manifest element. * * @param document the document whose attributes are changed @@ -947,12 +922,14 @@ public class ManifestMerger2 { * @param node Node in which to set the attribute; must be part of a document * @param localName Non-prefixed attribute name * @param value value of the attribute + * @return whether the attribute was set (i.e., whether it was missing previously) */ - private static void setAndroidAttributeIfMissing( - XmlElement node, String localName, String value) { + static boolean setAndroidAttributeIfMissing(XmlElement node, String localName, String value) { if (!node.getXml().hasAttributeNS(SdkConstants.ANDROID_URI, localName)) { setAndroidAttribute(node, localName, value); + return true; } + return false; } /** @@ -1167,13 +1144,24 @@ public class ManifestMerger2 { @NonNull LoadedManifestInfo lowerPriorityDocument, @NonNull MergingReport.Builder mergingReportBuilder) { + boolean validateExtractNativeLibsFromSources = + mSystemPropertyResolver.getValue( + ManifestSystemProperty.Application.EXTRACT_NATIVE_LIBS) + != null; + + Boolean higherPriorityExtractNativeLibsValue = + PreValidator.getExtractNativeLibsValue(xmlDocument); + boolean validateExtractNativeLibsFromDependencies = + mOptionalFeatures.contains( + Invoker.Feature.VALIDATE_EXTRACT_NATIVE_LIBS_FROM_DEPENDENCIES) + && !Boolean.TRUE.equals(higherPriorityExtractNativeLibsValue); + MergingReport.Result validationResult = PreValidator.validate( mergingReportBuilder, lowerPriorityDocument.getXmlDocument(), - mMergeType, - mOptionalFeatures.contains( - Invoker.Feature.VALIDATE_EXTRACT_NATIVE_LIBS_ATTRIBUTE)); + validateExtractNativeLibsFromSources, + validateExtractNativeLibsFromDependencies); if (validationResult == MergingReport.Result.ERROR && !mOptionalFeatures.contains(Invoker.Feature.KEEP_GOING_AFTER_ERRORS)) { @@ -1799,12 +1787,6 @@ public class ManifestMerger2 { /** Enforce that dependencies manifests don't have duplicated package names. */ ENFORCE_UNIQUE_PACKAGE_NAME, - /** - * Sets the application's android:extractNativeLibs attribute to false, unless it's - * already explicitly set to true. - */ - DO_NOT_EXTRACT_NATIVE_LIBS, - /** Unsafely disables minSdkVersion check in libraries. */ DISABLE_MINSDKLIBRARY_CHECK, @@ -1826,12 +1808,10 @@ public class ManifestMerger2 { KEEP_GOING_AFTER_ERRORS, /** - * Warn if the {@link SdkConstants#ATTR_EXTRACT_NATIVE_LIBS} attribute is present in a - * source manifest. - * - * <p>This is used in AGP because users must migrate to the new useLegacyPackaging APIs. + * Warn if the {@link SdkConstants#ATTR_EXTRACT_NATIVE_LIBS} attribute is set to true in + * a dependency manifest but not set to true in the merged manifest. */ - VALIDATE_EXTRACT_NATIVE_LIBS_ATTRIBUTE + VALIDATE_EXTRACT_NATIVE_LIBS_FROM_DEPENDENCIES } /** diff --git a/build-system/manifest-merger/src/main/java/com/android/manifmerger/ManifestModel.java b/build-system/manifest-merger/src/main/java/com/android/manifmerger/ManifestModel.java index ea9aa6cfd9..d1c78015d5 100644 --- a/build-system/manifest-merger/src/main/java/com/android/manifmerger/ManifestModel.java +++ b/build-system/manifest-merger/src/main/java/com/android/manifmerger/ManifestModel.java @@ -338,6 +338,8 @@ public class ManifestModel implements DocumentModel<ManifestModel.NodeTypes> { AttributeModel.newModel(SdkConstants.ATTR_LOCALE_CONFIG) .setMergingPolicy(STRICT_MAIN_OR_OVERLAY_MERGING_POLICY), AttributeModel.newModel(SdkConstants.ATTR_USE_EMBEDDED_DEX) + .setMergingPolicy(STRICT_MAIN_OR_OVERLAY_MERGING_POLICY), + AttributeModel.newModel(SdkConstants.ATTR_EXTRACT_NATIVE_LIBS) .setMergingPolicy(STRICT_MAIN_OR_OVERLAY_MERGING_POLICY)), /** diff --git a/build-system/manifest-merger/src/main/java/com/android/manifmerger/ManifestSystemProperty.kt b/build-system/manifest-merger/src/main/java/com/android/manifmerger/ManifestSystemProperty.kt index fd833b1515..5c7096223a 100644 --- a/build-system/manifest-merger/src/main/java/com/android/manifmerger/ManifestSystemProperty.kt +++ b/build-system/manifest-merger/src/main/java/com/android/manifmerger/ManifestSystemProperty.kt @@ -24,7 +24,6 @@ import com.android.manifmerger.ManifestMerger2.AutoAddingProperty import com.android.manifmerger.ManifestModel.NodeTypes import com.android.utils.SdkUtils import com.android.utils.XmlUtils -import org.w3c.dom.Element /** * List of manifest files properties that can be directly overridden without using a @@ -56,19 +55,22 @@ interface ManifestSystemProperty : AutoAddingProperty { /** * @see [ * https://developer.android.com/guide/topics/manifest/application-element](https://developer.android.com/guide/topics/manifest/application-element) + * + * [override] specifies whether an existing attribute value should be overridden. */ - enum class Application : ManifestSystemProperty { + enum class Application(private val override: Boolean) : ManifestSystemProperty { - TEST_ONLY; + TEST_ONLY(override = true), + EXTRACT_NATIVE_LIBS(override = false); override fun addTo(actionRecorder: ActionRecorder, document: XmlDocument, value: String) { - val msp = createOrGetElementInManifest( + val xmlElement = createOrGetElementInManifest( actionRecorder, document, NodeTypes.APPLICATION, "application injection requested" ) - addToElementInAndroidNS(this, actionRecorder, value, msp) + addToElementInAndroidNS(this, actionRecorder, value, xmlElement, override) } } @@ -183,21 +185,35 @@ private fun addToElement( recordElementInjectionAction(actionRecorder, to, xmlAttribute) } -// utility method to add an attribute in android namespace which local name is derived from -// the enum name(). +/** + * utility method to add an attribute in android namespace which local name is derived from + * the enum name(). + * + * @param override whether to override an existing attribute value + */ private fun addToElementInAndroidNS( elementAttribute: ManifestSystemProperty, actionRecorder: ActionRecorder, value: String, - to: XmlElement + to: XmlElement, + override: Boolean = true ) { val toolsPrefix = to.lookupNamespacePrefix( SdkConstants.ANDROID_URI, SdkConstants.ANDROID_NS_NAME, true) - to.setAttributeNS( - SdkConstants.ANDROID_URI, - toolsPrefix + XmlUtils.NS_SEPARATOR + elementAttribute.toCamelCase(), - value - ) + if (override) { + to.setAttributeNS( + SdkConstants.ANDROID_URI, + toolsPrefix + XmlUtils.NS_SEPARATOR + elementAttribute.toCamelCase(), + value + ) + } else { + val isModified = + ManifestMerger2.setAndroidAttributeIfMissing(to, elementAttribute.toCamelCase(), value) + if (!isModified) { + // no reason to record the action if not modified. + return + } + } val attr = to.getAttributeNodeNS( SdkConstants.ANDROID_URI, elementAttribute.toCamelCase() @@ -242,8 +258,7 @@ private fun createOrGetElement( ): XmlElement { return parentElement.createOrGetElementOfType( document, - nodeType, - SdkConstants.ANDROID_URI) { xmlElement -> + nodeType) { xmlElement -> val nodeRecord = NodeRecord( Actions.ActionType.INJECTED, SourceFilePosition( diff --git a/build-system/manifest-merger/src/main/java/com/android/manifmerger/PreValidator.java b/build-system/manifest-merger/src/main/java/com/android/manifmerger/PreValidator.java index accde08634..9f24340bce 100644 --- a/build-system/manifest-merger/src/main/java/com/android/manifmerger/PreValidator.java +++ b/build-system/manifest-merger/src/main/java/com/android/manifmerger/PreValidator.java @@ -18,7 +18,6 @@ package com.android.manifmerger; import static com.android.SdkConstants.ANDROID_URI; import static com.android.manifmerger.ManifestMerger2.COMPATIBLE_SCREENS_SUB_MANIFEST; -import static com.android.manifmerger.ManifestMerger2.MergeType.APPLICATION; import static com.android.manifmerger.ManifestMerger2.WEAR_APP_SUB_MANIFEST; import static com.android.manifmerger.MergingReport.Record.Severity.ERROR; import static com.android.manifmerger.MergingReport.Record.Severity.WARNING; @@ -26,6 +25,7 @@ import static com.android.manifmerger.XmlNode.NodeKey; import com.android.SdkConstants; import com.android.annotations.NonNull; +import com.android.annotations.Nullable; import com.android.xml.AndroidManifest; import com.google.common.base.Joiner; import com.google.common.base.Strings; @@ -69,22 +69,28 @@ public class PreValidator { * * @param mergingReport report to log warnings and errors. * @param xmlDocument the loaded xml part. - * @param mergeType the merge type. - * @param validateExtractNativeLibsAttribute whether to validate the application element's - * {@link SdkConstants#ATTR_EXTRACT_NATIVE_LIBS} attribute + * @param validateExtractNativeLibsFromSources whether to warn if the {@link + * SdkConstants#ATTR_EXTRACT_NATIVE_LIBS} attribute is set in a source (MAIN or OVERLAY) + * manifest. + * @param validateExtractNativeLibsFromDependencies whether to warn if the {@link + * SdkConstants#ATTR_EXTRACT_NATIVE_LIBS} attribute is set to true in a dependency (LIBRARY) + * manifest. * @return one the {@link MergingReport.Result} value. */ @NonNull public static MergingReport.Result validate( @NonNull MergingReport.Builder mergingReport, @NonNull XmlDocument xmlDocument, - @NonNull ManifestMerger2.MergeType mergeType, - boolean validateExtractNativeLibsAttribute) { + boolean validateExtractNativeLibsFromSources, + boolean validateExtractNativeLibsFromDependencies) { validatePackageAttribute( mergingReport, xmlDocument.getRootNode(), xmlDocument.getFileType()); - if (validateExtractNativeLibsAttribute) { - validateExtractNativeLibsAttribute(mergingReport, xmlDocument, mergeType); + if (validateExtractNativeLibsFromSources) { + validateExtractNativeLibsFromSources(mergingReport, xmlDocument); + } + if (validateExtractNativeLibsFromDependencies) { + validateExtractNativeLibsFromDependencies(mergingReport, xmlDocument); } return validate(mergingReport, xmlDocument.getRootNode()); } @@ -192,55 +198,88 @@ public class PreValidator { } } - /** Warn if android:extractNativeLibs is set in the MAIN or OVERLAY manifests. */ - private static void validateExtractNativeLibsAttribute( - @NonNull MergingReport.Builder mergingReport, - @NonNull XmlDocument xmlDocument, - @NonNull ManifestMerger2.MergeType mergeType) { - // Don't warn for manifests coming from dependencies because there is no simple fix. + /** Warn if android:extractNativeLibs is set in a MAIN or OVERLAY manifest. */ + private static void validateExtractNativeLibsFromSources( + @NonNull MergingReport.Builder mergingReport, @NonNull XmlDocument xmlDocument) { + // Ignore manifests coming from dependencies. if (xmlDocument.getFileType() == XmlDocument.Type.LIBRARY) { return; } - Optional<XmlElement> applicationElement = - xmlDocument.getByTypeAndKey(ManifestModel.NodeTypes.APPLICATION, null); - applicationElement.ifPresent( - element -> { - maybeWarnAboutAttribute( - mergingReport, - element, + final Boolean extractNativeLibsValue = getExtractNativeLibsValue(xmlDocument); + if (extractNativeLibsValue != null) { + String warning = + String.format( + "android:%1$s should not be specified in this " + + "source AndroidManifest.xml file. See " + + "%2$s for more information.\n" + + "The AGP Upgrade Assistant can remove " + + "the attribute from the " + + "AndroidManifest.xml file and update the " + + "build file accordingly. See %3$s for " + + "more information.", SdkConstants.ATTR_EXTRACT_NATIVE_LIBS, "https://d.android.com/guide/topics/manifest/application-element#extractNativeLibs", - mergeType); - }); + "https://d.android.com/studio/build/agp-upgrade-assistant"); + getExtractNativeLibsAttribute(xmlDocument) + .ifPresent(it -> mergingReport.addMessage(it, WARNING, warning)); + } } - private static void maybeWarnAboutAttribute( - @NonNull MergingReport.Builder mergingReport, - @NonNull XmlElement xmlElement, - @NonNull String attributeLocalName, - @NonNull String link, - @NonNull ManifestMerger2.MergeType mergeType) { - Optional<XmlAttribute> xmlAttribute = - xmlElement.getAttribute( - XmlNode.fromNSName(ANDROID_URI, "android", attributeLocalName)); - xmlAttribute.ifPresent( - it -> { - String warning = - String.format( - "android:%1$s should not be specified in source " - + "AndroidManifest.xml files. See %2$s for more " - + "information.", - attributeLocalName, link); - if (mergeType == APPLICATION) { - warning += - " The AGP Upgrade Assistant can remove the attribute " - + "from the AndroidManifest.xml file and " - + "update the build file accordingly. See " - + "https://d.android.com/studio/build/agp-upgrade-assistant " - + "for more information."; - } - mergingReport.addMessage(it, WARNING, warning); - }); + /** Warn if android:extractNativeLibs is set to true in LIBRARY manifest. */ + private static void validateExtractNativeLibsFromDependencies( + @NonNull MergingReport.Builder mergingReport, @NonNull XmlDocument xmlDocument) { + // Ignore MAIN and OVERLAY manifests. + if (xmlDocument.getFileType() != XmlDocument.Type.LIBRARY) { + return; + } + final Boolean extractNativeLibsValue = getExtractNativeLibsValue(xmlDocument); + if (Boolean.TRUE.equals(extractNativeLibsValue)) { + String warning = + String.format( + "android:%1$s is set to true in a dependency's " + + "AndroidManifest.xml, but not in the " + + "app's merged manifest. If the " + + "dependency truly requires its native " + + "libraries to be extracted, the app can " + + "be configured to do so by setting the " + + "jniLibs.useLegacyPackaging DSL to " + + "true.\n" + + "Otherwise, you can silence this type of " + + "warning by adding %2$s=true to your " + + "gradle.properties file.", + SdkConstants.ATTR_EXTRACT_NATIVE_LIBS, + "android.experimental.suppressExtractNativeLibsWarnings"); + getExtractNativeLibsAttribute(xmlDocument) + .ifPresent(it -> mergingReport.addMessage(it, WARNING, warning)); + } + } + + /** + * @param xmlDocument the XmlDocument to check for the value of the android:extractNativeLibs + * attribute + * @return the Boolean value of the android:extractNativeLibs attribute, or null if it's not set + */ + @Nullable + static Boolean getExtractNativeLibsValue(XmlDocument xmlDocument) { + final XmlAttribute extractNativeLibsAttribute = + getExtractNativeLibsAttribute(xmlDocument).orElse(null); + if (extractNativeLibsAttribute == null) { + return null; + } + return Boolean.valueOf(extractNativeLibsAttribute.getValue()); + } + + private static Optional<XmlAttribute> getExtractNativeLibsAttribute(XmlDocument xmlDocument) { + if (xmlDocument == null) { + return Optional.empty(); + } + final XmlElement applicationElement = + xmlDocument.getByTypeAndKey(ManifestModel.NodeTypes.APPLICATION, null).orElse(null); + if (applicationElement == null) { + return Optional.empty(); + } + return applicationElement.getAttribute( + XmlNode.fromNSName(ANDROID_URI, "android", SdkConstants.ATTR_EXTRACT_NATIVE_LIBS)); } private static boolean isSubManifest(@NonNull XmlElement manifest) { diff --git a/build-system/manifest-merger/src/main/java/com/android/manifmerger/XmlElement.java b/build-system/manifest-merger/src/main/java/com/android/manifmerger/XmlElement.java index ceab4018a2..1df0856e7a 100644 --- a/build-system/manifest-merger/src/main/java/com/android/manifmerger/XmlElement.java +++ b/build-system/manifest-merger/src/main/java/com/android/manifmerger/XmlElement.java @@ -381,22 +381,18 @@ public class XmlElement extends OrphanXmlElement { public XmlElement createOrGetElementOfType( XmlDocument document, ManifestModel.NodeTypes nodeType, - String namespaceUri, Consumer<XmlElement> postCreationAction) { - var elementName = document.getModel().toXmlName(nodeType); - var nodes = getXml().getElementsByTagName(elementName); - if (nodes.getLength() == 0) { - nodes = getXml().getElementsByTagNameNS(namespaceUri, elementName); - } - if (nodes.getLength() == 0) { - var node = getXml().getOwnerDocument().createElement(elementName); - appendChild(node); - var xmlElement = new XmlElement(node, document); - postCreationAction.accept(xmlElement); - return xmlElement; - } else { - return new XmlElement((Element) nodes.item(0), document); + Optional<XmlElement> optionalXmlElement = getFirstChildElementOfType(nodeType); + if (optionalXmlElement.isPresent()) { + return optionalXmlElement.get(); } + var elementName = document.getModel().toXmlName(nodeType); + var node = getXml().getOwnerDocument().createElement(elementName); + appendChild(node); + initMergeableChildren(); + var createdXmlElement = getFirstChildElementOfType(nodeType).get(); + postCreationAction.accept(createdXmlElement); + return createdXmlElement; } public void setAttribute(String name, String value) { diff --git a/build-system/manifest-merger/src/test/java/com/android/manifmerger/ManifestMerger2SmallTest.java b/build-system/manifest-merger/src/test/java/com/android/manifmerger/ManifestMerger2SmallTest.java index 128bde6e50..636355f5b3 100644 --- a/build-system/manifest-merger/src/test/java/com/android/manifmerger/ManifestMerger2SmallTest.java +++ b/build-system/manifest-merger/src/test/java/com/android/manifmerger/ManifestMerger2SmallTest.java @@ -1829,33 +1829,35 @@ public class ManifestMerger2SmallTest { } @Test - public void testExtractNativeLibs_notInjected_forLIbs() throws Exception { + public void testExtractNativeLibs_injected_true() throws Exception { MockLog mockLog = new MockLog(); String input = "<manifest\n" + " xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" - + " package=\"example\">\n" + + " package=\"foo.bar\">\n" + " <application/>\n" + "</manifest>"; - File tmpFile = TestUtils.inputAsFile("ManifestMerger2Test_noExtractNativeLibs", input); + File tmpFile = TestUtils.inputAsFile("ManifestMerger2Test_extractNativeLibsFalse", input); assertTrue(tmpFile.exists()); try { MergingReport mergingReport = - ManifestMerger2.newMerger(tmpFile, mockLog, ManifestMerger2.MergeType.LIBRARY) - .withFeatures(Feature.DO_NOT_EXTRACT_NATIVE_LIBS) + ManifestMerger2.newMerger( + tmpFile, mockLog, ManifestMerger2.MergeType.APPLICATION) + .setOverride( + ManifestSystemProperty.Application.EXTRACT_NATIVE_LIBS, "true") .merge(); assertEquals(MergingReport.Result.SUCCESS, mergingReport.getResult()); String mergedDocument = mergingReport.getMergedDocument(MergedManifestKind.MERGED); - assertThat(mergedDocument).doesNotContain("extractNativeLibs"); + assertThat(mergedDocument).contains("android:extractNativeLibs=\"true\""); } finally { assertTrue(tmpFile.delete()); } } @Test - public void testExtractNativeLibs_injected() throws Exception { + public void testExtractNativeLibs_injected_false() throws Exception { MockLog mockLog = new MockLog(); String input = "<manifest\n" @@ -1871,7 +1873,8 @@ public class ManifestMerger2SmallTest { MergingReport mergingReport = ManifestMerger2.newMerger( tmpFile, mockLog, ManifestMerger2.MergeType.APPLICATION) - .withFeatures(Feature.DO_NOT_EXTRACT_NATIVE_LIBS) + .setOverride( + ManifestSystemProperty.Application.EXTRACT_NATIVE_LIBS, "false") .merge(); assertEquals(MergingReport.Result.SUCCESS, mergingReport.getResult()); String mergedDocument = mergingReport.getMergedDocument(MergedManifestKind.MERGED); @@ -1898,9 +1901,12 @@ public class ManifestMerger2SmallTest { MergingReport mergingReport = ManifestMerger2.newMerger( tmpFile, mockLog, ManifestMerger2.MergeType.APPLICATION) - .withFeatures(Feature.DO_NOT_EXTRACT_NATIVE_LIBS) + .setOverride( + ManifestSystemProperty.Application.EXTRACT_NATIVE_LIBS, "false") .merge(); - assertEquals(MergingReport.Result.SUCCESS, mergingReport.getResult()); + assertEquals(MergingReport.Result.WARNING, mergingReport.getResult()); + assertStringPresenceInLogRecords( + mergingReport, "android:extractNativeLibs should not be specified"); String mergedDocument = mergingReport.getMergedDocument(MergedManifestKind.MERGED); assertThat(mergedDocument).contains("android:extractNativeLibs=\"true\""); assertThat(mergedDocument).doesNotContain("android:extractNativeLibs=\"false\""); diff --git a/build-system/manifest-merger/src/test/java/com/android/manifmerger/ManifestMerger2Test.java b/build-system/manifest-merger/src/test/java/com/android/manifmerger/ManifestMerger2Test.java index 94d6fcfef5..ccc71ffb16 100644 --- a/build-system/manifest-merger/src/test/java/com/android/manifmerger/ManifestMerger2Test.java +++ b/build-system/manifest-merger/src/test/java/com/android/manifmerger/ManifestMerger2Test.java @@ -151,7 +151,8 @@ public class ManifestMerger2Test { "103_attribution_node.xml", "104_merging_privacy_sandbox_tagged_permissions.xml", "104b_merging_privacy_sandbox_tagged_permissions_all_untagged.xml", - "105_ignore_use_embedded_dex_from_library.xml" + "105_ignore_use_embedded_dex_from_library.xml", + "106_ignore_extract_native_libs_from_library.xml" }; private static final Multimap<Predicate<String>, ManifestMerger2.Invoker.Feature> diff --git a/build-system/manifest-merger/src/test/java/com/android/manifmerger/PreValidatorTest.java b/build-system/manifest-merger/src/test/java/com/android/manifmerger/PreValidatorTest.java index 81dfd8d08a..289627a6a9 100644 --- a/build-system/manifest-merger/src/test/java/com/android/manifmerger/PreValidatorTest.java +++ b/build-system/manifest-merger/src/test/java/com/android/manifmerger/PreValidatorTest.java @@ -16,8 +16,6 @@ package com.android.manifmerger; -import static com.android.manifmerger.ManifestMerger2.MergeType.APPLICATION; - import com.android.testutils.MockLog; import java.io.IOException; import java.util.logging.Logger; @@ -56,7 +54,7 @@ public class PreValidatorTest extends TestCase { MergingReport.Builder mergingReport = new MergingReport.Builder(mockLog); MergingReport.Result validated = - PreValidator.validate(mergingReport, xmlDocument, APPLICATION, true); + PreValidator.validate(mergingReport, xmlDocument, true, true); assertEquals(MergingReport.Result.SUCCESS, validated); assertTrue(mockLog.toString().isEmpty()); } @@ -84,7 +82,7 @@ public class PreValidatorTest extends TestCase { MergingReport.Builder mergingReport = new MergingReport.Builder(mockLog); MergingReport.Result validated = - PreValidator.validate(mergingReport, xmlDocument, APPLICATION, true); + PreValidator.validate(mergingReport, xmlDocument, true, true); assertEquals(MergingReport.Result.ERROR, validated); // assert the error message complains about the bad instruction usage. assertStringPresenceInLogRecords(mergingReport, "tools:replace"); @@ -114,7 +112,7 @@ public class PreValidatorTest extends TestCase { MergingReport.Builder mergingReport = new MergingReport.Builder(mockLog); MergingReport.Result validated = - PreValidator.validate(mergingReport, xmlDocument, APPLICATION, true); + PreValidator.validate(mergingReport, xmlDocument, true, true); assertEquals(MergingReport.Result.ERROR, validated); // assert the error message complains about the bad instruction usage. assertStringPresenceInLogRecords(mergingReport, "tools:remove"); @@ -144,7 +142,7 @@ public class PreValidatorTest extends TestCase { MergingReport.Builder mergingReport = new MergingReport.Builder(mockLog); MergingReport.Result validated = - PreValidator.validate(mergingReport, xmlDocument, APPLICATION, true); + PreValidator.validate(mergingReport, xmlDocument, true, true); assertEquals(MergingReport.Result.ERROR, validated); // assert the error message complains about the bad instruction usage. assertStringPresenceInLogRecords(mergingReport, "tools:node=\"removeAll\""); @@ -175,7 +173,7 @@ public class PreValidatorTest extends TestCase { MergingReport.Builder mergingReport = new MergingReport.Builder(mockLog); MergingReport.Result validated = - PreValidator.validate(mergingReport, xmlDocument, APPLICATION, true); + PreValidator.validate(mergingReport, xmlDocument, true, true); assertEquals(MergingReport.Result.ERROR, validated); // assert the error message complains about the bad instruction usage. assertStringPresenceInLogRecords(mergingReport, "tools:selector=\"foo\""); @@ -210,7 +208,7 @@ public class PreValidatorTest extends TestCase { MergingReport.Builder mergingReport = new MergingReport.Builder(mockLog); MergingReport.Result validated = - PreValidator.validate(mergingReport, xmlDocument, APPLICATION, true); + PreValidator.validate(mergingReport, xmlDocument, true, true); assertEquals(MergingReport.Result.SUCCESS, validated); } @@ -254,11 +252,11 @@ public class PreValidatorTest extends TestCase { MergingReport.Builder mergingReport = new MergingReport.Builder(mockLog); MergingReport.Result validated = - PreValidator.validate(mergingReport, xmlDocument, APPLICATION, true); + PreValidator.validate(mergingReport, xmlDocument, true, true); assertEquals(MergingReport.Result.SUCCESS, validated); } - public void testValidateExtractNativeLibsAttribute() + public void testValidateExtractNativeLibsFromSources() throws ParserConfigurationException, SAXException, IOException { MockLog mockLog = new MockLog(); String input = @@ -273,19 +271,48 @@ public class PreValidatorTest extends TestCase { XmlDocument xmlDocument = TestUtils.xmlDocumentFromString( TestUtils.sourceFile( - getClass(), "testValidateApplicationElementAttributes"), + getClass(), "testValidateExtractNativeLibsFromSources"), input, mModel); MergingReport.Builder mergingReport = new MergingReport.Builder(mockLog); MergingReport.Result validated = - PreValidator.validate(mergingReport, xmlDocument, APPLICATION, true); + PreValidator.validate(mergingReport, xmlDocument, true, true); assertEquals(MergingReport.Result.SUCCESS, validated); assertStringPresenceInLogRecords( mergingReport, - "android:extractNativeLibs should not be specified in source AndroidManifest.xml files."); + "android:extractNativeLibs should not be specified in this source AndroidManifest.xml file."); + assertStringPresenceInLogRecords( + mergingReport, "The AGP Upgrade Assistant can remove the attribute"); + } + + public void testValidateExtractNativeLibsFromDependencies() + throws ParserConfigurationException, SAXException, IOException { + MockLog mockLog = new MockLog(); + String input = + "" + + "<manifest\n" + + " xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" + + " package=\"com.example.lib\">\n" + + "\n" + + " <application android:extractNativeLibs=\"true\"/>\n" + + "\n" + + "</manifest>"; + + XmlDocument xmlDocument = + TestUtils.xmlLibraryFromString( + TestUtils.sourceFile( + getClass(), "testValidateExtractNativeLibsFromDependencies"), + input, + mModel); + + MergingReport.Builder mergingReport = new MergingReport.Builder(mockLog); + MergingReport.Result validated = + PreValidator.validate(mergingReport, xmlDocument, true, true); + assertEquals(MergingReport.Result.SUCCESS, validated); assertStringPresenceInLogRecords( - mergingReport, " The AGP Upgrade Assistant can remove the attribute"); + mergingReport, + "android:extractNativeLibs is set to true in a dependency's AndroidManifest.xml"); } private static void assertStringPresenceInLogRecords(MergingReport.Builder mergingReport, String s) { diff --git a/build-system/manifest-merger/src/test/java/com/android/manifmerger/data2/106_ignore_extract_native_libs_from_library.xml b/build-system/manifest-merger/src/test/java/com/android/manifmerger/data2/106_ignore_extract_native_libs_from_library.xml new file mode 100644 index 0000000000..bf56dd8b10 --- /dev/null +++ b/build-system/manifest-merger/src/test/java/com/android/manifmerger/data2/106_ignore_extract_native_libs_from_library.xml @@ -0,0 +1,48 @@ +# +# Copyright (C) 2023 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. +# +# +# Test: +# - Check that android:extractNativeLibs attributes from libraries are ignored (b/272553504) +# + +@main + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.test" > + + <application android:extractNativeLibs="false" /> + +</manifest> + + +@lib1 + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.lib" > + + <application android:extractNativeLibs="true" /> + +</manifest> + +@result + +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.test" > + + <application android:extractNativeLibs="false" /> + +</manifest> diff --git a/common/release_version.bzl b/common/release_version.bzl index 79c85745f3..0e23b9e56e 100644 --- a/common/release_version.bzl +++ b/common/release_version.bzl @@ -1,3 +1,3 @@ -BASE_VERSION = "31.1.0-alpha11" -BUILD_VERSION = "8.1.0-alpha11" -COMMANDLINE_TOOLS_VERSION = "11.0-alpha11" +BASE_VERSION = "31.1.0-beta01" +BUILD_VERSION = "8.1.0-beta01" +COMMANDLINE_TOOLS_VERSION = "11.0-beta01" diff --git a/common/src/main/java/com/android/SdkConstants.java b/common/src/main/java/com/android/SdkConstants.java index 871626910c..f17b54ccdc 100644 --- a/common/src/main/java/com/android/SdkConstants.java +++ b/common/src/main/java/com/android/SdkConstants.java @@ -888,7 +888,7 @@ public final class SdkConstants { public static final String CLASS_COMPOSE_VIEW = "androidx.compose.ui.platform.ComposeView"; public static final String CLASS_COMPOSE_VIEW_ADAPTER = - "androidx.compose.ui.tooling.preview.ComposeViewAdapter"; + "androidx.compose.ui.tooling.ComposeViewAdapter"; public static final String ATTR_COMPOSABLE_NAME = "composableName"; diff --git a/common/src/main/java/com/android/utils/DataBindingUtils.kt b/common/src/main/java/com/android/utils/DataBindingUtils.kt new file mode 100644 index 0000000000..391b1bbebf --- /dev/null +++ b/common/src/main/java/com/android/utils/DataBindingUtils.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 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. + */ +@file:JvmName("DataBindingUtils") +package com.android.utils + +import com.android.SdkConstants + +fun isBindingExpression(string: String): Boolean { + return string.startsWith(SdkConstants.PREFIX_BINDING_EXPR) || string.startsWith(SdkConstants.PREFIX_TWOWAY_BINDING_EXPR) +} diff --git a/common/src/main/java/com/android/utils/SdkUtils.java b/common/src/main/java/com/android/utils/SdkUtils.java index 85330e6495..a14c1d7746 100644 --- a/common/src/main/java/com/android/utils/SdkUtils.java +++ b/common/src/main/java/com/android/utils/SdkUtils.java @@ -366,6 +366,21 @@ public class SdkUtils { return fileName.substring(0, lastExtension); } + /** + * Returns the layout resource name for the given layout file + * + * @param layoutFile the file pointing to the layout + * @return the layout resource name, not including the `@layout` prefix + */ + public static String getLayoutName(File layoutFile) { + String name = layoutFile.getName(); + int dotIndex = name.indexOf('.'); + if (dotIndex != -1) { + name = name.substring(0, dotIndex); + } + return name; + } + public static final List<String> IMAGE_EXTENSIONS = ImmutableList.of( DOT_PNG, DOT_9PNG, DOT_GIF, DOT_JPEG, DOT_JPG, DOT_BMP, DOT_WEBP, DOT_AVIF); diff --git a/ddmlib/src/main/java/com/android/ddmlib/EmulatorConsole.java b/ddmlib/src/main/java/com/android/ddmlib/EmulatorConsole.java index ee12d680df..59c95efee6 100644 --- a/ddmlib/src/main/java/com/android/ddmlib/EmulatorConsole.java +++ b/ddmlib/src/main/java/com/android/ddmlib/EmulatorConsole.java @@ -33,7 +33,8 @@ package com.android.ddmlib; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.google.common.annotations.VisibleForTesting; - +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; @@ -56,13 +57,20 @@ public abstract class EmulatorConsole { @Nullable public abstract String getAvdName(); + @NonNull + public Path getAvdNioPath() throws CommandFailedException { + return Paths.get(getAvdPath()); + } + /** * The absolute path to the virtual device in the file system. The path is operating system * dependent; it will have / name separators on Linux and \ separators on Windows. * * @throws CommandFailedException If the subcommand failed or if the emulator's version is older - * than 30.0.18 + * than 30.0.18 + * @deprecated Use {@link #getAvdNioPath} */ + @Deprecated @NonNull public abstract String getAvdPath() throws CommandFailedException; diff --git a/ddmlib/src/test/java/com/android/ddmlib/IntegrationTest.java b/ddmlib/src/test/java/com/android/ddmlib/IntegrationTest.java index 03e2699e3f..beef9a6f28 100644 --- a/ddmlib/src/test/java/com/android/ddmlib/IntegrationTest.java +++ b/ddmlib/src/test/java/com/android/ddmlib/IntegrationTest.java @@ -33,7 +33,7 @@ import com.android.ddmlib.logcat.LogCatReceiverTask; import com.android.fakeadbserver.DeviceState; import com.android.fakeadbserver.FakeAdbServer; import com.android.fakeadbserver.PortForwarder; -import com.android.fakeadbserver.execcommandhandlers.PingExecCommandHandler; +import com.android.fakeadbserver.shellcommandhandlers.PingCommandHandler; import com.android.testutils.TestResources; import com.android.testutils.TestUtils; import com.google.common.base.Charsets; @@ -128,10 +128,9 @@ public class IntegrationTest { assertNotNull("Device serial=" + SERIAL, device); - String cmd = PingExecCommandHandler.PING_EXEC; String[] parameters = new String[0]; - String expectedResponse = PingExecCommandHandler.PING_EXEC_OUTPUT; - try (SocketChannel channel = device.rawExec(cmd, parameters)) { + String expectedResponse = PingCommandHandler.PING_COMMAND_FAKE_OUTPUT; + try (SocketChannel channel = device.rawExec("ping", parameters)) { channel.configureBlocking(true); byte[] bytes = new byte[expectedResponse.getBytes(Charsets.UTF_8).length]; ByteBuffer buffer = ByteBuffer.wrap(bytes); diff --git a/ddmlib/src/test/java/com/android/ddmlib/internal/FakeAdbTestRule.java b/ddmlib/src/test/java/com/android/ddmlib/internal/FakeAdbTestRule.java index 6b35b4e51b..9cb895af0a 100644 --- a/ddmlib/src/test/java/com/android/ddmlib/internal/FakeAdbTestRule.java +++ b/ddmlib/src/test/java/com/android/ddmlib/internal/FakeAdbTestRule.java @@ -64,9 +64,10 @@ public class FakeAdbTestRule extends ExternalResource { // Start server execution. myServer.start(); // Test that we obtain 1 device via the ddmlib APIs + AndroidDebugBridge.terminate(); AndroidDebugBridge.enableFakeAdbServerMode(myServer.getPort()); DdmPreferences.setJdwpProxyPort(getFreePort()); - AndroidDebugBridge.initIfNeeded(true); + AndroidDebugBridge.init(true); AndroidDebugBridge bridge = AndroidDebugBridge.createBridge(getPathToAdb().toString(), false); assertNotNull("Debug bridge", bridge); @@ -80,7 +81,11 @@ public class FakeAdbTestRule extends ExternalResource { // timing of when an adb server is started / stopped if (myServer != null) { myServer.stop(); - myServer.awaitServerTermination(1000, TimeUnit.MILLISECONDS); + if (!myServer.awaitServerTermination(1000, TimeUnit.MILLISECONDS)) { + // Not stopping fake adb server leads to thread leaks, + // that's hard to debug if we ignore the fact that we didn't stop. + throw new RuntimeException("fake adb server didn't stop"); + } } AndroidDebugBridge.terminate(); } diff --git a/debugger-tests/.editorconfig b/debugger-tests/.editorconfig new file mode 100644 index 0000000000..fb2a888e5a --- /dev/null +++ b/debugger-tests/.editorconfig @@ -0,0 +1,3 @@ +[*] +indent_size = 2 +tab_width = 2 diff --git a/debugger-tests/BUILD b/debugger-tests/BUILD new file mode 100644 index 0000000000..1b8f6d7425 --- /dev/null +++ b/debugger-tests/BUILD @@ -0,0 +1,94 @@ +load("//tools/base/bazel:bazel.bzl", "iml_module") +load("//tools/base/bazel:kotlin.bzl", "kotlin_library", "kotlin_test") + +tags = [ + "no_windows", + "no_mac", +] + +kotlin_library( + name = "debugger", + srcs = glob(["src/**/*.kt"]), + tags = tags, + deps = [ + "//prebuilts/studio/intellij-sdk:studio-sdk", + "@maven//:org.jetbrains.kotlinx.kotlinx-cli-jvm", + ], +) + +# A library with all tested classes +kotlin_library( + name = "test-classes", + srcs = glob(["resources/src/**/*.kt"]), + tags = tags, +) + +# A library with all tested classes so we can create a "*_deploy.jar" that contains all dependencies +java_binary( + name = "test-classes-binary", + main_class = "MainKt", + tags = tags, + runtime_deps = [ + ":test-classes", + ], +) + +# Test target +kotlin_test( + name = "tests", + srcs = glob(["testSrc/**/*.kt"]), + data = glob(["resources/**"]) + [":test-classes-binary_deploy.jar"], + friends = [":debugger"], + jvm_flags = [ + "-Dtest.suite.jar=tests.jar", + "-Dtest-classes-jar=$(location :test-classes-binary_deploy.jar)", + ], + tags = tags, + test_class = "com.android.testutils.JarTestSuite", + deps = [ + ":debugger", + "//tools/base/testutils:tools.testutils", + "@maven//:com.google.truth.truth", + "@maven//:junit.junit", + "@maven//:org.jetbrains.kotlin.kotlin-test", + ], +) + +# A command line program that updates the golden files. +java_binary( + name = "update-golden", + data = glob(["resources/**"]) + [":test-classes-binary_deploy.jar"], + jvm_flags = [ + "--add-opens=jdk.jdi/com.sun.tools.jdi=ALL-UNNAMED", + "-Dtest-classes-jar=$(location :test-classes-binary_deploy.jar)", + ], + main_class = "com.android.tools.debuggertests.UpdateGoldenKt", + tags = tags, + runtime_deps = [ + ":debugger", + ], +) + +# managed by go/iml_to_build +iml_module( + name = "studio.debugger-tests", + # do not sort: must match IML order + srcs = [ + "resources/src", + "src", + ], + iml_files = ["debugger-tests.iml"], + resources = ["resources/res"], + tags = tags, + test_srcs = ["testSrc"], + test_tags = ["manual"], + visibility = ["//visibility:public"], + # do not sort: must match IML order + deps = [ + "//prebuilts/studio/intellij-sdk:studio-sdk", + "//tools/adt/idea/.idea/libraries:jetbrains.kotlinx.coroutines.test[test]", + "//tools/adt/idea/.idea/libraries:mockito[test]", + "//tools/adt/idea/.idea/libraries:truth[test]", + "//prebuilts/tools/common/m2:kotlinx-cli-jvm-0.3.1", + ], +) diff --git a/debugger-tests/debugger-tests.iml b/debugger-tests/debugger-tests.iml new file mode 100644 index 0000000000..6a4877bd82 --- /dev/null +++ b/debugger-tests/debugger-tests.iml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" /> + <sourceFolder url="file://$MODULE_DIR$/resources/res" type="java-resource" /> + <sourceFolder url="file://$MODULE_DIR$/resources/src" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> + </content> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="inheritedJdk" /> + <orderEntry type="library" name="studio-sdk" level="project" /> + <orderEntry type="library" scope="TEST" name="jetbrains.kotlinx.coroutines.test" level="project" /> + <orderEntry type="library" scope="TEST" name="mockito" level="project" /> + <orderEntry type="library" scope="TEST" name="truth" level="project" /> + <orderEntry type="module-library"> + <library> + <CLASSES> + <root url="jar://$MODULE_DIR$/../../../prebuilts/tools/common/m2/repository/org/jetbrains/kotlinx/kotlinx-cli-jvm/0.3.1/kotlinx-cli-jvm-0.3.1.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + </library> + </orderEntry> + </component> +</module> diff --git a/debugger-tests/resources/res/golden/jvm/tests/Inline.txt b/debugger-tests/resources/res/golden/jvm/tests/Inline.txt new file mode 100644 index 0000000000..3eaebd4428 --- /dev/null +++ b/debugger-tests/resources/res/golden/jvm/tests/Inline.txt @@ -0,0 +1,21 @@ +Breakpoint: Inline.kt:25 +======================================================== + +Breakpoint: Inline.kt:30 +======================================================== +0 [12-40] : this_$iv : tests.Inline +1 [12-40] : i$iv : int +2 [12-40] : s$iv : java.lang.String +3 [14-40] : $i$f$foo : int + +Breakpoint: Inline.kt:35 +======================================================== +0 [12-40] : this_$iv : tests.Inline +1 [12-40] : i$iv : int +2 [12-40] : s$iv : java.lang.String +3 [14-40] : $i$f$foo : int +4 [33-39] : this_$iv$iv : tests.Inline +5 [33-39] : i$iv$iv : int +6 [33-39] : s$iv$iv : java.lang.String +7 [36-39] : $i$f$bar : int + diff --git a/debugger-tests/resources/res/golden/simple/tests/Inline.txt b/debugger-tests/resources/res/golden/simple/tests/Inline.txt new file mode 100644 index 0000000000..3eaebd4428 --- /dev/null +++ b/debugger-tests/resources/res/golden/simple/tests/Inline.txt @@ -0,0 +1,21 @@ +Breakpoint: Inline.kt:25 +======================================================== + +Breakpoint: Inline.kt:30 +======================================================== +0 [12-40] : this_$iv : tests.Inline +1 [12-40] : i$iv : int +2 [12-40] : s$iv : java.lang.String +3 [14-40] : $i$f$foo : int + +Breakpoint: Inline.kt:35 +======================================================== +0 [12-40] : this_$iv : tests.Inline +1 [12-40] : i$iv : int +2 [12-40] : s$iv : java.lang.String +3 [14-40] : $i$f$foo : int +4 [33-39] : this_$iv$iv : tests.Inline +5 [33-39] : i$iv$iv : int +6 [33-39] : s$iv$iv : java.lang.String +7 [36-39] : $i$f$bar : int + diff --git a/debugger-tests/resources/src/Breakpoint.kt b/debugger-tests/resources/src/Breakpoint.kt new file mode 100644 index 0000000000..9557c55a48 --- /dev/null +++ b/debugger-tests/resources/src/Breakpoint.kt @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2023 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. + */ + +/** A method that tested code calls when it wants to check a breakpoint. */ +internal fun breakpoint() { + // nothing to do +} diff --git a/debugger-tests/resources/src/Main.kt b/debugger-tests/resources/src/Main.kt new file mode 100644 index 0000000000..f586a56f1e --- /dev/null +++ b/debugger-tests/resources/src/Main.kt @@ -0,0 +1,27 @@ +import kotlin.system.exitProcess + +/* + * Copyright (C) 2023 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. + */ + +fun main(args: Array<String>) { + if (args.size != 1) { + println("Missing test class name argument") + exitProcess(1) + } + val testClass = object {}.javaClass.classLoader.loadClass(args[0]) + val method = testClass.getDeclaredMethod("start") + method.invoke(null) +} diff --git a/debugger-tests/resources/src/tests/Inline.kt b/debugger-tests/resources/src/tests/Inline.kt new file mode 100644 index 0000000000..6fb7ee45c4 --- /dev/null +++ b/debugger-tests/resources/src/tests/Inline.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 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 tests + +import breakpoint + +@Suppress("NOTHING_TO_INLINE", "SameParameterValue", "UNUSED_PARAMETER", "unused") +object Inline { + + @JvmStatic + fun start() { + breakpoint() + foo(1, "Hello") + } + + private inline fun foo(i: Int, s: String) { + breakpoint() + bar(i + 1, s + "1") + } + + private inline fun bar(i: Int, s: String) { + breakpoint() + } +} diff --git a/debugger-tests/src/com/android/tools/debuggertests/Debugger.kt b/debugger-tests/src/com/android/tools/debuggertests/Debugger.kt new file mode 100644 index 0000000000..f1044c2390 --- /dev/null +++ b/debugger-tests/src/com/android/tools/debuggertests/Debugger.kt @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2023 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.tools.debuggertests + +import com.sun.jdi.Bootstrap.virtualMachineManager +import com.sun.jdi.VirtualMachine +import com.sun.jdi.connect.Connector +import com.sun.jdi.event.ClassPrepareEvent +import com.sun.jdi.event.Event +import com.sun.jdi.event.VMStartEvent + +private const val LAUNCH_CONNECTOR = "com.sun.jdi.CommandLineLaunch" +private const val ATTACH_CONNECTOR = "com.sun.jdi.SocketAttach" + +/** A simple JDI client that can set a breakpoint */ +internal class Debugger private constructor(private val vm: VirtualMachine) { + + private val requestManager = vm.eventRequestManager() + private val eventChannel = EventChannel(vm.eventQueue()) + + suspend fun start() { + eventChannel.receive<VMStartEvent>() + } + + /** Resume execution and return the next event. */ + suspend inline fun <reified T : Event> resume(): T { + vm.resume() + return eventChannel.receive() + } + + /** Set a breakpoint */ + suspend fun setBreakpoint(className: String, line: Int) { + requestManager.createClassPrepareRequest().apply { + addClassFilter(className) + addCountFilter(1) + enable() + } + val event = resume<ClassPrepareEvent>() + + requestManager + .createBreakpointRequest(event.referenceType().locationsOfLine(line).first()) + .apply { enable() } + } + + companion object { + + fun launch(mainClass: String, classpath: String): Debugger { + val connector = virtualMachineManager().launchingConnectors().named(LAUNCH_CONNECTOR) + val arguments = connector.defaultArguments() + arguments["main"]?.setValue("MainKt $mainClass") + arguments["options"]?.setValue("-classpath $classpath") + return Debugger(connector.launch(arguments)) + } + + fun attachToProcess(hostname: String, port: Int): Debugger { + val connector = virtualMachineManager().attachingConnectors().named(ATTACH_CONNECTOR) + val arguments = connector.defaultArguments() + arguments["hostname"]?.setValue(hostname) + (arguments["port"] as? Connector.IntegerArgument)?.setValue(port) + return Debugger(connector.attach(arguments)) + } + } +} + +private inline fun <reified T : Connector> List<T>.named(name: String): T = first { + it.name() == name +} diff --git a/debugger-tests/src/com/android/tools/debuggertests/Engine.kt b/debugger-tests/src/com/android/tools/debuggertests/Engine.kt new file mode 100644 index 0000000000..54b8d61cad --- /dev/null +++ b/debugger-tests/src/com/android/tools/debuggertests/Engine.kt @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2023 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.tools.debuggertests + +import com.sun.jdi.LocalVariable +import com.sun.jdi.Location +import com.sun.jdi.event.BreakpointEvent +import com.sun.jdi.event.Event +import java.io.Closeable + +private const val BREAKPOINT_CLASS = "BreakpointKt" +private const val BREAKPOINT_LINE = 20 + +/** A simple test engine */ +internal abstract class Engine : Closeable { + + protected abstract suspend fun createDebugger(): Debugger + + /** + * Executes a single test. + * 1. Starts a [Debugger] + * 2. Sets a breakpoint at Breakpoint.breakpoint() + * 3. Resumes the program each time it hits a breakpoint + * 4. On each breakpoint, emits information about the frame into a string + */ + suspend fun runTest(): String { + val debugger = createDebugger() + debugger.start() + debugger.setBreakpoint(BREAKPOINT_CLASS, BREAKPOINT_LINE) + val actual = buildString { + while (true) { + val breakpoint = debugger.resume<Event>() as? BreakpointEvent ?: break + val frame = breakpoint.thread().frames()[1] + val location = frame.location() + append("Breakpoint: ${location.sourceName()}:${location.lineNumber()}\n") + append("========================================================\n") + frame.visibleVariables().map { variable -> + val scope = + "[%d-%d]".format( + variable.getStartScope().codeIndex(), + variable.getEndScope().codeIndex() + ) + val line = + "%-2d %-10s: %-20s: %s\n".format( + variable.getSlot(), + scope, + variable.name(), + variable.typeName() + ) + append(line) + } + append('\n') + } + } + return actual + } + + enum class EngineType(private val factory: (String) -> Engine) { + SIMPLE(::SimpleEngine), + JVM(::JvmEngine), + ; + + fun getEngine(testName: String) = factory(testName) + } +} + +private fun LocalVariable.getStartScope(): Location = getFieldValue("scopeStart") + +private fun LocalVariable.getEndScope(): Location = getFieldValue("scopeEnd") + +private fun LocalVariable.getSlot(): Int = getFieldValue("slot") + +private inline fun <reified T> Any.getFieldValue(name: String): T { + val field = javaClass.getDeclaredField(name).apply { isAccessible = true } + return field.get(this) as T +} diff --git a/debugger-tests/src/com/android/tools/debuggertests/EventChannel.kt b/debugger-tests/src/com/android/tools/debuggertests/EventChannel.kt new file mode 100644 index 0000000000..8a2215a265 --- /dev/null +++ b/debugger-tests/src/com/android/tools/debuggertests/EventChannel.kt @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2023 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.tools.debuggertests + +import com.sun.jdi.event.Event +import com.sun.jdi.event.EventQueue +import com.sun.jdi.event.VMDeathEvent +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.runBlocking + +/** Converts an [EventQueue] into a [Flow<Event>] */ +internal class EventChannel(queue: EventQueue) { + + private val channel = Channel<Event>(10) + private var thread = EventQueueThread(queue, channel) + + init { + thread.start() + } + + suspend inline fun <reified T : Event> receive(): T { + val event = channel.receive() + return event as? T ?: throw IllegalStateException("Unexpected event: $event") + } + + private class EventQueueThread( + private val queue: EventQueue, + private val channel: Channel<Event> + ) : Thread("Event Queue") { + + override fun run() { + var done = false + while (!done) { + val events = + try { + queue.remove() + } catch (e: InterruptedException) { + return + } + events.forEach { + runBlocking { + channel.send(it) + if (it is VMDeathEvent) { + done = true + } + } + } + } + } + } +} diff --git a/debugger-tests/src/com/android/tools/debuggertests/JvmEngine.kt b/debugger-tests/src/com/android/tools/debuggertests/JvmEngine.kt new file mode 100644 index 0000000000..2640967f91 --- /dev/null +++ b/debugger-tests/src/com/android/tools/debuggertests/JvmEngine.kt @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2023 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.tools.debuggertests + +import java.io.BufferedReader +import java.io.InputStreamReader +import java.lang.ProcessBuilder.Redirect.INHERIT +import java.lang.ProcessBuilder.Redirect.PIPE +import java.nio.file.Paths +import kotlin.io.path.pathString +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers.IO +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.cancel +import kotlinx.coroutines.currentCoroutineContext +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +private const val JDWP_OPTIONS = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y" +private const val CLASSPATH = "-classpath" +private const val MAIN = "MainKt" +private val JAVA = if (isWindows()) "java.exe" else "java" + +/** + * An [Engine] that launches and connects to a program using a socket. + * + * Starts a java process and connects to it using the socket JDWP transport. + */ +internal class JvmEngine(private val mainClass: String) : Engine() { + + private lateinit var process: Process + private val scope = CoroutineScope(SupervisorJob()) + + override suspend fun createDebugger(): Debugger { + val classpath = Resources.getTestClassesJarPath() + process = + ProcessBuilder(getJavaExe(), JDWP_OPTIONS, CLASSPATH, classpath, MAIN, mainClass) + .redirectOutput(PIPE) + .redirectError(INHERIT) + .start() + + val portDeferred = CompletableDeferred<Int>() + scope.launch { + launch { + BufferedReader(InputStreamReader(process.inputStream)).use { + while (currentCoroutineContext().isActive) { + val line = withContext(IO) { it.readLine() } ?: break + println(line) + if (line.startsWith("Listening")) { + portDeferred.complete(line.substringAfterLast(": ").toInt()) + break + } + } + while (currentCoroutineContext().isActive) { + val line = withContext(IO) { it.readLine() } ?: break + println(line) + } + } + } + } + val port = portDeferred.await() + println("Attaching to localhost:$port") + return Debugger.attachToProcess("localhost", port) + } + + override fun close() { + if (this::process.isInitialized && process.isAlive) { + process.destroyForcibly() + } + scope.cancel() + } +} + +private fun isWindows() = System.getProperty("os.name").lowercase().startsWith("windows") + +private fun getJavaExe() = Paths.get(System.getProperty("java.home"), "bin", JAVA).pathString diff --git a/debugger-tests/src/com/android/tools/debuggertests/Resources.kt b/debugger-tests/src/com/android/tools/debuggertests/Resources.kt new file mode 100644 index 0000000000..6ce047b80e --- /dev/null +++ b/debugger-tests/src/com/android/tools/debuggertests/Resources.kt @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2023 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.tools.debuggertests + +import com.intellij.util.io.isFile +import java.io.File +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths +import kotlin.io.path.pathString +import kotlin.io.path.reader +import kotlin.io.path.writer +import kotlin.streams.asSequence + +private const val MODULE_PATH = "tools/base/debugger-tests" +private const val RESOURCE_PATH = "$MODULE_PATH/resources" +private const val TEST_CLASSES_JAR = "bazel-bin/$MODULE_PATH/test-classes-binary_deploy.jar" +private const val TOOLS_ADT = "tools/adt/idea" +private const val RES = "res" +private const val GOLDEN = "golden" +private const val SRC = "src" +private const val TESTS = "tests" +private const val BAZEL_PWD = "BUILD_WORKSPACE_DIRECTORY" +private const val TEST_CLASSES = "test-classes-jar" +private const val USER_DIR = "user.dir" + +/** Utilities for fetching resources */ +object Resources { + + /** Find all tested classes. */ + fun findTestClasses(): List<String> { + return Files.walk(Paths.get(getRepoResourceDir(), SRC, TESTS)) + .asSequence() + .filter(Path::isFile) + .map(Path::toClassName) + .toList() + } + + /** Read expected result from golden file */ + fun readGolden(test: String, dir: String): String { + val path = Paths.get(getRepoResourceDir(), RES, GOLDEN, dir, getGoldenFileName(test)) + return path.reader().use { it.readText() } + } + + /** Write expected result to golden file */ + fun writeGolden(test: String, actual: String, dir: String) { + val fileName = getGoldenFileName(test) + val path = Paths.get(getWorkspaceDir(), RESOURCE_PATH, RES, GOLDEN, dir, fileName) + path.parent.toFile().mkdirs() + path.writer().use { it.write(actual) } + } + + fun getTestClassesJarPath(): String { + val jarPath = System.getProperty(TEST_CLASSES) + if (jarPath != null) { + return jarPath + } + val path = Paths.get(getWorkspaceDir(), TEST_CLASSES_JAR) + if (path.isFile()) { + return path.pathString + } + throw IllegalStateException( + """ + $TEST_CLASSES_JAR not found. Please run + 'bazel build //tools/base/debugger-tests:test-classes-binary_deploy.jar' + """ + ) + } +} + +private fun getWorkspaceDir(): String = + System.getenv(BAZEL_PWD) ?: System.getProperty(USER_DIR).removeSuffix(TOOLS_ADT) + +// Only works when running locally. Used for writing golden files +private fun getRepoResourceDir(): String { + val path = Paths.get(System.getProperty(USER_DIR).removeSuffix(TOOLS_ADT)) + return Paths.get(path.pathString, RESOURCE_PATH).pathString +} + +private fun getGoldenFileName(test: String) = "${test.replace(".", File.separator)}.txt" + +private fun Path.toClassName() = + pathString + .substringAfterLast("src${File.separator}") + .replace(File.separator, ".") + .removeSuffix(".kt") diff --git a/debugger-tests/src/com/android/tools/debuggertests/SimpleEngine.kt b/debugger-tests/src/com/android/tools/debuggertests/SimpleEngine.kt new file mode 100644 index 0000000000..229c70f063 --- /dev/null +++ b/debugger-tests/src/com/android/tools/debuggertests/SimpleEngine.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2023 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.tools.debuggertests + +/** + * A simple [Engine] that launches and connects to a program. + * + * This is the easiest way to debug a program. It uses a [com.sun.jdi.connect.LaunchingConnector] + * which launches and connects to the process. + */ +internal class SimpleEngine(private val mainClass: String) : Engine() { + + override suspend fun createDebugger() = + Debugger.launch(mainClass, Resources.getTestClassesJarPath()) + + override fun close() {} +} diff --git a/debugger-tests/src/com/android/tools/debuggertests/UpdateGolden.kt b/debugger-tests/src/com/android/tools/debuggertests/UpdateGolden.kt new file mode 100644 index 0000000000..e377967c71 --- /dev/null +++ b/debugger-tests/src/com/android/tools/debuggertests/UpdateGolden.kt @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2023 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.tools.debuggertests + +import com.android.tools.debuggertests.Engine.EngineType +import com.android.tools.debuggertests.Engine.EngineType.JVM +import com.android.tools.debuggertests.Engine.EngineType.SIMPLE +import kotlin.time.Duration.Companion.seconds +import kotlinx.cli.ArgParser +import kotlinx.cli.ArgType +import kotlinx.cli.default +import kotlinx.cli.optional +import kotlinx.cli.vararg +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeout + +/** + * Updates golden files. + * + * Run with `bazel run //tools/base/debugger-tests:update-golden` + * + * When running from Intellij, add to VM options: + * ``` + * --add-opens=jdk.jdi/com.sun.tools.jdi=ALL-UNNAMED + * ``` + */ +fun main(args: Array<String>) { + val parser = ArgParser("UpdateGolden") + val verbose by parser.option(ArgType.Boolean, shortName = "v").default(false) + val noop by parser.option(ArgType.Boolean, shortName = "n").default(false) + val type by parser.option(ArgType.Choice<EngineType>(), shortName = "t").default(SIMPLE) + val tests by parser.argument(ArgType.String).vararg().optional() + parser.parse(args) + + val testClasses = tests.takeIf { it.isNotEmpty() } ?: Resources.findTestClasses() + testClasses.forEach { testClass -> + println("Test $testClass") + val engine = + when (type) { + SIMPLE -> SimpleEngine(testClass) + JVM -> JvmEngine(testClass) + } + engine.use { + val actual = runBlocking { withTimeout(30.seconds) { engine.runTest() } } + if (!noop) { + Resources.writeGolden(testClass, actual, type.name.lowercase()) + } + if (verbose) { + println(actual) + } + } + } +} diff --git a/debugger-tests/testSrc/com/android/tools/debuggertests/DebuggerTestBase.kt b/debugger-tests/testSrc/com/android/tools/debuggertests/DebuggerTestBase.kt new file mode 100644 index 0000000000..91ceaacc8e --- /dev/null +++ b/debugger-tests/testSrc/com/android/tools/debuggertests/DebuggerTestBase.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 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.tools.debuggertests + +import com.android.tools.debuggertests.Engine.EngineType +import com.google.common.truth.Truth +import kotlin.time.Duration.Companion.seconds +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeout + +/** A base class for Debugger Tests */ +internal abstract class DebuggerTestBase(private val testClass: String) { + + private fun describeTest() = "at $testClass(${testClass.substringAfterLast(".")}.kt:20)" + + fun runTest(engineType: EngineType) { + val actual = runBlocking { + withTimeout(5.seconds) { engineType.getEngine(testClass).runTest() } + } + val expected = Resources.readGolden(testClass, engineType.name.lowercase()) + + Truth.assertThat(actual).named(describeTest()).isEqualTo(expected) + } +} diff --git a/debugger-tests/testSrc/com/android/tools/debuggertests/JvmEngineDebuggerTest.kt b/debugger-tests/testSrc/com/android/tools/debuggertests/JvmEngineDebuggerTest.kt new file mode 100644 index 0000000000..095b9ced5b --- /dev/null +++ b/debugger-tests/testSrc/com/android/tools/debuggertests/JvmEngineDebuggerTest.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 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.tools.debuggertests + +import com.android.tools.debuggertests.Engine.EngineType.JVM +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized +import org.junit.runners.Parameterized.Parameters + +/** Runs tests using a [JvmEngine] */ +@RunWith(Parameterized::class) +internal class JvmEngineDebuggerTest(testClass: String) : DebuggerTestBase(testClass) { + + companion object { + + @JvmStatic @Parameters fun getTestClasses() = Resources.findTestClasses() + } + + @Test + fun test() { + runTest(JVM) + } +} diff --git a/debugger-tests/testSrc/com/android/tools/debuggertests/SimpleEngineDebuggerTest.kt b/debugger-tests/testSrc/com/android/tools/debuggertests/SimpleEngineDebuggerTest.kt new file mode 100644 index 0000000000..9234953ec0 --- /dev/null +++ b/debugger-tests/testSrc/com/android/tools/debuggertests/SimpleEngineDebuggerTest.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 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.tools.debuggertests + +import com.android.tools.debuggertests.Engine.EngineType.SIMPLE +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized +import org.junit.runners.Parameterized.Parameters + +/** Runs tests using a [SimpleEngine] */ +@RunWith(Parameterized::class) +internal class SimpleEngineDebuggerTest(testClass: String) : DebuggerTestBase(testClass) { + + companion object { + + @JvmStatic @Parameters fun getTestClasses() = Resources.findTestClasses() + } + + @Test + fun test() { + runTest(SIMPLE) + } +} diff --git a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceAction.kt b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceAction.kt index 911e492cec..52b356557b 100644 --- a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceAction.kt +++ b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceAction.kt @@ -73,7 +73,11 @@ interface EditAction : DeviceAction { } interface EditTemplateAction : DeviceAction { - suspend fun edit() + /** + * Invokes a UI to make edits to the template. If the edits are accepted, returns the new template + * that was created. + */ + suspend fun edit(): DeviceTemplate? } /** Deletes the given device from any persistent storage. */ diff --git a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceHandle.kt b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceHandle.kt index 81779e3b35..db3db3618e 100644 --- a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceHandle.kt +++ b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceHandle.kt @@ -40,6 +40,10 @@ interface DeviceHandle { val stateFlow: StateFlow<DeviceState> + /** The DeviceTemplate that this handle originated from, if applicable. */ + val sourceTemplate: DeviceTemplate? + get() = null + /** An action that allows activating the device, or null if activation is not supported. */ val activationAction: ActivationAction? get() = null diff --git a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProperties.kt b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProperties.kt index 0fc6746ccb..d274b06f0d 100644 --- a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProperties.kt +++ b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProperties.kt @@ -60,6 +60,14 @@ interface DeviceProperties { */ val disambiguator: String? + /** + * The ID used by the WearPairingManager for this device (in the PairingDevice.deviceId field). + * This must be kept in sync with WearPairingManager's IDevice.getDeviceID extension function. + * This is a stopgap until WearPairingManager is ported to adblib / DeviceProvisioner, and should + * not be used except for interfacing with WearPairingManager. + */ + val wearPairingId: String? + /** Default implementation of device title; may be overridden. */ val title: String get() { @@ -85,6 +93,7 @@ interface DeviceProperties { var disambiguator: String? = null var deviceType: DeviceType? = null var isVirtual: Boolean? = null + var wearPairingId: String? = null fun readCommonProperties(properties: Map<String, String>) { manufacturer = properties[RO_PRODUCT_MANUFACTURER] ?: properties[RO_MANUFACTURER] @@ -113,6 +122,7 @@ interface DeviceProperties { disambiguator = disambiguator, deviceType = deviceType, isVirtual = isVirtual, + wearPairingId = wearPairingId, ) } @@ -125,6 +135,7 @@ interface DeviceProperties { override val disambiguator: String?, override val deviceType: DeviceType?, override val isVirtual: Boolean?, + override val wearPairingId: String? ) : DeviceProperties } diff --git a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProvisioner.kt b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProvisioner.kt index a550e28a36..9385967d10 100644 --- a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProvisioner.kt +++ b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProvisioner.kt @@ -43,6 +43,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.time.withTimeoutOrNull +import org.jetbrains.annotations.TestOnly /** * Central access point for devices and device templates. [DeviceProvisionerPlugin] instances @@ -51,12 +52,22 @@ import kotlinx.coroutines.time.withTimeoutOrNull */ class DeviceProvisioner private constructor( + val scope: CoroutineScope, private val adbSession: AdbSession, private val provisioners: List<DeviceProvisionerPlugin> ) { companion object { + @TestOnly fun create(adbSession: AdbSession, provisioners: List<DeviceProvisionerPlugin>) = + create(adbSession.scope, adbSession, provisioners) + + fun create( + coroutineScope: CoroutineScope, + adbSession: AdbSession, + provisioners: List<DeviceProvisionerPlugin> + ) = DeviceProvisioner( + coroutineScope, adbSession, (provisioners + OfflineDeviceProvisionerPlugin() + DefaultProvisionerPlugin()) .sortedByDescending { it.priority } @@ -70,9 +81,6 @@ private constructor( private val combinedDevices = combine(provisioners.map { it.devices }) { it.flatMap { it } } private val combinedTemplates = combine(provisioners.map { it.templates }) { it.flatMap { it } } - val scope: CoroutineScope - get() = adbSession.scope - /** The [device handles][DeviceHandle] known to this class, provided by its plugins. */ val devices: StateFlow<List<DeviceHandle>> = combinedDevices.stateIn(adbSession.scope, SharingStarted.Eagerly, emptyList()) diff --git a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceTemplate.kt b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceTemplate.kt index c6377855a3..615290fccf 100644 --- a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceTemplate.kt +++ b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceTemplate.kt @@ -19,9 +19,11 @@ package com.android.sdklib.deviceprovisioner * A DeviceTemplate contains the information necessary to activate / lease a device from a * provisioner. In contrast to a DeviceHandle, it does not refer to a specific device: each * activation produces a different device. + * + * A [DeviceTemplate] instance should be immutable. */ interface DeviceTemplate { - val displayName: String + val properties: DeviceProperties /** * An action that instantiates the template as a specific device. This may involve obtaining a diff --git a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/LocalEmulatorProvisionerPlugin.kt b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/LocalEmulatorProvisionerPlugin.kt index 65d74264f6..f1ac11c461 100644 --- a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/LocalEmulatorProvisionerPlugin.kt +++ b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/LocalEmulatorProvisionerPlugin.kt @@ -65,6 +65,7 @@ import kotlinx.coroutines.withContext * rescanned after an edit is made via a device action. */ class LocalEmulatorProvisionerPlugin( + private val scope: CoroutineScope, private val adbSession: AdbSession, private val avdManager: AvdManager, rescanPeriod: Duration = Duration.ofSeconds(10) @@ -83,8 +84,6 @@ class LocalEmulatorProvisionerPlugin( suspend fun stopAvd(avdInfo: AvdInfo) } - private val scope = adbSession.scope - // We can identify local emulators reliably, so this can be relatively high priority. override val priority = 100 @@ -212,6 +211,7 @@ class LocalEmulatorProvisionerPlugin( avdName = handle.avdInfo.name displayName = handle.avdInfo.displayName disambiguator = port.toString() + wearPairingId = path.toString() } handle.stateFlow.value = Connected(properties, device) handle @@ -227,6 +227,7 @@ class LocalEmulatorProvisionerPlugin( avdName = avdInfo.name displayName = avdInfo.displayName deviceType = avdInfo.tag.toDeviceType() + wearPairingId = avdInfo.id } private fun IdDisplay.toDeviceType(): DeviceType = diff --git a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/PhysicalDeviceProvisionerPlugin.kt b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/PhysicalDeviceProvisionerPlugin.kt index f77396535f..cdcab4bb91 100644 --- a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/PhysicalDeviceProvisionerPlugin.kt +++ b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/PhysicalDeviceProvisionerPlugin.kt @@ -41,11 +41,17 @@ class PhysicalDeviceProvisionerPlugin(val scope: CoroutineScope) : DeviceProvisi PhysicalDeviceProperties.build { readCommonProperties(properties) isVirtual = false + val matcher = WIFI_SERIAL_NUMBER.matchEntire(device.serialNumber) connectionType = - when (WIFI_SERIAL_NUMBER.matchEntire(device.serialNumber)) { + when (matcher) { null -> ConnectionType.USB else -> ConnectionType.WIFI } + wearPairingId = + when (matcher) { + null -> device.serialNumber + else -> matcher.groupValues[1] + } } val serialNumber = checkNotNull(properties["ro.serialno"]) { "Missing [ro.serialno] property" } diff --git a/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/DeviceProvisionerTest.kt b/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/DeviceProvisionerTest.kt index ae437a0800..efd61d910c 100644 --- a/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/DeviceProvisionerTest.kt +++ b/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/DeviceProvisionerTest.kt @@ -47,7 +47,7 @@ class DeviceProvisionerTest { val fakeSession = FakeAdbSession() val plugin = PhysicalDeviceProvisionerPlugin(fakeSession.scope) - val provisioner = DeviceProvisioner.create(fakeSession, listOf(plugin)) + val provisioner = DeviceProvisioner.create(fakeSession.scope, fakeSession, listOf(plugin)) object SerialNumbers { val physicalUsb = "X1058A" @@ -106,10 +106,15 @@ class DeviceProvisionerTest { handles.associateBy { (it.state.properties as PhysicalDeviceProperties).connectionType } assertThat(handlesByType).hasSize(2) - assertThat(handlesByType[ConnectionType.USB]?.state?.connectedDevice?.serialNumber) + val usbHandle = checkNotNull(handlesByType[ConnectionType.USB]) + assertThat(usbHandle.state.connectedDevice?.serialNumber) .isEqualTo(SerialNumbers.physicalUsb) - assertThat(handlesByType[ConnectionType.WIFI]?.state?.connectedDevice?.serialNumber) + assertThat(usbHandle.state.properties.wearPairingId).isEqualTo(SerialNumbers.physicalUsb) + + val wifiHandle = checkNotNull(handlesByType[ConnectionType.WIFI]) + assertThat(wifiHandle.state.connectedDevice?.serialNumber) .isEqualTo(SerialNumbers.physicalWifi) + assertThat(wifiHandle.state.properties.wearPairingId).isEqualTo("X1BQ704RX2B") } } } diff --git a/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/LocalEmulatorProvisionerPluginTest.kt b/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/LocalEmulatorProvisionerPluginTest.kt index 9354a1e48c..d8021de9bc 100644 --- a/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/LocalEmulatorProvisionerPluginTest.kt +++ b/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/LocalEmulatorProvisionerPluginTest.kt @@ -39,7 +39,8 @@ class LocalEmulatorProvisionerPluginTest { val session = FakeAdbSession() val avdManager = FakeAvdManager() - val plugin = LocalEmulatorProvisionerPlugin(session, avdManager, Duration.ofMillis(100)) + val plugin = + LocalEmulatorProvisionerPlugin(session.scope, session, avdManager, Duration.ofMillis(100)) val provisioner = DeviceProvisioner.create(session, listOf(plugin)) @After @@ -206,6 +207,7 @@ class LocalEmulatorProvisionerPluginTest { assertThat(properties.abi).isEqualTo(ABI) assertThat(properties.avdName).startsWith("fake_avd_") assertThat(properties.displayName).startsWith("Fake Device") + assertThat(Path.of(properties.wearPairingId!!).parent).isEqualTo(Path.of("/tmp/fake_avds")) } companion object { diff --git a/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/testing/DeviceProvisionerRule.kt b/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/testing/DeviceProvisionerRule.kt new file mode 100644 index 0000000000..1435a8da88 --- /dev/null +++ b/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/testing/DeviceProvisionerRule.kt @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 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.sdklib.deviceprovisioner.testing + +import com.android.adblib.testingutils.FakeAdbServerProvider +import com.android.adblib.testingutils.FakeAdbServerProviderRule +import com.android.sdklib.deviceprovisioner.DeviceProvisioner + +/** A [FakeAdbServerProviderRule] that also provides a [DeviceProvisioner] */ +class DeviceProvisionerRule( + configure: (FakeAdbServerProvider.() -> FakeAdbServerProvider)? = null +) : FakeAdbServerProviderRule(configure) { + + lateinit var deviceProvisioner: DeviceProvisioner + private set + lateinit var deviceProvisionerPlugin: FakeAdbDeviceProvisionerPlugin + private set + + override fun before() { + super.before() + deviceProvisionerPlugin = FakeAdbDeviceProvisionerPlugin(adbSession.scope, fakeAdb) + deviceProvisioner = DeviceProvisioner.create(adbSession, listOf(deviceProvisionerPlugin)) + } +} diff --git a/device_validator/dvlib/src/main/java/com/android/dvlib/DeviceSchema.java b/device_validator/dvlib/src/main/java/com/android/dvlib/DeviceSchema.java index 03a43e3b6c..837d42bbbf 100644 --- a/device_validator/dvlib/src/main/java/com/android/dvlib/DeviceSchema.java +++ b/device_validator/dvlib/src/main/java/com/android/dvlib/DeviceSchema.java @@ -53,7 +53,7 @@ public class DeviceSchema { * The latest version of the device XML Schema. Valid version numbers are between 1 and this * number, included. */ - public static final int NS_LATEST_VERSION = 6; + public static final int NS_LATEST_VERSION = 7; /** The XML namespace of the latest device XML. */ public static final String NS_DEVICES_URI = getSchemaUri(NS_LATEST_VERSION); @@ -190,6 +190,17 @@ public class DeviceSchema { public static final String NODE_Y_FOLDED_OFFSET_3 = "y-folded-offset-3"; public static final String NODE_X_FOLDED_DIMENSION_3 = "x-folded-dimension-3"; public static final String NODE_Y_FOLDED_DIMENSION_3 = "y-folded-dimension-3"; + public static final String NODE_HINGE = "hinge"; + public static final String NODE_HINGE_AREAS = "areas"; + public static final String NODE_HINGE_COUNT = "count"; + public static final String NODE_HINGE_DEFAULTS = "defaults"; + public static final String NODE_HINGE_RANGES = "ranges"; + public static final String NODE_HINGE_SUB_TYPE = "sub-type"; + public static final String NODE_HINGE_TYPE = "type"; + public static final String NODE_HINGE_FOLD_AT_POSTURE = "fold-at-posture"; + public static final String NODE_HINGE_POSTURE_LIST = "posture-list"; + public static final String NODE_HINGE_ANGLES_POSTURE_DEFINITIONS = + "hinge-angles-posture-definitions"; public static final String NODE_CPU = "cpu"; diff --git a/device_validator/dvlib/src/main/resources/com/android/dvlib/devices-7.xsd b/device_validator/dvlib/src/main/resources/com/android/dvlib/devices-7.xsd new file mode 100644 index 0000000000..0182975482 --- /dev/null +++ b/device_validator/dvlib/src/main/resources/com/android/dvlib/devices-7.xsd @@ -0,0 +1,1209 @@ +<?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. + --> + +<xsd:schema + targetNamespace="http://schemas.android.com/sdk/devices/7" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:c="http://schemas.android.com/sdk/devices/7" + elementFormDefault="qualified" + version="1"> + + <!-- The devices element contains a collection of device definitions. + + History: + - v1 is used by the dvlib in Tools r20-22.. + + - v2 is used by the dvlib in Tools r23. + - It adds support for new ABIs arm64-v8a, x86_64 and mips64. + - v3 is used by the dvlib in Tools r25 + - It adds an indicator for Google Play Store compatibility + - v4 adds support for foldable devices + - v5 adds support for no sdcard devices + - v6 adds support for multiple foldable regions + + --> + <xsd:element name="devices" type="c:devicesType" /> + + <xsd:complexType name="devicesType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + The "devices" element is the root element of this schema. + + It must contain one or more "device" elements that each define the configurations + and states available for a given device. + </xsd:documentation> + </xsd:annotation> + <xsd:sequence> + <xsd:element name="device" maxOccurs="unbounded"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + A device element contains one hardware profile for a device, along with + 1 or more software profiles and 1 or more states. Each software profile + defines the supported software for a given API release, and each state + profile defines a different possible state of the device (screen in + portrait orientation, screen in landscape orientation with the keyboard + out, etc.) + </xsd:documentation> + </xsd:annotation> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="name" type= "xsd:token" /> + <xsd:element name="id" type= "xsd:token" minOccurs="0" /> + <xsd:element name="manufacturer" type= "xsd:token" /> + <xsd:element name="meta" type= "c:metaType" minOccurs="0" /> + <xsd:element name="playstore-enabled" + type="xsd:boolean" minOccurs="0" /> + <xsd:element name="hardware" type= "c:hardwareType" /> + <xsd:element name="software" type= "c:softwareType" + maxOccurs="unbounded" /> + <xsd:element name="state" type= "c:stateType" + maxOccurs="unbounded" /> + <xsd:element name="tag-id" type= "c:idType" minOccurs="0" /> + <xsd:element name="boot-props" type= "c:bootPropsType" minOccurs="0" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + + <xsd:simpleType name="idType"> + <xsd:annotation> + <xsd:documentation> + A tag string for a system image can only be a simple alphanumeric string. + </xsd:documentation> + </xsd:annotation> + <xsd:restriction base="xsd:token"> + <xsd:pattern value="[a-zA-Z0-9_-]+"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:complexType name="bootPropsType" > + <xsd:annotation> + <xsd:documentation> + List of boot properties. + </xsd:documentation> + </xsd:annotation> + <xsd:sequence minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="boot-prop"> + <xsd:complexType> + <xsd:all> + <xsd:element name="prop-name"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:pattern value="[^\n\r\t =]+"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="prop-value" type= "xsd:string" /> + </xsd:all> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + + <xsd:complexType name="hardwareType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + The hardwareType contains all of the hardware information for + a given device. This includes things like the GPU type, screen + size, mic presence, etc. + </xsd:documentation> + </xsd:annotation> + <xsd:sequence> + <xsd:element name="screen" type= "c:screenType" /> + <xsd:element name="hinge" type="c:hingeType" + minOccurs="0" /> + <xsd:element name="networking" type= "c:networkingType" /> + <xsd:element name="sensors" type= "c:sensorsType" /> + <xsd:element name="mic" type= "c:micType" /> + <xsd:element name="camera" type= "c:cameraType" + minOccurs="0" maxOccurs="unbounded" /> + <xsd:element name="keyboard" type= "c:keyboardType" /> + <xsd:element name="nav" type= "c:navType" /> + <xsd:element name="ram" type= "c:ramType" /> + <xsd:element name="buttons" type= "c:buttonsType" /> + <xsd:element name="internal-storage" type= "c:internalStorageType" /> + <xsd:element name="removable-storage" type= "c:removableStorageType" + minOccurs="0" /> + <xsd:element name="cpu" type= "c:cpuType" /> + <xsd:element name="gpu" type= "c:gpuType" /> + <xsd:element name="abi" type= "c:abiType" /> + <xsd:element name="dock" type= "c:dockType" /> + <xsd:element name="power-type" type= "c:powerType" /> + <xsd:element name="skin" minOccurs="0"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Path to a custom skin directory. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + + <xsd:complexType name="softwareType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + The softwareType contains all of the device's software + information for a given API version. This includes things like + live wallpaper support, OpenGL version, etc. + </xsd:documentation> + </xsd:annotation> + <xsd:sequence> + <xsd:element name="api-level"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies which API version(s) this this element is + defining. This can be in the form of a single number + or a range of low to high, separated with a dash and + with either limit missing. The default lower limit is + one, and the default upper limit is unbounded. + The following are valid: + 10 + 7-10 + -10 + 7- + - + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:pattern value="[\d]*-[\d]*|[\d]+" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="live-wallpaper-support" type="xsd:boolean"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies whether the device supports live wallpapers. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + + <xsd:element name="bluetooth-profiles"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies all of the available Bluetooth profiles. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:list> + <xsd:simpleType> + <xsd:restriction base="xsd:NMTOKEN"> + <xsd:enumeration value="A2DP" /> + <xsd:enumeration value="ATT" /> + <xsd:enumeration value="AVRCP" /> + <xsd:enumeration value="AVDTP" /> + <xsd:enumeration value="BIP" /> + <xsd:enumeration value="BPP" /> + <xsd:enumeration value="CIP" /> + <xsd:enumeration value="CTP" /> + <xsd:enumeration value="DIP" /> + <xsd:enumeration value="DUN" /> + <xsd:enumeration value="FAX" /> + <xsd:enumeration value="FTP" /> + <xsd:enumeration value="GAVDP" /> + <xsd:enumeration value="GAP" /> + <xsd:enumeration value="GATT" /> + <xsd:enumeration value="GOEP" /> + <xsd:enumeration value="HCRP" /> + <xsd:enumeration value="HDP" /> + <xsd:enumeration value="HFP" /> + <xsd:enumeration value="HID" /> + <xsd:enumeration value="HSP" /> + <xsd:enumeration value="ICP" /> + <xsd:enumeration value="LAP" /> + <xsd:enumeration value="MAP" /> + <xsd:enumeration value="OPP" /> + <xsd:enumeration value="PAN" /> + <xsd:enumeration value="PBA" /> + <xsd:enumeration value="PBAP" /> + <xsd:enumeration value="SPP" /> + <xsd:enumeration value="SDAP" /> + <xsd:enumeration value="SAP" /> + <xsd:enumeration value="SIM" /> + <xsd:enumeration value="rSAP" /> + <xsd:enumeration value="SYNCH" /> + <xsd:enumeration value="VDP" /> + <xsd:enumeration value="WAPB" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:list> + </xsd:simpleType> + </xsd:element> + + <xsd:element name="gl-version"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the OpenGL version supported for this release. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:decimal"> + <xsd:pattern value="[0-9]\.[0-9]" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + + <xsd:element name="gl-extensions"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies all of the supported OpenGL extensions for + this release. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:list itemType="xsd:NMTOKEN" /> + </xsd:simpleType> + </xsd:element> + <xsd:element name="status-bar" type="xsd:boolean"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies whether the device has a status bar in this + software configuration. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + + <xsd:complexType name="stateType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + The stateType contains the information for a given state of + of the device. States include things like portrait mode, + landscape with the keyboard exposed, etc. States can also + modify the hardware attributes of a device. For instance, if + sliding out the keyboard increased the available screen + real estate, you can define a new screenType to override the + default one defined in the device's hardwareType. + </xsd:documentation> + </xsd:annotation> + <xsd:sequence> + <xsd:element name="description" type="xsd:token"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + A description of the defined state. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + + <xsd:element name="screen-orientation"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Defines the orientation of the screen. Use square if + the device's screen has equal height and width, + otherwise use landscape or portrait. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="port" /> + <xsd:enumeration value="land" /> + <xsd:enumeration value="square" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + + <xsd:element name="keyboard-state"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Defines the state of the keyboard. If the device has no + keyboard use keysoft, otherwise use keysexposed or keyshidden. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="keyssoft" /> + <xsd:enumeration value="keyshidden" /> + <xsd:enumeration value="keysexposed" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="nav-state"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Defines the state of the primary non-touchscreen + navigation hardware on the devices. If the device + doesn't have non-touchscreen navigation hardware use + nonav, otherwise use navexposed or navhidden. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="nonav" /> + <xsd:enumeration value="navhidden" /> + <xsd:enumeration value="navexposed" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="screen" type="c:screenType" minOccurs="0" /> + <xsd:element name="networking" type="c:networkingType" + minOccurs="0" /> + <xsd:element name="sensors" type="c:sensorsType" minOccurs="0" /> + <xsd:element name="mic" type="c:micType" minOccurs="0" /> + <xsd:element name="camera" type="c:cameraType" + minOccurs="0" maxOccurs="unbounded" /> + <xsd:element name="keyboard" type="c:keyboardType" minOccurs="0" /> + <xsd:element name="nav" type="c:navType" minOccurs="0" /> + <xsd:element name="ram" type="c:ramType" minOccurs="0" /> + <xsd:element name="buttons" type="c:buttonsType" minOccurs="0" /> + <xsd:element name="internal-storage" type="c:internalStorageType" + minOccurs="0" /> + <xsd:element name="removable-storage" type="c:removableStorageType" + minOccurs="0" /> + <xsd:element name="cpu" type="c:cpuType" minOccurs="0" /> + <xsd:element name="gpu" type="c:gpuType" minOccurs="0" /> + <xsd:element name="abi" type="c:abiType" minOccurs="0" /> + <xsd:element name="dock" type="c:dockType" minOccurs="0" /> + <xsd:element name="power-type" type="c:powerType" + minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:token" /> + <xsd:attribute name="default" type="xsd:boolean" /> + </xsd:complexType> + + <xsd:complexType name="metaType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Details where more device information can be found, such as + icons and frame images. + </xsd:documentation> + </xsd:annotation> + <xsd:sequence> + <xsd:element name="icons" minOccurs="0"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Contains the relative paths to the icon files for this + device. + </xsd:documentation> + </xsd:annotation> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="sixty-four" type="xsd:normalizedString"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Relative path for the 64x64 icon. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="sixteen" type="xsd:normalizedString" + minOccurs="0"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Relative path for the 16x16 icon. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="frame" minOccurs="0"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Contains information about the frame for the device. + </xsd:documentation> + </xsd:annotation> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="path" + type="xsd:normalizedString"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + The relative path to the emulator frame for + the device. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="portrait-x-offset" + type="xsd:nonNegativeInteger"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + The offset for the frame in the x direction, + in portrait mode. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="portrait-y-offset" + type="xsd:nonNegativeInteger"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + The offset for the frame in the y direction, + in portrait mode. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="landscape-x-offset" + type="xsd:nonNegativeInteger"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + The offset for the frame in the x direction, + in landscape mode. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="landscape-y-offset" + type="xsd:nonNegativeInteger"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + The offset for the frame in the y direction, + in landscape mode. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + + <xsd:complexType name="screenType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Contains the specifications for the device's screen. + </xsd:documentation> + </xsd:annotation> + <xsd:sequence> + <xsd:element name="screen-size"> + <xsd:simpleType> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the class of the screen. + </xsd:documentation> + </xsd:annotation> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="small" /> + <xsd:enumeration value="normal" /> + <xsd:enumeration value="large" /> + <xsd:enumeration value="xlarge" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + + <xsd:element name="diagonal-length"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the diagonal length of the screen in inches. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:decimal"> + <!-- Negative lengths are not valid --> + <xsd:minInclusive value="0" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + + <xsd:element name="pixel-density"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the screen density of the device. The + medium density of traditional HVGA screens (mdpi) + is defined to be approximately 160dpi; low density + (ldpi) is 120, and high density (hdpi) is 240. There + is thus a 4:3 scaling factor between each density, + so a 9x9 bitmap in ldpi would be 12x12 in mdpi and + 16x16 in hdpi. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="ldpi" /> + <xsd:enumeration value="mdpi" /> + <xsd:enumeration value="tvdpi" /> + <xsd:enumeration value="hdpi" /> + <xsd:enumeration value="140dpi" /> + <xsd:enumeration value="180dpi" /> + <xsd:enumeration value="200dpi" /> + <xsd:enumeration value="260dpi" /> + <xsd:enumeration value="280dpi" /> + <xsd:enumeration value="300dpi" /> + <xsd:enumeration value="xhdpi" /> + <xsd:enumeration value="340dpi" /> + <xsd:enumeration value="360dpi" /> + <xsd:enumeration value="400dpi" /> + <xsd:enumeration value="420dpi" /> + <xsd:enumeration value="440dpi" /> + <xsd:enumeration value="xxhdpi" /> + <xsd:enumeration value="560dpi" /> + <xsd:enumeration value="xxxhdpi" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + + <xsd:element name="screen-ratio"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies whether the configuration is for a taller or + wider than traditional screen. This is based purely on + the aspect ratio of the screen: QVGA, HVGA, and VGA are + notlong; WQVGA, WVGA, FWVGA are long. Note that long may + mean either wide or tall, depending on the current + orientation. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="notlong" /> + <xsd:enumeration value="long" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + + <xsd:element name="dimensions"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the device screen resolution in pixels. + </xsd:documentation> + </xsd:annotation> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="x-dimension"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the x-dimension's resolution in + pixels. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:positiveInteger" /> + </xsd:simpleType> + </xsd:element> + <xsd:element name="y-dimension"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the y-dimension's resolution in + pixels. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:positiveInteger" /> + </xsd:simpleType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:element name="xdpi"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the actual density in X of the device screen. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:decimal"> + <!-- Negative DPIs are not valid --> + <xsd:minInclusive value="0" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + + <xsd:element name="ydpi"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the actual density in Y of the device screen. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:decimal"> + <!-- Negative DPIs are not valid --> + <xsd:minInclusive value="0" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + + <xsd:element name="touch"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the touch properties of the device. + </xsd:documentation> + </xsd:annotation> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="multitouch"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the multitouch capabilities of the + device. This can be none if multitouch is + not supported, basic if the device can track + only basic two finger gestures, distinct if + the device can track two or more fingers + simultaneously, or jazz-hands if the device + can track 5 or more fingers simultaneously. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none" /> + <xsd:enumeration value="basic" /> + <xsd:enumeration value="distinct" /> + <xsd:enumeration value="jazz-hands" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + + <xsd:element name="mechanism"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the mechanism the device was + created for. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="notouch" /> + <xsd:enumeration value="stylus" /> + <xsd:enumeration value="finger" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + + <xsd:element name="screen-type"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the type of touch screen on the + device. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="notouch" /> + <xsd:enumeration value="capacitive" /> + <xsd:enumeration value="resistive" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + + <xsd:element name="foldable-region" minOccurs="0" > + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the region of the device screen + that is active when the device is folded. + </xsd:documentation> + </xsd:annotation> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="x-folded-offset"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the start of the foldable + region in the x-dimension, in pixels. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger" /> + </xsd:simpleType> + </xsd:element> + <xsd:element name="y-folded-offset"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the start of the foldable + region in the y-dimension, in pixels. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger" /> + </xsd:simpleType> + </xsd:element> + <xsd:element name="x-folded-dimension"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the number of pixels in the x-dimension + that are available when folded. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger" /> + </xsd:simpleType> + </xsd:element> + <xsd:element name="y-folded-dimension"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the number of pixels in the y-dimension + that are available when folded. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger" /> + </xsd:simpleType> + </xsd:element> + <xsd:element name="x-folded-offset-2" minOccurs="0"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the start of the second foldable + region in the x-dimension, in pixels. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger" /> + </xsd:simpleType> + </xsd:element> + <xsd:element name="y-folded-offset-2" minOccurs="0"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the start of the second foldable + region in the y-dimension, in pixels. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger" /> + </xsd:simpleType> + </xsd:element> + <xsd:element name="x-folded-dimension-2" minOccurs="0"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the number of pixels in the x-dimension + that are available when folded. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger" /> + </xsd:simpleType> + </xsd:element> + <xsd:element name="y-folded-dimension-2" minOccurs="0"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the number of pixels in the y-dimension + that are available when folded. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger" /> + </xsd:simpleType> + </xsd:element> + <xsd:element name="x-folded-offset-3" minOccurs="0"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the start of the third foldable + region in the x-dimension, in pixels. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger" /> + </xsd:simpleType> + </xsd:element> + <xsd:element name="y-folded-offset-3" minOccurs="0"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the start of the third foldable + region in the y-dimension, in pixels. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger" /> + </xsd:simpleType> + </xsd:element> + <xsd:element name="x-folded-dimension-3" minOccurs="0"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the number of pixels in the x-dimension + that are available when folded. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger" /> + </xsd:simpleType> + </xsd:element> + <xsd:element name="y-folded-dimension-3" minOccurs="0"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the number of pixels in the y-dimension + that are available when folded. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger" /> + </xsd:simpleType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + + <xsd:complexType name="hingeType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Contains the specifications for the hinge in a foldable + device. + </xsd:documentation> + </xsd:annotation> + <xsd:sequence> + <xsd:element name="count" type="xsd:nonNegativeInteger"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies number of hinges + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="type" type="xsd:nonNegativeInteger"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the type of the hinge. The value + must match the type definition in the + emulator. 0: horizontal hinge; 1: vertical + hinge; 2: horizontal roll + (for rollable device); 3: vertical roll + (for rollable device). + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="sub-type" type="xsd:nonNegativeInteger"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the sub-type of the hinge. Currently + it doesn't do anything. 0: fold; 1: hinge. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="ranges" type="xsd:normalizedString"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the folding range, in the format of + min-max. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="defaults" type="xsd:integer"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the default folding angle. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="areas" type="xsd:normalizedString"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the area of the hinge, in the format + of xoffset-yoffset-width-height. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="fold-at-posture" type="xsd:nonNegativeInteger" + minOccurs="0"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the default folded posture. The value + must match the definition in the emulator. + 0: unknown; 1: closed; 2: half-opened; + 3: opened; 4: flipped; 5: tent. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="posture-list" type="xsd:normalizedString"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies a list of postures, separated by + comma. The value of each posture must match + the definition in the emulator. + 0: unknown; 1: closed; 2: half-opened; + 3: opened; 4: flipped; 5: tent. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="hinge-angles-posture-definitions" type="xsd:normalizedString"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies hinge angle ranges that correspond + to each posture. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + + <xsd:simpleType name="networkingType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the available networking hardware. + </xsd:documentation> + </xsd:annotation> + <xsd:list> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="NFC" /> + <xsd:enumeration value="Bluetooth" /> + <xsd:enumeration value="Wifi" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:list> + </xsd:simpleType> + + <xsd:simpleType name="sensorsType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the available sensors. + </xsd:documentation> + </xsd:annotation> + <xsd:list> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="Accelerometer" /> + <xsd:enumeration value="Barometer" /> + <xsd:enumeration value="Compass" /> + <xsd:enumeration value="GPS" /> + <xsd:enumeration value="Gyroscope" /> + <xsd:enumeration value="LightSensor" /> + <xsd:enumeration value="ProximitySensor" /> + <xsd:enumeration value="StepCounter" /> + <xsd:enumeration value="StepDetector" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:list> + </xsd:simpleType> + + <xsd:simpleType name="micType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies whether the device has a mic or not. + </xsd:documentation> + </xsd:annotation> + <xsd:restriction base="xsd:boolean" /> + </xsd:simpleType> + + <xsd:complexType name="cameraType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the attributes of the camera. + </xsd:documentation> + </xsd:annotation> + <xsd:sequence> + <xsd:element name="location"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the location of the camera. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="front" /> + <xsd:enumeration value="back" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + + <xsd:element name="autofocus" type="xsd:boolean"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies whether the camera can autofocus + </xsd:documentation> + </xsd:annotation> + </xsd:element> + + <xsd:element name="flash" type="xsd:boolean"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies whether the camera has flash. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + + <xsd:simpleType name="keyboardType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the type of keyboard on the device. + </xsd:documentation> + </xsd:annotation> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="qwerty" /> + <xsd:enumeration value="12key" /> + <xsd:enumeration value="nokeys" /> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="navType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the primary non-touchscreen navigation + hardware on the device. + </xsd:documentation> + </xsd:annotation> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="dpad" /> + <xsd:enumeration value="trackball" /> + <xsd:enumeration value="wheel" /> + <xsd:enumeration value="nonav" /> + </xsd:restriction> + </xsd:simpleType> + + <xsd:complexType name="ramType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the amount of RAM on the device in the unit provided. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleContent> + <xsd:extension base="xsd:positiveInteger"> + <xsd:attribute name="unit" type="c:storageUnitType" use="required" /> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + + <xsd:simpleType name="buttonsType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies whether the device has physical (hard) buttons + (Home, Search, etc.), or uses soft buttons. + </xsd:documentation> + </xsd:annotation> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="hard" /> + <xsd:enumeration value="soft" /> + </xsd:restriction> + </xsd:simpleType> + + <xsd:complexType name="internalStorageType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + A list specifying the sizes of internal storage in + the device, in the storage size unit provided. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleContent> + <xsd:extension base="c:storageListType"> + <xsd:attribute name="unit" type="c:storageUnitType" + use="required" /> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + + <xsd:complexType name="removableStorageType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the range of available removable storage sizes + in the unit provided. A positive value indicates the device is + available with that storage size included while a zero value + indicates an empty storage slot. + </xsd:documentation> + </xsd:annotation> + <xsd:simpleContent> + <xsd:extension base="c:storageListType"> + <xsd:attribute name="unit" type="c:storageUnitType" + use="required" /> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + + <xsd:simpleType name="storageListType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Defines a list for storage configurations such as internal or + removable storage. A positive value indicates the device + has a storage unit of that size, while a zero value indicates + there is an empty location for a storage unit (such as an empty + SD card slot). + </xsd:documentation> + </xsd:annotation> + <xsd:list> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger" /> + </xsd:simpleType> + </xsd:list> + </xsd:simpleType> + <xsd:simpleType name="gpuType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the device's GPU. + </xsd:documentation> + </xsd:annotation> + <xsd:restriction base="xsd:token"> + <xsd:minLength value="1" /> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="cpuType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the device's CPU. + </xsd:documentation> + </xsd:annotation> + <xsd:restriction base="xsd:token"> + <xsd:minLength value="1" /> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="abiType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies which ABIs the device conforms to. + </xsd:documentation> + </xsd:annotation> + <xsd:list> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="armeabi" /> + <xsd:enumeration value="armeabi-v7a" /> + <xsd:enumeration value="arm64-v8a" /> + <xsd:enumeration value="x86" /> + <xsd:enumeration value="x86_64" /> + <xsd:enumeration value="mips" /> + <!-- TODO double-check this is appropriate value for mips64 --> + <xsd:enumeration value="mips64" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:list> + </xsd:simpleType> + + <xsd:simpleType name="dockType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the official docks available for the device. + </xsd:documentation> + </xsd:annotation> + <xsd:list> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="desk" /> + <xsd:enumeration value="television" /> + <xsd:enumeration value="car" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:list> + </xsd:simpleType> + + <xsd:simpleType name="powerType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies whether the device is plugged in. + </xsd:documentation> + </xsd:annotation> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="plugged-in" /> + <xsd:enumeration value="battery" /> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="storageUnitType"> + <xsd:annotation> + <xsd:documentation xml:lang="en"> + Specifies the unit of storage. This can be MiB, GiB, etc. + </xsd:documentation> + </xsd:annotation> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="B" /> + <xsd:enumeration value="KiB" /> + <xsd:enumeration value="MiB" /> + <xsd:enumeration value="GiB" /> + <xsd:enumeration value="TiB" /> + </xsd:restriction> + </xsd:simpleType> + +</xsd:schema> diff --git a/dynamic-layout-inspector/agent/appinspection/fake-android/src/android/content/res/Configuration.java b/dynamic-layout-inspector/agent/appinspection/fake-android/src/android/content/res/Configuration.java index 5773a48001..8c4513cf55 100644 --- a/dynamic-layout-inspector/agent/appinspection/fake-android/src/android/content/res/Configuration.java +++ b/dynamic-layout-inspector/agent/appinspection/fake-android/src/android/content/res/Configuration.java @@ -38,6 +38,7 @@ public final class Configuration { public int orientation = 0; public int screenWidthDp = 0; public int screenHeightDp = 0; + public int grammaticalGender = 0; public final LocaleList getLocales() { return mLocales; diff --git a/dynamic-layout-inspector/agent/appinspection/proto/view_layout_inspection.proto b/dynamic-layout-inspector/agent/appinspection/proto/view_layout_inspection.proto index 321cf7e5c9..fb6ee0940d 100644 --- a/dynamic-layout-inspector/agent/appinspection/proto/view_layout_inspection.proto +++ b/dynamic-layout-inspector/agent/appinspection/proto/view_layout_inspection.proto @@ -136,6 +136,7 @@ message Configuration { int32 orientation = 16; int32 screen_width_dp = 17; // excludes window decor int32 screen_height_dp = 18; // excludes window decor + int32 grammatical_gender = 19; } // Event set when the angle, orientation, or posture of a foldable device changes. diff --git a/dynamic-layout-inspector/agent/appinspection/src/main/com/android/tools/agent/appinspection/proto/resource/ConfigurationExtensions.kt b/dynamic-layout-inspector/agent/appinspection/src/main/com/android/tools/agent/appinspection/proto/resource/ConfigurationExtensions.kt index 0433b599bd..8adb090726 100644 --- a/dynamic-layout-inspector/agent/appinspection/src/main/com/android/tools/agent/appinspection/proto/resource/ConfigurationExtensions.kt +++ b/dynamic-layout-inspector/agent/appinspection/src/main/com/android/tools/agent/appinspection/proto/resource/ConfigurationExtensions.kt @@ -20,6 +20,7 @@ import com.android.tools.agent.appinspection.proto.StringTable import com.android.tools.agent.appinspection.proto.convert import com.android.tools.idea.layoutinspector.view.inspection.LayoutInspectorViewProtocol.Configuration import android.content.res.Configuration as AndroidResConfiguration +import android.os.Build fun AndroidResConfiguration.convert(stringTable: StringTable): Configuration = Configuration.newBuilder().apply(this, stringTable).build() @@ -49,5 +50,8 @@ private fun Configuration.Builder.apply( if (!config.locales.isEmpty) { locale = config.locales[0].convert(stringTable) } + if (Build.VERSION.SDK_INT >= 34) { + grammaticalGender = config.grammaticalGender + } return this } diff --git a/dynamic-layout-inspector/external/libpng.BUILD b/dynamic-layout-inspector/external/libpng.BUILD index fe92d09c80..c521fa2873 100644 --- a/dynamic-layout-inspector/external/libpng.BUILD +++ b/dynamic-layout-inspector/external/libpng.BUILD @@ -12,28 +12,16 @@ config_setting( cc_library( name = "libpng", - srcs = [ - "intel/filter_sse2_intrinsics.c", - "intel/intel_init.c", - "png.c", - "pngerror.c", - "pngget.c", - "pngmem.c", - "pngpread.c", - "pngread.c", - "pngrio.c", - "pngrtran.c", - "pngrutil.c", - "pngset.c", - "pngtrans.c", - "pngwio.c", - "pngwrite.c", - "pngwtran.c", - "pngwutil.c", - ] + glob( - ["*.h"], + srcs = glob( + [ + "*.c", + "*.h", + ], exclude = ["png.h"], - ), + ) + select({ + "@platforms//cpu:arm64": glob(["arm/*.c"]), + "@platforms//cpu:x86_64": glob(["intel/*.c"]), + }), hdrs = ["png.h"], copts = select({ "windows": [ diff --git a/dynamic-layout-inspector/external/skia-user-config/BUILD.bazel b/dynamic-layout-inspector/external/skia-user-config/BUILD.bazel new file mode 100644 index 0000000000..8be341df1d --- /dev/null +++ b/dynamic-layout-inspector/external/skia-user-config/BUILD.bazel @@ -0,0 +1,10 @@ +cc_library( + name = "user_config", + hdrs = [ + "SkUserConfig.h", + ], + defines = [ + "SK_USE_BAZEL_CONFIG_HEADER", + ], + visibility = ["//visibility:public"], +) diff --git a/dynamic-layout-inspector/external/skia-extra/SkUserConfig.h b/dynamic-layout-inspector/external/skia-user-config/SkUserConfig.h index 217c4fe716..217c4fe716 100644 --- a/dynamic-layout-inspector/external/skia-extra/SkUserConfig.h +++ b/dynamic-layout-inspector/external/skia-user-config/SkUserConfig.h diff --git a/dynamic-layout-inspector/external/skia-user-config/WORKSPACE b/dynamic-layout-inspector/external/skia-user-config/WORKSPACE new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/dynamic-layout-inspector/external/skia-user-config/WORKSPACE diff --git a/dynamic-layout-inspector/external/skia-user-config/copts.bzl b/dynamic-layout-inspector/external/skia-user-config/copts.bzl new file mode 100644 index 0000000000..0fafedfeb0 --- /dev/null +++ b/dynamic-layout-inspector/external/skia-user-config/copts.bzl @@ -0,0 +1,8 @@ +""" +For now: Use the copts from skia. +""" + +load("@skia_repo//include/config:copts.bzl", _DEFAULT_COPTS = "DEFAULT_COPTS", _DEFAULT_OBJC_COPTS = "DEFAULT_OBJC_COPTS") + +DEFAULT_COPTS = _DEFAULT_COPTS +DEFAULT_OBJC_COPTS = _DEFAULT_OBJC_COPTS diff --git a/dynamic-layout-inspector/external/skia-user-config/linkopts.bzl b/dynamic-layout-inspector/external/skia-user-config/linkopts.bzl new file mode 100644 index 0000000000..35ec4315b2 --- /dev/null +++ b/dynamic-layout-inspector/external/skia-user-config/linkopts.bzl @@ -0,0 +1,7 @@ +""" +For now: Use the linkopts from skia. +""" + +load("@skia_repo//include/config:linkopts.bzl", _DEFAULT_LINKOPTS = "DEFAULT_LINKOPTS") + +DEFAULT_LINKOPTS = _DEFAULT_LINKOPTS diff --git a/dynamic-layout-inspector/skia/files/source.properties b/dynamic-layout-inspector/skia/files/source.properties index 8dad9180d4..5a6ae7bdc0 100644 --- a/dynamic-layout-inspector/skia/files/source.properties +++ b/dynamic-layout-inspector/skia/files/source.properties @@ -1,3 +1,3 @@ -Pkg.Revision=2 +Pkg.Revision=3 Pkg.Path=skiaparser;3 Pkg.Desc=Layout Inspector image server for API 31-34 diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/ClientState.java b/fakeadbserver/src/main/java/com/android/fakeadbserver/ClientState.java deleted file mode 100644 index 1e425a0165..0000000000 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/ClientState.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2017 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.fakeadbserver; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import java.net.Socket; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; - -public class ClientState extends ProcessState { - - private final int mUid; - - @NonNull private final String mProcessName; - - @NonNull - private final String mPackageName; - - // Whether this client is waiting for a debugger connection or not - private boolean mWaiting; - - private final ClientViewsState mViewsState = new ClientViewsState(); - - private final ProfilerState mProfilerState = new ProfilerState(); - - /** - * Set of DDMS features for this process. - * - * <p>See <a - * href="https://cs.android.com/android/platform/superproject/+/android13-release:frameworks/base/core/java/android/ddm/DdmHandleHello.java;l=107">HandleFEAT - * source code</a> - */ - private final Set<String> mFeatures = new HashSet<>(); - - /** - * See <a - * href="https://cs.android.com/android/platform/superproject/+/android13-release:art/runtime/native/dalvik_system_VMDebug.cc;l=56">List - * of VM features</a> - */ - private static final String[] mBuiltinVMFeatures = { - "method-trace-profiling", - "method-trace-profiling-streaming", - "method-sample-profiling", - "hprof-heap-dump", - "hprof-heap-dump-streaming" - }; - - /** - * See <a - * href="https://cs.android.com/android/platform/superproject/+/android13-release:frameworks/base/core/java/android/ddm/DdmHandleHello.java;drc=4794e479f4b485be2680e83993e3cf93f0f42d03;l=44">Framework - * features</a> - */ - private static final String[] mBuiltinFrameworkFeatures = { - "opengl-tracing", "view-hierarchy", - }; - - @Nullable private Socket jdwpSocket; - - private boolean allocationTrackerEnabled; - - private String allocationTrackerDetails = ""; - - private final AtomicInteger hgpcRequestsCount = new AtomicInteger(); - - private final AtomicInteger nextDdmsCommandId = new AtomicInteger(0x7000_0000); - - ClientState( - int pid, - int uid, - @NonNull String processName, - @NonNull String packageName, - boolean isWaiting) { - super(pid); - mUid = uid; - mProcessName = processName; - mPackageName = packageName; - mWaiting = isWaiting; - mFeatures.addAll(Arrays.asList(mBuiltinVMFeatures)); - mFeatures.addAll(Arrays.asList(mBuiltinFrameworkFeatures)); - } - - @Override - public boolean getDebuggable() { - return true; - } - - @Override - public boolean getProfileable() { - return false; - } - - public int getUid() { - return mUid; - } - - @NonNull - public String getProcessName() { - return mProcessName; - } - - @NonNull - public String getPackageName() { - return mPackageName; - } - - public boolean getIsWaiting() { - return mWaiting; - } - - @NonNull - public ClientViewsState getViewsState() { - return mViewsState; - } - - @NonNull - public ProfilerState getProfilerState() { - return mProfilerState; - } - - public synchronized boolean startJdwpSession(@NonNull Socket socket) { - if (this.jdwpSocket != null) { - return false; - } - this.jdwpSocket = socket; - return true; - } - - public synchronized void stopJdwpSession() { - if (this.jdwpSocket != null) { - try { - this.jdwpSocket.shutdownOutput(); - Thread.sleep(10); // So that FIN is received by peer - this.jdwpSocket.close(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - this.jdwpSocket = null; - } - - public int nextDdmsCommandId() { - return nextDdmsCommandId.incrementAndGet(); - } - - public synchronized void clearFeatures() { - mFeatures.clear(); - } - - public synchronized void addFeature(@NonNull String value) { - mFeatures.add(value); - } - - public synchronized void removeFeature(@NonNull String value) { - mFeatures.remove(value); - } - - @NonNull - public synchronized Set<String> getFeatures() { - return new HashSet<>(mFeatures); - } - - public void requestHgpc() { - hgpcRequestsCount.incrementAndGet(); - } - - public int getHgpcRequestsCount() { - return hgpcRequestsCount.get(); - } - - public void setAllocationTrackerEnabled(boolean enabled) { - allocationTrackerEnabled = enabled; - } - - public boolean isAllocationTrackerEnabled() { - return allocationTrackerEnabled; - } - - public String getAllocationTrackerDetails() { - return allocationTrackerDetails; - } - - public void setAllocationTrackerDetails(String details) { - this.allocationTrackerDetails = details; - } -} diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/ClientState.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/ClientState.kt new file mode 100644 index 0000000000..33af25979b --- /dev/null +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/ClientState.kt @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2017 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.fakeadbserver + +import java.net.Socket +import java.util.Arrays +import java.util.concurrent.atomic.AtomicInteger + +class ClientState internal constructor( + pid: Int, + val uid: Int, + val processName: String, + val packageName: String, // Whether this client is waiting for a debugger connection or not + val isWaiting: Boolean +) : ProcessState(pid) { + + val viewsState = ClientViewsState() + val profilerState = ProfilerState() + + /** + * Set of DDMS features for this process. + * + * See [HandleFEAT source code](https://cs.android.com/android/platform/superproject/+/android13-release:frameworks/base/core/java/android/ddm/DdmHandleHello.java;l=107) + */ + private val mFeatures: MutableSet<String> = HashSet() + private var jdwpSocket: Socket? = null + var isAllocationTrackerEnabled = false + var allocationTrackerDetails = "" + private val hgpcRequestsCount = AtomicInteger() + private val nextDdmsCommandId = AtomicInteger(0x70000000) + + init { + mFeatures.addAll(Arrays.asList(*mBuiltinVMFeatures)) + mFeatures.addAll(Arrays.asList(*mBuiltinFrameworkFeatures)) + } + + override val debuggable: Boolean + get() = true + override val profileable: Boolean + get() = false + + @Synchronized + fun startJdwpSession(socket: Socket): Boolean { + if (jdwpSocket != null) { + return false + } + jdwpSocket = socket + return true + } + + @Synchronized + fun stopJdwpSession() { + if (jdwpSocket != null) { + try { + jdwpSocket!!.shutdownOutput() + Thread.sleep(10) // So that FIN is received by peer + jdwpSocket!!.close() + } catch (e: Exception) { + throw RuntimeException(e) + } + } + jdwpSocket = null + } + + fun nextDdmsCommandId(): Int { + return nextDdmsCommandId.incrementAndGet() + } + + @Synchronized + fun clearFeatures() { + mFeatures.clear() + } + + @Synchronized + fun addFeature(value: String) { + mFeatures.add(value) + } + + @Synchronized + fun removeFeature(value: String) { + mFeatures.remove(value) + } + + @get:Synchronized + val features: Set<String> + get() = HashSet(mFeatures) + + fun requestHgpc() { + hgpcRequestsCount.incrementAndGet() + } + + fun getHgpcRequestsCount(): Int { + return hgpcRequestsCount.get() + } + + companion object { + + /** + * See [List of VM features](https://cs.android.com/android/platform/superproject/+/android13-release:art/runtime/native/dalvik_system_VMDebug.cc;l=56) + */ + private val mBuiltinVMFeatures = arrayOf( + "method-trace-profiling", + "method-trace-profiling-streaming", + "method-sample-profiling", + "hprof-heap-dump", + "hprof-heap-dump-streaming" + ) + + /** + * See [Framework features](https://cs.android.com/android/platform/superproject/+/android13-release:frameworks/base/core/java/android/ddm/DdmHandleHello.java;drc=4794e479f4b485be2680e83993e3cf93f0f42d03;l=44) + */ + private val mBuiltinFrameworkFeatures = arrayOf( + "opengl-tracing", "view-hierarchy" + ) + } +} diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/DeviceState.java b/fakeadbserver/src/main/java/com/android/fakeadbserver/DeviceState.java deleted file mode 100644 index ea5fd48489..0000000000 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/DeviceState.java +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Copyright (C) 2017 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.fakeadbserver; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.fakeadbserver.services.Service; -import com.android.fakeadbserver.services.ServiceManager; -import com.android.fakeadbserver.statechangehubs.ClientStateChangeHandlerFactory; -import com.android.fakeadbserver.statechangehubs.ClientStateChangeHub; -import com.android.fakeadbserver.statechangehubs.StateChangeQueue; -import com.google.common.collect.ImmutableMap; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.Vector; -import java.util.stream.Collectors; -import org.jetbrains.annotations.NotNull; - -public class DeviceState { - - private final ClientStateChangeHub mClientStateChangeHub = new ClientStateChangeHub(); - - private final Map<String, DeviceFileState> mFiles = new HashMap<>(); - - private final List<String> mLogcatMessages = new ArrayList<>(); - - /** PID -> {@link ProcessState} */ - private final Map<Integer, ProcessState> mProcessStates = new HashMap<>(); - - private final Map<Integer, PortForwarder> mPortForwarders = new HashMap<>(); - - private final Map<Integer, PortForwarder> mReversePortForwarders = new HashMap<>(); - - private final FakeAdbServer mServer; - - private final HostConnectionType mHostConnectionType; - - private final Set<String> mFeatures; - - private final int myTransportId; - - private final String mDeviceId; - - private final String mManufacturer; - - private final String mModel; - - private final String mBuildVersionRelease; - - private final String mBuildVersionSdk; - - private final String mCpuAbi; - - private final Map<String, String> mProperties; - - private DeviceStatus mDeviceStatus; - - private final ServiceManager mServiceManager; - - // Keep track of all PM commands invocation - private final Vector<String> mPmLogs = new Vector<>(); - - // Keep track of all cmd commands invocation - private final Vector<String> mCmdLogs = new Vector<>(); - - // Keep track of all ABB/ABB_EXEC commands invocation - private final Vector<String> mAbbLogs = new Vector<>(); - - DeviceState( - @NonNull FakeAdbServer server, - @NonNull String deviceId, - @NonNull String manufacturer, - @NonNull String model, - @NonNull String release, - @NonNull String sdk, - @NonNull String cpuAbi, - @NonNull Map<String, String> properties, - @NonNull HostConnectionType hostConnectionType, - int transportId) { - mServer = server; - mDeviceId = deviceId; - mManufacturer = manufacturer; - mModel = model; - mBuildVersionRelease = release; - mBuildVersionSdk = sdk; - mCpuAbi = cpuAbi; - mFeatures = initFeatures(sdk); - mProperties = - combinedProperties(deviceId, manufacturer, model, release, sdk, cpuAbi, properties); - mHostConnectionType = hostConnectionType; - myTransportId = transportId; - mDeviceStatus = DeviceStatus.OFFLINE; - mServiceManager = new ServiceManager(); - } - - DeviceState(@NonNull FakeAdbServer server, int transportId, @NonNull DeviceStateConfig config) { - this( - server, - config.getSerialNumber(), - config.getManufacturer(), - config.getModel(), - config.getBuildVersionRelease(), - config.getBuildVersionSdk(), - config.getCpuAbi(), - config.getProperties(), - config.getHostConnectionType(), - transportId); - config.getFiles().forEach(fileState -> mFiles.put(fileState.getPath(), fileState)); - mLogcatMessages.addAll(config.getLogcatMessages()); - mDeviceStatus = config.getDeviceStatus(); - config.getProcesses() - .forEach(clientState -> mProcessStates.put(clientState.getPid(), clientState)); - } - - public void stop() { - mClientStateChangeHub.stop(); - } - - @NonNull - public String getDeviceId() { - return mDeviceId; - } - - @NonNull - public String getCpuAbi() { - return mCpuAbi; - } - - @NonNull - public String getManufacturer() { - return mManufacturer; - } - - @NonNull - public String getModel() { - return mModel; - } - - @NonNull - public String getBuildVersionRelease() { - return mBuildVersionRelease; - } - - @NonNull - public String getBuildVersionSdk() { - return mBuildVersionSdk; - } - - public int getApiLevel() { - try { - return Integer.parseInt(mBuildVersionSdk); - } catch (NumberFormatException e) { - return 1; - } - } - - public Map<String, String> getProperties() { - return mProperties; - } - - @NonNull - public DeviceStatus getDeviceStatus() { - return mDeviceStatus; - } - - public int getTransportId() { - return myTransportId; - } - - public void setDeviceStatus(@NonNull DeviceStatus status) { - mDeviceStatus = status; - mServer.getDeviceChangeHub().deviceStatusChanged(this, status); - } - - @NonNull - public ClientStateChangeHub getClientChangeHub() { - return mClientStateChangeHub; - } - - public void addLogcatMessage(@NonNull String message) { - synchronized (mLogcatMessages) { - mLogcatMessages.add(message); - mClientStateChangeHub.logcatMessageAdded(message); - } - } - - @Nullable - public LogcatChangeHandlerSubscriptionResult subscribeLogcatChangeHandler( - @NonNull ClientStateChangeHandlerFactory handlerFactory) { - synchronized (mLogcatMessages) { - StateChangeQueue queue = getClientChangeHub().subscribe(handlerFactory); - if (queue == null) { - return null; - } - - return new LogcatChangeHandlerSubscriptionResult( - queue, new ArrayList<>(mLogcatMessages)); - } - } - - public void createFile(@NonNull DeviceFileState file) { - synchronized (mFiles) { - mFiles.put(file.getPath(), file); - } - } - - @Nullable - public DeviceFileState getFile(@NonNull String filepath) { - synchronized (mFiles) { - return mFiles.get(filepath); - } - } - - public void deleteFile(@NonNull String filepath) { - synchronized (mFiles) { - mFiles.remove(filepath); - } - } - - @NonNull - public ClientState startClient( - int pid, int uid, @NonNull String packageName, boolean isWaiting) { - return startClient(pid, uid, packageName, packageName, isWaiting); - } - - @NonNull - public ClientState startClient( - int pid, - int uid, - @NonNull String processName, - @NonNull String packageName, - boolean isWaiting) { - synchronized (mProcessStates) { - ClientState clientState = - new ClientState(pid, uid, processName, packageName, isWaiting); - mProcessStates.put(pid, clientState); - mClientStateChangeHub.clientListChanged(); - mClientStateChangeHub.appProcessListChanged(); - return clientState; - } - } - - public void stopClient(int pid) { - synchronized (mProcessStates) { - ProcessState processState = mProcessStates.remove(pid); - if (processState instanceof ClientState) { - mClientStateChangeHub.clientListChanged(); - mClientStateChangeHub.appProcessListChanged(); - ((ClientState) processState).stopJdwpSession(); - } - } - } - - @Nullable - public ClientState getClient(int pid) { - synchronized (mProcessStates) { - ProcessState processState = mProcessStates.get(pid); - if (processState instanceof ClientState) { - return (ClientState) processState; - } else { - return null; - } - } - } - - @NonNull - public ProfileableProcessState startProfileableProcess( - int pid, @NonNull String architecture, @NonNull String commandLine) { - synchronized (mProcessStates) { - ProfileableProcessState process = - new ProfileableProcessState(pid, architecture, commandLine); - mProcessStates.put(pid, process); - mClientStateChangeHub.appProcessListChanged(); - return process; - } - } - - public void stopProfileableProcess(int pid) { - synchronized (mProcessStates) { - ProcessState process = mProcessStates.remove(pid); - if (process instanceof ProfileableProcessState) { - mClientStateChangeHub.appProcessListChanged(); - } - } - } - - @Nullable - public ProfileableProcessState getProfileableProcess(int pid) { - synchronized (mProcessStates) { - ProcessState process = mProcessStates.get(pid); - if (process instanceof ProfileableProcessState) { - return (ProfileableProcessState) process; - } else { - return null; - } - } - } - - @NonNull - public ImmutableMap<Integer, PortForwarder> getAllPortForwarders() { - synchronized (mPortForwarders) { - return ImmutableMap.copyOf(mPortForwarders); - } - } - - @NonNull - public ImmutableMap<Integer, PortForwarder> getAllReversePortForwarders() { - synchronized (mReversePortForwarders) { - return ImmutableMap.copyOf(mReversePortForwarders); - } - } - - public boolean addPortForwarder(@NonNull PortForwarder forwarder, boolean noRebind) { - synchronized (mPortForwarders) { - if (noRebind) { - return mPortForwarders.computeIfAbsent( - forwarder.getSource().mPort, port -> forwarder) - == forwarder; - } else { - // Just overwrite the previous forwarder. - mPortForwarders.put(forwarder.getSource().mPort, forwarder); - return true; - } - } - } - - public boolean addReversePortForwarder(@NonNull PortForwarder forwarder, boolean noRebind) { - synchronized (mReversePortForwarders) { - if (noRebind) { - return mReversePortForwarders.computeIfAbsent( - forwarder.getSource().mPort, port -> forwarder) - == forwarder; - } else { - // Just overwrite the previous forwarder. - mReversePortForwarders.put(forwarder.getSource().mPort, forwarder); - return true; - } - } - } - - public boolean removePortForwarder(int hostPort) { - synchronized (mPortForwarders) { - return mPortForwarders.remove(hostPort) != null; - } - } - - public boolean removeReversePortForwarder(int hostPort) { - synchronized (mReversePortForwarders) { - return mReversePortForwarders.remove(hostPort) != null; - } - } - - public void removeAllPortForwarders() { - synchronized (mPortForwarders) { - mPortForwarders.clear(); - } - } - - public void removeAllReversePortForwarders() { - synchronized (mReversePortForwarders) { - mReversePortForwarders.clear(); - } - } - - @NonNull - public HostConnectionType getHostConnectionType() { - return mHostConnectionType; - } - - @NonNull - public String getClientListString() { - synchronized (mProcessStates) { - return mProcessStates.values().stream() - .filter(process -> process instanceof ClientState) - .map(clientState -> Integer.toString(clientState.getPid())) - .collect(Collectors.joining("\n")); - } - } - - public List<ProcessState> copyOfProcessStates() { - synchronized (mProcessStates) { - return new ArrayList<>(mProcessStates.values()); - } - } - - @NonNull - public DeviceStateConfig getConfig() { - return new DeviceStateConfig( - mDeviceId, - new ArrayList<>(mFiles.values()), - new ArrayList<>(mLogcatMessages), - new ArrayList<>(mProcessStates.values()), - mHostConnectionType, - mManufacturer, - mModel, - mBuildVersionRelease, - mBuildVersionSdk, - mCpuAbi, - mProperties, - mDeviceStatus); - } - - private static Set<String> initFeatures(String sdk) { - Set<String> features = - new HashSet<>(Arrays.asList("push_sync", "fixed_push_mkdir", "apex")); - try { - int api = Integer.parseInt(sdk); - if (api >= 24) { - features.add("cmd"); - features.add("shell_v2"); - features.add("stat_v2"); - } - if (api >= 30) { - features.add("abb"); - features.add("abb_exec"); - } - } catch (NumberFormatException e) { - // Cannot add more features based on API level since it is not the expected integer - // This is expected in many of our test that don't pass a correct value but instead - // pass "sdk". In such case, we return the default set of features. - // TODO: Fix adblist test to not send "sdk" and delete this catch. - } - return Collections.unmodifiableSet(features); - } - - public Set<String> getFeatures() { - return mFeatures; - } - - public ServiceManager getServiceManager() { - return mServiceManager; - } - - public void setActivityManager(Service newActivityManager) { - mServiceManager.setActivityManager(newActivityManager); - } - - public void addPmLog(String cmd) { - mPmLogs.add(cmd); - } - - public List<String> getPmLogs() { - //noinspection unchecked - return (List<String>) mPmLogs.clone(); - } - - public void addCmdLog(String cmd) { - mCmdLogs.add(cmd); - } - - public List<String> getCmdLogs() { - //noinspection unchecked - return (List<String>) mCmdLogs.clone(); - } - - public void addAbbLog(String cmd) { - mAbbLogs.add(cmd); - } - - public List<String> getAbbLogs() { - //noinspection unchecked - return (List<String>) mAbbLogs.clone(); - } - - private static Map<String, String> combinedProperties( - @NotNull String serialNumber, - @NonNull String manufacturer, - @NonNull String model, - @NonNull String release, - @NonNull String sdk, - @NonNull String cpuAbi, - @NonNull Map<String, String> properties) { - Map<String, String> combined = new TreeMap<>(properties); - combined.put("ro.serialno", serialNumber); - combined.put("ro.product.manufacturer", manufacturer); - combined.put("ro.product.model", model); - combined.put("ro.build.version.release", release); - combined.put("ro.build.version.sdk", sdk); - combined.put("ro.product.cpu.abi", cpuAbi); - return combined; - } - - /** - * The state of a device. - */ - public enum DeviceStatus { - BOOTLOADER("bootloader"), //$NON-NLS-1$ - /** bootloader mode with is-userspace = true though `adb reboot fastboot` */ - FASTBOOTD("fastbootd"), //$NON-NLS-1$ - OFFLINE("offline"), //$NON-NLS-1$ - ONLINE("device"), //$NON-NLS-1$ - RECOVERY("recovery"), //$NON-NLS-1$ - /** - * Device is in "sideload" state either through `adb sideload` or recovery menu - */ - SIDELOAD("sideload"), //$NON-NLS-1$ - UNAUTHORIZED("unauthorized"), //$NON-NLS-1$ - DISCONNECTED("disconnected"), //$NON-NLS-1$ - ; - - private final String mState; - - DeviceStatus(String state) { - mState = state; - } - - /** - * Returns a {DeviceStatus} from the string returned by <code>adb devices</code>. - * - * @param state the device state. - * @return a {DeviceStatus} object or <code>null</code> if the state is unknown. - */ - @Nullable - public static DeviceStatus getState(String state) { - for (DeviceStatus deviceStatus : values()) { - if (deviceStatus.mState.equals(state)) { - return deviceStatus; - } - } - return null; - } - - public String getState() { - return mState; - } - } - - public enum HostConnectionType { - USB, - LOCAL, - NETWORK - } - - /** - * This class represents the result of calling {@link - * #subscribeLogcatChangeHandler(ClientStateChangeHandlerFactory)}. This is needed to - * synchronize between adding the listener and getting the correct lines from the logcat buffer. - */ - public static final class LogcatChangeHandlerSubscriptionResult { - - @NonNull - public final StateChangeQueue mQueue; - - @NonNull - public final List<String> mLogcatContents; - - public LogcatChangeHandlerSubscriptionResult(@NonNull StateChangeQueue queue, - @NonNull List<String> logcatContents) { - mQueue = queue; - mLogcatContents = logcatContents; - } - } -} diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/DeviceState.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/DeviceState.kt new file mode 100644 index 0000000000..434e94d7d4 --- /dev/null +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/DeviceState.kt @@ -0,0 +1,438 @@ +/* + * Copyright (C) 2017 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.fakeadbserver + +import com.android.fakeadbserver.services.Service +import com.android.fakeadbserver.services.ServiceManager +import com.android.fakeadbserver.statechangehubs.ClientStateChangeHandlerFactory +import com.android.fakeadbserver.statechangehubs.ClientStateChangeHub +import com.android.fakeadbserver.statechangehubs.StateChangeQueue +import com.google.common.collect.ImmutableMap +import java.util.Collections +import java.util.TreeMap +import java.util.Vector +import java.util.function.Consumer +import java.util.stream.Collectors + +class DeviceState internal constructor( + private val mServer: FakeAdbServer, + val deviceId: String, + val manufacturer: String, + val model: String, + val buildVersionRelease: String, + val buildVersionSdk: String, + val cpuAbi: String, + properties: Map<String, String>, + val hostConnectionType: HostConnectionType, + val transportId: Int +) { + + val clientChangeHub = ClientStateChangeHub() + private val mFiles: MutableMap<String, DeviceFileState> = HashMap() + private val mLogcatMessages: MutableList<String> = ArrayList() + + /** PID -> [ProcessState] */ + private val mProcessStates: MutableMap<Int, ProcessState> = HashMap() + private val mPortForwarders: MutableMap<Int, PortForwarder?> = HashMap() + private val mReversePortForwarders: MutableMap<Int, PortForwarder?> = HashMap() + val features: Set<String> + val properties: Map<String, String> + private var mDeviceStatus: DeviceStatus + val serviceManager: ServiceManager + + // Keep track of all PM commands invocation + private val mPmLogs = Vector<String>() + + // Keep track of all cmd commands invocation + private val mCmdLogs = Vector<String>() + + // Keep track of all ABB/ABB_EXEC commands invocation + private val mAbbLogs = Vector<String>() + + init { + features = initFeatures(buildVersionSdk) + this.properties = + combinedProperties( + deviceId, + manufacturer, + model, + buildVersionRelease, + buildVersionSdk, + cpuAbi, + properties + ) + mDeviceStatus = DeviceStatus.OFFLINE + serviceManager = ServiceManager() + } + + internal constructor(server: FakeAdbServer, transportId: Int, config: DeviceStateConfig) : this( + server, + config.serialNumber, + config.manufacturer, + config.model, + config.buildVersionRelease, + config.buildVersionSdk, + config.cpuAbi, + config.properties, + config.hostConnectionType, + transportId + ) { + config.files.forEach(Consumer { fileState: DeviceFileState -> + mFiles[fileState.path] = + fileState + }) + mLogcatMessages.addAll(config.logcatMessages) + mDeviceStatus = config.deviceStatus + config.processes + .forEach(Consumer { clientState: ProcessState -> + mProcessStates[clientState.pid] = + clientState + }) + } + + fun stop() { + clientChangeHub.stop() + } + + val apiLevel: Int + get() = try { + buildVersionSdk.toInt() + } catch (e: NumberFormatException) { + 1 + } + + var deviceStatus: DeviceStatus + get() = mDeviceStatus + set(status) { + mDeviceStatus = status + mServer.deviceChangeHub.deviceStatusChanged(this, status) + } + + fun addLogcatMessage(message: String) { + synchronized(mLogcatMessages) { + mLogcatMessages.add(message) + clientChangeHub.logcatMessageAdded(message) + } + } + + fun subscribeLogcatChangeHandler( + handlerFactory: ClientStateChangeHandlerFactory + ): LogcatChangeHandlerSubscriptionResult? { + synchronized(mLogcatMessages) { + val queue = clientChangeHub.subscribe(handlerFactory) ?: return null + return LogcatChangeHandlerSubscriptionResult( + queue, ArrayList(mLogcatMessages) + ) + } + } + + fun createFile(file: DeviceFileState) { + synchronized(mFiles) { mFiles.put(file.path, file) } + } + + fun getFile(filepath: String): DeviceFileState? { + synchronized(mFiles) { return mFiles[filepath] } + } + + fun deleteFile(filepath: String) { + synchronized(mFiles) { mFiles.remove(filepath) } + } + + fun startClient( + pid: Int, uid: Int, packageName: String, isWaiting: Boolean + ): ClientState { + return startClient(pid, uid, packageName, packageName, isWaiting) + } + + fun startClient( + pid: Int, + uid: Int, + processName: String, + packageName: String, + isWaiting: Boolean + ): ClientState { + synchronized(mProcessStates) { + val clientState = ClientState(pid, uid, processName, packageName, isWaiting) + mProcessStates[pid] = clientState + clientChangeHub.clientListChanged() + clientChangeHub.appProcessListChanged() + return clientState + } + } + + fun stopClient(pid: Int) { + synchronized(mProcessStates) { + val processState = mProcessStates.remove(pid) + if (processState is ClientState) { + clientChangeHub.clientListChanged() + clientChangeHub.appProcessListChanged() + processState.stopJdwpSession() + } + } + } + + fun getClient(pid: Int): ClientState? { + synchronized(mProcessStates) { + val processState = mProcessStates[pid] + return if (processState is ClientState) { + processState + } else { + null + } + } + } + + fun startProfileableProcess( + pid: Int, architecture: String, commandLine: String + ): ProfileableProcessState { + synchronized(mProcessStates) { + val process = ProfileableProcessState(pid, architecture, commandLine) + mProcessStates[pid] = process + clientChangeHub.appProcessListChanged() + return process + } + } + + fun stopProfileableProcess(pid: Int) { + synchronized(mProcessStates) { + val process = mProcessStates.remove(pid) + if (process is ProfileableProcessState) { + clientChangeHub.appProcessListChanged() + } + } + } + + fun getProfileableProcess(pid: Int): ProfileableProcessState? { + synchronized(mProcessStates) { + val process = mProcessStates[pid] + return if (process is ProfileableProcessState) { + process + } else { + null + } + } + } + + val allPortForwarders: ImmutableMap<Int, PortForwarder?> + get() { + synchronized(mPortForwarders) { return ImmutableMap.copyOf(mPortForwarders) } + } + + val allReversePortForwarders: ImmutableMap<Int, PortForwarder?> + get() { + synchronized(mReversePortForwarders) { return ImmutableMap.copyOf(mReversePortForwarders) } + } + + fun addPortForwarder(forwarder: PortForwarder, noRebind: Boolean): Boolean { + synchronized(mPortForwarders) { + return if (noRebind) { + (mPortForwarders.computeIfAbsent( + forwarder.source.mPort + ) { port: Int? -> forwarder } + == forwarder) + } else { + // Just overwrite the previous forwarder. + mPortForwarders[forwarder.source.mPort] = forwarder + true + } + } + } + + fun addReversePortForwarder(forwarder: PortForwarder, noRebind: Boolean): Boolean { + synchronized(mReversePortForwarders) { + return if (noRebind) { + (mReversePortForwarders.computeIfAbsent( + forwarder.source.mPort + ) { port: Int? -> forwarder } + == forwarder) + } else { + // Just overwrite the previous forwarder. + mReversePortForwarders[forwarder.source.mPort] = forwarder + true + } + } + } + + fun removePortForwarder(hostPort: Int): Boolean { + synchronized(mPortForwarders) { return mPortForwarders.remove(hostPort) != null } + } + + fun removeReversePortForwarder(hostPort: Int): Boolean { + synchronized(mReversePortForwarders) { return mReversePortForwarders.remove(hostPort) != null } + } + + fun removeAllPortForwarders() { + synchronized(mPortForwarders) { mPortForwarders.clear() } + } + + fun removeAllReversePortForwarders() { + synchronized(mReversePortForwarders) { mReversePortForwarders.clear() } + } + + val clientListString: String + get() { + synchronized(mProcessStates) { + return mProcessStates.values.stream() + .filter { process: ProcessState? -> process is ClientState } + .map { clientState: ProcessState -> Integer.toString(clientState.pid) } + .collect(Collectors.joining("\n")) + } + } + + fun copyOfProcessStates(): List<ProcessState> { + synchronized(mProcessStates) { return ArrayList(mProcessStates.values) } + } + + val config: DeviceStateConfig + get() = DeviceStateConfig( + deviceId, + ArrayList(mFiles.values), + ArrayList(mLogcatMessages), + ArrayList(mProcessStates.values), + hostConnectionType, + manufacturer, + model, + buildVersionRelease, + buildVersionSdk, + cpuAbi, + properties, + mDeviceStatus + ) + + fun setActivityManager(newActivityManager: Service?) { + serviceManager.setActivityManager(newActivityManager!!) + } + + fun addPmLog(cmd: String) { + mPmLogs.add(cmd) + } + + val pmLogs: List<String> + get() = mPmLogs.clone() as List<String> + + fun addCmdLog(cmd: String) { + mCmdLogs.add(cmd) + } + + val cmdLogs: List<String> + get() = mCmdLogs.clone() as List<String> + + fun addAbbLog(cmd: String) { + mAbbLogs.add(cmd) + } + + val abbLogs: List<String> + get() = mAbbLogs.clone() as List<String> + + /** + * The state of a device. + */ + enum class DeviceStatus( //$NON-NLS-1$ + val state: String + ) { + + BOOTLOADER("bootloader"), //$NON-NLS-1$ + + /** bootloader mode with is-userspace = true though `adb reboot fastboot` */ + FASTBOOTD("fastbootd"), //$NON-NLS-1$ + OFFLINE("offline"), //$NON-NLS-1$ + ONLINE("device"), //$NON-NLS-1$ + RECOVERY("recovery"), //$NON-NLS-1$ + + /** + * Device is in "sideload" state either through `adb sideload` or recovery menu + */ + SIDELOAD("sideload"), //$NON-NLS-1$ + UNAUTHORIZED("unauthorized"), //$NON-NLS-1$ + DISCONNECTED("disconnected"); + + companion object { + + /** + * Returns a [DeviceStatus] from the string returned by `adb devices`. + * + * @param state the device state. + * @return a {DeviceStatus} object or `null` if the state is unknown. + */ + fun getState(state: String): DeviceStatus? { + for (deviceStatus in values()) { + if (deviceStatus.state == state) { + return deviceStatus + } + } + return null + } + } + } + + enum class HostConnectionType { + USB, LOCAL, NETWORK + } + + /** + * This class represents the result of calling [subscribeLogcatChangeHandler]. This is needed to + * synchronize between adding the listener and getting the correct lines from the logcat buffer. + */ + class LogcatChangeHandlerSubscriptionResult( + @JvmField val mQueue: StateChangeQueue, + @JvmField val mLogcatContents: List<String> + ) + + companion object { + + private fun initFeatures(sdk: String): Set<String> { + val features: MutableSet<String> = + HashSet(mutableListOf("push_sync", "fixed_push_mkdir", "apex")) + try { + val api = sdk.toInt() + if (api >= 24) { + features.add("cmd") + features.add("shell_v2") + features.add("stat_v2") + } + if (api >= 30) { + features.add("abb") + features.add("abb_exec") + } + } catch (e: NumberFormatException) { + // Cannot add more features based on API level since it is not the expected integer + // This is expected in many of our test that don't pass a correct value but instead + // pass "sdk". In such case, we return the default set of features. + // TODO: Fix adblist test to not send "sdk" and delete this catch. + } + return Collections.unmodifiableSet(features) + } + + private fun combinedProperties( + serialNumber: String, + manufacturer: String, + model: String, + release: String, + sdk: String, + cpuAbi: String, + properties: Map<String, String> + ): Map<String, String> { + val combined: MutableMap<String, String> = TreeMap(properties) + combined["ro.serialno"] = serialNumber + combined["ro.product.manufacturer"] = manufacturer + combined["ro.product.model"] = model + combined["ro.build.version.release"] = release + combined["ro.build.version.sdk"] = sdk + combined["ro.product.cpu.abi"] = cpuAbi + return combined + } + } +} diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/FakeAdbServer.java b/fakeadbserver/src/main/java/com/android/fakeadbserver/FakeAdbServer.java index 1b98f4160a..3b48e0eef1 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/FakeAdbServer.java +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/FakeAdbServer.java @@ -27,8 +27,6 @@ import com.android.fakeadbserver.devicecommandhandlers.JdwpCommandHandler; import com.android.fakeadbserver.devicecommandhandlers.ReverseForwardCommandHandler; import com.android.fakeadbserver.devicecommandhandlers.TrackAppCommandHandler; import com.android.fakeadbserver.devicecommandhandlers.TrackJdwpCommandHandler; -import com.android.fakeadbserver.execcommandhandlers.PackageExecCommandHandler; -import com.android.fakeadbserver.execcommandhandlers.PingExecCommandHandler; import com.android.fakeadbserver.hostcommandhandlers.FeaturesCommandHandler; import com.android.fakeadbserver.hostcommandhandlers.ForwardCommandHandler; import com.android.fakeadbserver.hostcommandhandlers.GetDevPathCommandHandler; @@ -55,6 +53,7 @@ import com.android.fakeadbserver.shellcommandhandlers.EchoCommandHandler; import com.android.fakeadbserver.shellcommandhandlers.GetPropCommandHandler; import com.android.fakeadbserver.shellcommandhandlers.LogcatCommandHandler; import com.android.fakeadbserver.shellcommandhandlers.PackageManagerCommandHandler; +import com.android.fakeadbserver.shellcommandhandlers.PingCommandHandler; import com.android.fakeadbserver.shellcommandhandlers.RmCommandHandler; import com.android.fakeadbserver.shellcommandhandlers.SetPropCommandHandler; import com.android.fakeadbserver.shellcommandhandlers.ShellProtocolEchoCommandHandler; @@ -570,11 +569,8 @@ public final class FakeAdbServer implements AutoCloseable { addDeviceHandler(new FakeSyncCommandHandler()); addDeviceHandler(new ReverseForwardCommandHandler()); - // Exec commands - addDeviceHandler(new PackageExecCommandHandler()); - addDeviceHandler(new PingExecCommandHandler()); + addDeviceHandler(new PingCommandHandler(ShellProtocolType.EXEC)); addDeviceHandler(new RmCommandHandler(ShellProtocolType.SHELL)); - addDeviceHandler(new LogcatCommandHandler(ShellProtocolType.SHELL)); addDeviceHandler(new GetPropCommandHandler(ShellProtocolType.EXEC)); addDeviceHandler(new GetPropCommandHandler(ShellProtocolType.SHELL)); @@ -594,6 +590,7 @@ public final class FakeAdbServer implements AutoCloseable { addDeviceHandler(new AbbCommandHandler()); addDeviceHandler(new AbbExecCommandHandler()); addDeviceHandler(new ActivityManagerCommandHandler(ShellProtocolType.SHELL)); + addDeviceHandler(new ActivityManagerCommandHandler(ShellProtocolType.SHELL_V2)); addDeviceHandler(new JdwpCommandHandler()); addDeviceHandler(new StatCommandHandler(ShellProtocolType.SHELL)); diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/ShellV2Protocol.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/ShellV2Protocol.kt index 7a115c78da..42082d439c 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/ShellV2Protocol.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/ShellV2Protocol.kt @@ -17,7 +17,7 @@ package com.android.fakeadbserver import com.android.fakeadbserver.services.ExecOutput import com.android.fakeadbserver.services.LegacyShellOutput -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput import com.android.fakeadbserver.services.ShellV2Output import com.google.common.base.Charsets import java.io.EOFException @@ -35,7 +35,7 @@ enum class ShellProtocolType { override val command: String get() = "shell" - override fun createServiceOutput(socket: Socket, device: DeviceState): ServiceOutput { + override fun createServiceOutput(socket: Socket, device: DeviceState): ShellCommandOutput { return LegacyShellOutput(socket, device) } }, @@ -44,7 +44,7 @@ enum class ShellProtocolType { override val command: String get() = "exec" - override fun createServiceOutput(socket: Socket, device: DeviceState): ServiceOutput { + override fun createServiceOutput(socket: Socket, device: DeviceState): ShellCommandOutput { return ExecOutput(socket) } }, @@ -53,13 +53,13 @@ enum class ShellProtocolType { override val command: String get() = "shell,v2" - override fun createServiceOutput(socket: Socket, device: DeviceState): ServiceOutput { + override fun createServiceOutput(socket: Socket, device: DeviceState): ShellCommandOutput { return ShellV2Output(socket) } }; abstract val command: String - abstract fun createServiceOutput(socket: Socket, device: DeviceState) : ServiceOutput + abstract fun createServiceOutput(socket: Socket, device: DeviceState) : ShellCommandOutput } class ShellV2Protocol(private val socket: Socket) { diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/devicecommandhandlers/ReverseForwardCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/devicecommandhandlers/ReverseForwardCommandHandler.kt index cf07b8b514..e20720e573 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/devicecommandhandlers/ReverseForwardCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/devicecommandhandlers/ReverseForwardCommandHandler.kt @@ -197,9 +197,9 @@ internal class ReverseForwardCommandHandler : DeviceCommandHandler("reverse") { // https://cs.android.com/android/platform/superproject/+/3a52886262ae22477a7d8ffb12adba64daf6aafa:packages/modules/adb/daemon/usb.cpp;l=759 builder.append("UsbFfs") builder.append(" ") - builder.append("tcp:${portForwarder.source.port}") + builder.append("tcp:${portForwarder?.source?.port}") builder.append(" ") - builder.append("tcp:${portForwarder.destination.port}") + builder.append("tcp:${portForwarder?.destination?.port}") builder.append("\n") } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/devicecommandhandlers/ddmsHandlers/HeloHandler.java b/fakeadbserver/src/main/java/com/android/fakeadbserver/devicecommandhandlers/ddmsHandlers/HeloHandler.java deleted file mode 100644 index d25610a1f8..0000000000 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/devicecommandhandlers/ddmsHandlers/HeloHandler.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2017 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.fakeadbserver.devicecommandhandlers.ddmsHandlers; - -import com.android.annotations.NonNull; -import com.android.fakeadbserver.ClientState; -import com.android.fakeadbserver.DeviceState; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.ByteBuffer; - -public class HeloHandler implements DDMPacketHandler { - - public static final int CHUNK_TYPE = DdmPacket.encodeChunkType("HELO"); - - private static final String VM_IDENTIFIER = "FakeVM"; - - private static final String JVM_FLAGS = "-jvmflag=true"; - - private static final int HELO_CHUNK_HEADER_LENGTH = 16; - - private static final int VERSION = 9999; - - @Override - public boolean handlePacket( - @NonNull DeviceState device, - @NonNull ClientState client, - @NonNull DdmPacket packet, - @NonNull OutputStream oStream) { - // ADB has an issue of reporting the process name instead of the real not reporting the real package name. - String appName = client.getProcessName(); - - int deviceApiLevel = device.getApiLevel(); - - // UserID starts at API 18 - boolean writeUserId = deviceApiLevel >= 18; - - // ABI starts at API 21 - boolean writeAbi = deviceApiLevel >= 21; - String abi = device.getCpuAbi(); - - // JvmFlags starts at API 21 - boolean writeJvmFlags = deviceApiLevel >= 21; - String jvmFlags = JVM_FLAGS; - - // native debuggable starts at API 24 - boolean writeNativeDebuggable = deviceApiLevel >= 24; - - // package name starts at API 30 - boolean writePackageName = deviceApiLevel >= 30; - String packageName = client.getPackageName(); - - int payloadLength = - HELO_CHUNK_HEADER_LENGTH - + ((VM_IDENTIFIER.length() + appName.length()) * 2) - + (writeUserId ? 4 : 0) - + (writeAbi ? 4 + abi.length() * 2 : 0) - + (writeJvmFlags ? 4 + jvmFlags.length() * 2 : 0) - + (writeNativeDebuggable ? 1 : 0) - + (writePackageName ? 4 + packageName.length() * 2 : 0); - byte[] payload = new byte[payloadLength]; - ByteBuffer payloadBuffer = ByteBuffer.wrap(payload); - payloadBuffer.putInt(VERSION); - payloadBuffer.putInt(client.getPid()); - payloadBuffer.putInt(VM_IDENTIFIER.length()); - payloadBuffer.putInt(appName.length()); - for (char c : VM_IDENTIFIER.toCharArray()) { - payloadBuffer.putChar(c); - } - for (char c : appName.toCharArray()) { - payloadBuffer.putChar(c); - } - if (writeUserId) { - payloadBuffer.putInt(client.getUid()); - } - if (writeAbi) { - payloadBuffer.putInt(abi.length()); - for (char c : abi.toCharArray()) { - payloadBuffer.putChar(c); - } - } - if (writeJvmFlags) { - payloadBuffer.putInt(jvmFlags.length()); - for (char c : jvmFlags.toCharArray()) { - payloadBuffer.putChar(c); - } - } - if (writeNativeDebuggable) { - payloadBuffer.put((byte) 0); - } - if (writePackageName) { - payloadBuffer.putInt(packageName.length()); - for (char c : packageName.toCharArray()) { - payloadBuffer.putChar(c); - } - } - - DdmPacket responsePacket = DdmPacket.createResponse(packet.getId(), CHUNK_TYPE, payload); - - try { - responsePacket.write(oStream); - } catch (IOException e) { - e.printStackTrace(); - return false; - } - - // Send "APMN" command packet as to simulate Android behavior - try { - int apnmPayloadLength = - (4 + appName.length() * 2) - + (writeUserId ? 4 : 0) - + (writePackageName ? 4 + packageName.length() * 2 : 0); - ByteBuffer apmnPayload = ByteBuffer.allocate(apnmPayloadLength); - - // Process Name - apmnPayload.putInt(appName.length()); - for (char c : appName.toCharArray()) { - apmnPayload.putChar(c); - } - - // User ID - if (writeUserId) { - apmnPayload.putInt(client.getUid()); - } - - // Package Name - if (writePackageName) { - apmnPayload.putInt(packageName.length()); - for (char c : packageName.toCharArray()) { - apmnPayload.putChar(c); - } - } - - DdmPacket apnmPacket = - DdmPacket.createCommand( - client.nextDdmsCommandId(), - DdmPacket.encodeChunkType("APNM"), - apmnPayload.array()); - apnmPacket.write(oStream); - } catch (IOException e) { - e.printStackTrace(); - return false; - } - - // Send "WAIT" packet if needed - if (client.getIsWaiting()) { - - byte[] waitPayload = new byte[1]; - DdmPacket waitPacket = - DdmPacket.createCommand( - client.nextDdmsCommandId(), - DdmPacket.encodeChunkType("WAIT"), - waitPayload); - try { - waitPacket.write(oStream); - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } - return true; - } -} diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/devicecommandhandlers/ddmsHandlers/HeloHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/devicecommandhandlers/ddmsHandlers/HeloHandler.kt new file mode 100644 index 0000000000..3ced911b57 --- /dev/null +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/devicecommandhandlers/ddmsHandlers/HeloHandler.kt @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2017 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.fakeadbserver.devicecommandhandlers.ddmsHandlers + +import com.android.fakeadbserver.ClientState +import com.android.fakeadbserver.DeviceState +import java.io.IOException +import java.io.OutputStream +import java.nio.ByteBuffer + +class HeloHandler : DDMPacketHandler { + + override fun handlePacket( + device: DeviceState, + client: ClientState, + packet: DdmPacket, + oStream: OutputStream + ): Boolean { + // ADB has an issue of reporting the process name instead of the real not reporting the real package name. + val appName = client.processName + val deviceApiLevel = device.apiLevel + + // UserID starts at API 18 + val writeUserId = deviceApiLevel >= 18 + + // ABI starts at API 21 + val writeAbi = deviceApiLevel >= 21 + val abi = device.cpuAbi + + // JvmFlags starts at API 21 + val writeJvmFlags = deviceApiLevel >= 21 + val jvmFlags = JVM_FLAGS + + // native debuggable starts at API 24 + val writeNativeDebuggable = deviceApiLevel >= 24 + + // package name starts at API 30 + val writePackageName = deviceApiLevel >= 30 + val packageName = client.packageName + + val payloadLength = (HELO_CHUNK_HEADER_LENGTH + (VM_IDENTIFIER.length + appName.length) * 2 + + (if (writeUserId) 4 else 0) + + (if (writeAbi) 4 + abi.length * 2 else 0) + + (if (writeJvmFlags) 4 + jvmFlags.length * 2 else 0) + + (if (writeNativeDebuggable) 1 else 0) + + if (writePackageName) 4 + packageName.length * 2 else 0) + val payload = ByteArray(payloadLength) + val payloadBuffer = ByteBuffer.wrap(payload) + payloadBuffer.putInt(VERSION) + payloadBuffer.putInt(client.pid) + payloadBuffer.putInt(VM_IDENTIFIER.length) + payloadBuffer.putInt(appName.length) + for (c in VM_IDENTIFIER.toCharArray()) { + payloadBuffer.putChar(c) + } + for (c in appName.toCharArray()) { + payloadBuffer.putChar(c) + } + if (writeUserId) { + payloadBuffer.putInt(client.uid) + } + if (writeAbi) { + payloadBuffer.putInt(abi.length) + for (c in abi.toCharArray()) { + payloadBuffer.putChar(c) + } + } + if (writeJvmFlags) { + payloadBuffer.putInt(jvmFlags.length) + for (c in jvmFlags.toCharArray()) { + payloadBuffer.putChar(c) + } + } + if (writeNativeDebuggable) { + payloadBuffer.put(0.toByte()) + } + if (writePackageName) { + payloadBuffer.putInt(packageName.length) + for (c in packageName.toCharArray()) { + payloadBuffer.putChar(c) + } + } + + val responsePacket = DdmPacket.createResponse(packet.id, CHUNK_TYPE, payload) + try { + responsePacket.write(oStream) + } catch (e: IOException) { + e.printStackTrace() + return false + } + + // Send "APMN" command packet as to simulate Android behavior + try { + val apnmPayloadLength = (4 + appName.length * 2 + + (if (writeUserId) 4 else 0) + + if (writePackageName) 4 + packageName.length * 2 else 0) + val apmnPayload = ByteBuffer.allocate(apnmPayloadLength) + + // Process Name + apmnPayload.putInt(appName.length) + for (c in appName.toCharArray()) { + apmnPayload.putChar(c) + } + + // User ID + if (writeUserId) { + apmnPayload.putInt(client.uid) + } + + // Package Name + if (writePackageName) { + apmnPayload.putInt(packageName.length) + for (c in packageName.toCharArray()) { + apmnPayload.putChar(c) + } + } + + val apnmPacket = DdmPacket.createCommand( + client.nextDdmsCommandId(), + DdmPacket.encodeChunkType("APNM"), + apmnPayload.array() + ) + apnmPacket.write(oStream) + } catch (e: IOException) { + e.printStackTrace() + return false + } + + // Send "WAIT" packet if needed + if (client.isWaiting) { + val waitPayload = ByteArray(1) + val waitPacket = DdmPacket.createCommand( + client.nextDdmsCommandId(), + DdmPacket.encodeChunkType("WAIT"), + waitPayload + ) + try { + waitPacket.write(oStream) + } catch (e: IOException) { + e.printStackTrace() + return false + } + } + return true + } + + companion object { + + @JvmField + val CHUNK_TYPE = DdmPacket.encodeChunkType("HELO") + private const val VM_IDENTIFIER = "FakeVM" + private const val JVM_FLAGS = "-jvmflag=true" + private const val HELO_CHUNK_HEADER_LENGTH = 16 + private const val VERSION = 9999 + } +} diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/execcommandhandlers/PackageExecCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/execcommandhandlers/PackageExecCommandHandler.kt deleted file mode 100644 index f27f250bfa..0000000000 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/execcommandhandlers/PackageExecCommandHandler.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2017 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.fakeadbserver.execcommandhandlers - -import com.android.fakeadbserver.CommandHandler -import com.android.fakeadbserver.DeviceState -import com.android.fakeadbserver.FakeAdbServer -import java.io.InputStream -import java.net.Socket -import java.util.regex.Pattern - -class PackageExecCommandHandler : SimpleExecHandler("package") { - - override fun execute( - fakeAdbServer: FakeAdbServer, - responseSocket: Socket, - device: DeviceState, - args: String? - ) { - val output = responseSocket.getOutputStream() - if (args == null) { - CommandHandler.writeFail(output) - return - } - - CommandHandler.writeOkay(output) - - val response: String = when { - args.startsWith("install-create") -> installMultiple() - args.startsWith("install-commit") -> installCommit() - else -> "" - } - - CommandHandler.writeString(output, response) - } - - /** - * Handler for commands that look like: - * - * adb shell cmd package install-create -r -t --ephemeral -S 1298948 - */ - private fun installMultiple(): String { - return "Success: created install session [1234]" - } - - /** - * handler for commands that look like: - * - * adb shell cmd package install-commit 538681231 - */ - private fun installCommit(): String { - return "Success\n" - } -} diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/hostcommandhandlers/ListForwardCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/hostcommandhandlers/ListForwardCommandHandler.kt index 56fba111ff..e7059745db 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/hostcommandhandlers/ListForwardCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/hostcommandhandlers/ListForwardCommandHandler.kt @@ -45,9 +45,9 @@ internal class ListForwardCommandHandler : HostCommandHandler() { for (portForwarder in deviceState.allPortForwarders.values) { builder.append(deviceState.deviceId) builder.append(" ") - builder.append("tcp:${portForwarder.source.port}") + builder.append("tcp:${portForwarder?.source?.port}") builder.append(" ") - builder.append("tcp:${portForwarder.destination.port}") + builder.append("tcp:${portForwarder?.destination?.port}") builder.append("\n") } } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/services/PackageManager.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/services/PackageManager.kt index 9ba940baa0..c4d13369cf 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/services/PackageManager.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/services/PackageManager.kt @@ -38,110 +38,110 @@ class PackageManager : Service { const val SERVICE_NAME = "package" } - override fun process(args: List<String>, serviceOutput: ServiceOutput) { + override fun process(args: List<String>, shellCommandOutput: ShellCommandOutput) { val cmd = args[0] return when { cmd == "list users" -> { - serviceOutput.writeStdout("Users:\n\tUserInfo{0:Owner:13} running\n") - serviceOutput.writeExitCode(0) + shellCommandOutput.writeStdout("Users:\n\tUserInfo{0:Owner:13} running\n") + shellCommandOutput.writeExitCode(0) } cmd.startsWith("uninstall") -> { if (args.size == 1) { - serviceOutput.writeStdout("Error: package name not specified") - serviceOutput.writeExitCode(1) + shellCommandOutput.writeStdout("Error: package name not specified") + shellCommandOutput.writeExitCode(1) return } val applicationId = args.last() if (applicationId == ShellConstants.NON_INSTALLED_APP_ID) { - serviceOutput.writeStdout("Failure [DELETE_FAILED_INTERNAL_ERROR]") + shellCommandOutput.writeStdout("Failure [DELETE_FAILED_INTERNAL_ERROR]") } else { - serviceOutput.writeStdout("Success") + shellCommandOutput.writeStdout("Success") } } cmd == "path" -> { val appId = args[1] - serviceOutput.writeStdout("/data/app/$appId/base.apk") - serviceOutput.writeExitCode(0) + shellCommandOutput.writeStdout("/data/app/$appId/base.apk") + shellCommandOutput.writeExitCode(0) } cmd.startsWith("install-create") -> { if (args.contains(BAD_FLAG)) { - serviceOutput.writeStderr("Error: (requested to fail via flag))") - serviceOutput.writeExitCode(1) - return; + shellCommandOutput.writeStderr("Error: (requested to fail via flag))") + shellCommandOutput.writeExitCode(1) + return } else { - serviceOutput.writeStdout("Success: created install session [1234]") - serviceOutput.writeExitCode(0) + shellCommandOutput.writeStdout("Success: created install session [1234]") + shellCommandOutput.writeExitCode(0) } } cmd.startsWith("install-write") -> { - installWrite(args.joinToString(" "), serviceOutput) + installWrite(args.joinToString(" "), shellCommandOutput) } cmd.startsWith("install-commit") -> { val sessionID = args[1] if (BAD_SESSIONS.containsKey(sessionID)) { - BAD_SESSIONS.get(sessionID)?.let { serviceOutput.writeStderr(it) } - serviceOutput.writeExitCode(1) + BAD_SESSIONS.get(sessionID)?.let { shellCommandOutput.writeStderr(it) } + shellCommandOutput.writeExitCode(1) } else { - commit(args.drop(1), serviceOutput) + commit(args.drop(1), shellCommandOutput) } } cmd.startsWith("install-abandon") -> { - serviceOutput.writeStdout("Success\n") - serviceOutput.writeExitCode(0) + shellCommandOutput.writeStdout("Success\n") + shellCommandOutput.writeExitCode(0) } cmd.startsWith("install") -> { - commit(args.drop(1), serviceOutput) + commit(args.drop(1), shellCommandOutput) } else -> { - serviceOutput.writeStderr("Error: Package command '$cmd' is not supported") - serviceOutput.writeExitCode(1) + shellCommandOutput.writeStderr("Error: Package command '$cmd' is not supported") + shellCommandOutput.writeExitCode(1) } } } - private fun commit(slice: List<String>, serviceOutput: ServiceOutput) { + private fun commit(slice: List<String>, shellCommandOutput: ShellCommandOutput) { val sessionID = slice[0] if (sessionID == "FAIL_ME") { - serviceOutput.writeStderr("Error (requested a FAIL_ME session)\n") - serviceOutput.writeExitCode(1) + shellCommandOutput.writeStderr("Error (requested a FAIL_ME session)\n") + shellCommandOutput.writeExitCode(1) } else { - serviceOutput.writeStdout("Success\n") - serviceOutput.writeExitCode(0) + shellCommandOutput.writeStdout("Success\n") + shellCommandOutput.writeExitCode(0) } } - private fun installWrite(args: String, serviceOutput: ServiceOutput) { + private fun installWrite(args: String, shellCommandOutput: ShellCommandOutput) { val parameters = args.split(" ") if (parameters.isEmpty()) { - serviceOutput.writeStderr("Malformed install-write request") - serviceOutput.writeExitCode(1) + shellCommandOutput.writeStderr("Malformed install-write request") + shellCommandOutput.writeExitCode(1) return } if (parameters.last() != "-") { val sessionID = parameters[1] if (BAD_SESSIONS.containsKey(sessionID)) { - BAD_SESSIONS.get(sessionID)?.let { serviceOutput.writeStderr(it) } - serviceOutput.writeExitCode(1) + BAD_SESSIONS.get(sessionID)?.let { shellCommandOutput.writeStderr(it) } + shellCommandOutput.writeExitCode(1) return } // This is a remote apk write (the apk is somewhere on the device, likely /data/local"..) // Use a random value - serviceOutput.writeStdout("Success: streamed 123456789 bytes\n") - serviceOutput.writeExitCode(0) + shellCommandOutput.writeStdout("Success: streamed 123456789 bytes\n") + shellCommandOutput.writeExitCode(0) return } // This is a streamed install val sizeIndex = parameters.indexOf("-S") + 1 if (sizeIndex == 0) { - serviceOutput.writeStderr("Malformed install-write request") - serviceOutput.writeExitCode(1) + shellCommandOutput.writeStderr("Malformed install-write request") + shellCommandOutput.writeExitCode(1) return } @@ -150,14 +150,14 @@ class PackageManager : Service { var totalBytesRead = 0 while (totalBytesRead < expectedBytesLength) { val length = Integer.min(buffer.size, expectedBytesLength - totalBytesRead) - val numRead = serviceOutput.readStdin(buffer, 0, length) + val numRead = shellCommandOutput.readStdin(buffer, 0, length) if (numRead < 0) { break } totalBytesRead += numRead } - serviceOutput.writeStdout("Success: streamed $totalBytesRead bytes\n") - serviceOutput.writeExitCode(0) + shellCommandOutput.writeStdout("Success: streamed $totalBytesRead bytes\n") + shellCommandOutput.writeExitCode(0) } } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/services/Service.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/services/Service.kt index 8c6430c338..160111e4ce 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/services/Service.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/services/Service.kt @@ -16,5 +16,5 @@ package com.android.fakeadbserver.services fun interface Service { - fun process(args: List<String>, serviceOutput: ServiceOutput) + fun process(args: List<String>, shellCommandOutput: ShellCommandOutput) } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/services/ServiceManager.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/services/ServiceManager.kt index dcd9adb998..5169d7dc55 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/services/ServiceManager.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/services/ServiceManager.kt @@ -26,7 +26,7 @@ class ServiceManager { private val packageManager = PackageManager() private var activityManager: Service? = null - private val log = java.util.Collections.synchronizedList(mutableListOf<List<String>>()) + private val log = Collections.synchronizedList(mutableListOf<List<String>>()) // Returns a list of all service request received. // Each entry is a list of all parameters for that request. @@ -34,7 +34,7 @@ class ServiceManager { return Collections.unmodifiableList(log) } - fun processCommand(args: List<String>, output: ServiceOutput) { + fun processCommand(args: List<String>, output: ShellCommandOutput) { // We log received commands to allow tests to inspect call history log.add(Collections.unmodifiableList(args)) @@ -44,7 +44,7 @@ class ServiceManager { if (service == null) { output.writeStderr("Error: Service '$serviceName' is not supported") output.writeExitCode(5) - return; + return } service.process(args.slice(1 until args.size), output) diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/services/ServiceOutput.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/services/ShellCommandOutput.kt index c19b3eb0a1..1dc6846b14 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/services/ServiceOutput.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/services/ShellCommandOutput.kt @@ -27,7 +27,7 @@ import java.nio.charset.StandardCharsets.UTF_8 * This allows shell command implementor in [FakeAdbServer] to have a single implementation * that can deal with the simplified stdin/stdout protocol, or the full [ShellV2Protocol]. */ -interface ServiceOutput { +interface ShellCommandOutput { fun writeStdout(bytes: ByteArray) fun writeStderr(bytes: ByteArray) @@ -46,11 +46,11 @@ interface ServiceOutput { } /** - * Implementation of [ServiceOutput] that writes stdout/stderr directly to + * Implementation of [ShellCommandOutput] that writes stdout/stderr directly to * [Socket.getOutputStream], and ignores exit code. This corresponds to how * the legacy "shell:" ADB service works. */ -class LegacyShellOutput(socket: Socket, val device: DeviceState) : ServiceOutput { +class LegacyShellOutput(socket: Socket, val device: DeviceState) : ShellCommandOutput { private val input = socket.getInputStream() private val output = socket.getOutputStream() @@ -73,11 +73,11 @@ class LegacyShellOutput(socket: Socket, val device: DeviceState) : ServiceOutput } /** - * Implementation of [ServiceOutput] that writes stdout/stderr directly to + * Implementation of [ShellCommandOutput] that writes stdout/stderr directly to * [Socket.getOutputStream], and ignores exit code. This corresponds to how * the legacy "exec:" ADB service works */ -class ExecOutput(socket: Socket) : ServiceOutput { +class ExecOutput(socket: Socket) : ShellCommandOutput { private val input = socket.getInputStream() private val output = socket.getOutputStream() @@ -119,10 +119,10 @@ fun ByteArray.replaceNewLineForOlderDevices(device: DeviceState): ByteArray { } /** - * Implementation of [ServiceOutput] that read and writes from/to the underlying socket + * Implementation of [ShellCommandOutput] that read and writes from/to the underlying socket * using the [ShellV2Protocol]. This corresponds to how the "shell,v2:" ADB service works. */ -class ShellV2Output(socket: Socket) : ServiceOutput { +class ShellV2Output(socket: Socket) : ShellCommandOutput { private val protocol = ShellV2Protocol(socket) diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/ActivityManagerCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/ActivityManagerCommandHandler.kt index fcccd1a6e5..0a794b222b 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/ActivityManagerCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/ActivityManagerCommandHandler.kt @@ -19,18 +19,18 @@ import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType import com.android.fakeadbserver.services.ServiceManager -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput class ActivityManagerCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandler( shellProtocolType,"am") { override fun execute( - fakeAdbServer: FakeAdbServer, - statusWriter: StatusWriter, - serviceOutput: ServiceOutput, - device: DeviceState, - shellCommand: String, - shellCommandArgs: String? + fakeAdbServer: FakeAdbServer, + statusWriter: StatusWriter, + shellCommandOutput: ShellCommandOutput, + device: DeviceState, + shellCommand: String, + shellCommandArgs: String? ) { if (shellCommandArgs == null) { statusWriter.writeFail() @@ -42,6 +42,6 @@ class ActivityManagerCommandHandler(shellProtocolType: ShellProtocolType) : Simp // Create a service request val params = mutableListOf(ServiceManager.ACTIVITY_MANAGER_SERVICE_NAME) params.addAll(shellCommandArgs.split(" ")) - device.serviceManager.processCommand(params, serviceOutput) + device.serviceManager.processCommand(params, shellCommandOutput) } } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/CatCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/CatCommandHandler.kt index d019427d0d..5ba8bd5d8a 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/CatCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/CatCommandHandler.kt @@ -18,7 +18,7 @@ package com.android.fakeadbserver.shellcommandhandlers import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput import java.io.ByteArrayOutputStream /** @@ -39,49 +39,49 @@ class CatCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandl override fun execute( fakeAdbServer: FakeAdbServer, statusWriter: StatusWriter, - serviceOutput: ServiceOutput, + shellCommandOutput: ShellCommandOutput, device: DeviceState, shellCommand: String, shellCommandArgs: String? ) { statusWriter.writeOk() if (shellCommandArgs.isNullOrEmpty()) { - forwardStdinAsStdout(serviceOutput) + forwardStdinAsStdout(shellCommandOutput) return } - if (tryHandleCatProcPidCmdline(serviceOutput, device, shellCommandArgs)) { + if (tryHandleCatProcPidCmdline(shellCommandOutput, device, shellCommandArgs)) { return } - catRegularFiles(serviceOutput, device, shellCommandArgs) + catRegularFiles(shellCommandOutput, device, shellCommandArgs) } /** Outputs all characters received from `stdin` back to `stdout`, one * line at a time, i.e. characters are written back to `stdout` only when a newline ("\n") * character is received from `stdin`. **/ - private fun forwardStdinAsStdout(serviceOutput: ServiceOutput) { + private fun forwardStdinAsStdout(shellCommandOutput: ShellCommandOutput) { val stdoutStream = ByteArrayOutputStream() val buffer = ByteArray(1) while (true) { - val numRead = serviceOutput.readStdin(buffer, 0, buffer.size) + val numRead = shellCommandOutput.readStdin(buffer, 0, buffer.size) if (numRead < 0) { - serviceOutput.writeStdout(stdoutStream.toByteArray()) - serviceOutput.writeExitCode(0) + shellCommandOutput.writeStdout(stdoutStream.toByteArray()) + shellCommandOutput.writeExitCode(0) break } val ch = buffer[0].toInt() stdoutStream.write(ch) if (ch == '\n'.code) { - serviceOutput.writeStdout(stdoutStream.toByteArray()) + shellCommandOutput.writeStdout(stdoutStream.toByteArray()) stdoutStream.reset() } } } private fun tryHandleCatProcPidCmdline( - serviceOutput: ServiceOutput, + shellCommandOutput: ShellCommandOutput, device: DeviceState, args: String ): Boolean { @@ -94,16 +94,16 @@ class CatCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandl val profileableClient = device.getProfileableProcess(pid) if (profileableClient == null) { - serviceOutput.writeStderr("profileableClient with a pid $pid not found") + shellCommandOutput.writeStderr("profileableClient with a pid $pid not found") return true } - serviceOutput.writeStdout(profileableClient.commandLine) - serviceOutput.writeExitCode(0) + shellCommandOutput.writeStdout(profileableClient.commandLine) + shellCommandOutput.writeExitCode(0) return true } - private fun catRegularFiles(serviceOutput: ServiceOutput, device: DeviceState, args: String) { + private fun catRegularFiles(shellCommandOutput: ShellCommandOutput, device: DeviceState, args: String) { val fileName = args.trim() if (fileName.contains("\\s+")) { throw NotImplementedError("Multiple files or file names with spaces are not implemented") @@ -111,9 +111,9 @@ class CatCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandl val file = device.getFile(fileName) if (file == null) { - serviceOutput.writeStderr("No such file or directory") + shellCommandOutput.writeStderr("No such file or directory") } else { - serviceOutput.writeStdout(file.bytes) + shellCommandOutput.writeStdout(file.bytes) } } } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/CmdCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/CmdCommandHandler.kt index 7ef49f80a3..26702cf50e 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/CmdCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/CmdCommandHandler.kt @@ -19,7 +19,7 @@ import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType import com.android.fakeadbserver.services.PackageManager -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput import java.io.IOException import java.util.regex.Pattern @@ -28,12 +28,12 @@ class CmdCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandl ) { override fun execute( - fakeAdbServer: FakeAdbServer, - statusWriter: StatusWriter, - serviceOutput: ServiceOutput, - device: DeviceState, - shellCommand: String, - shellCommandArgs: String? + fakeAdbServer: FakeAdbServer, + statusWriter: StatusWriter, + shellCommandOutput: ShellCommandOutput, + device: DeviceState, + shellCommand: String, + shellCommandArgs: String? ) { try { if (shellCommandArgs == null) { @@ -55,14 +55,14 @@ class CmdCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandl shellCommandArgs.startsWith("package install-create") -> installMultiple() shellCommandArgs.startsWith("package install-commit") -> installCommit() shellCommandArgs.startsWith("package install-write") -> installWrite( - shellCommandArgs, - serviceOutput + shellCommandArgs, + shellCommandOutput ) else -> "" } - serviceOutput.writeStdout(response) + shellCommandOutput.writeStdout(response) } catch (ignored: IOException) { } @@ -95,7 +95,7 @@ class CmdCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandl * `args` would be "package install-write -S 1289508 548838628 0_base-debug -" in * the above example. */ - private fun installWrite(args: String, serviceOutput: ServiceOutput): String { + private fun installWrite(args: String, shellCommandOutput: ShellCommandOutput): String { val streamLengthExtractor = Pattern.compile("package install-write\\s+-S\\s+(\\d+).*") val streamLengthMatcher = streamLengthExtractor.matcher(args) streamLengthMatcher.find() @@ -114,7 +114,7 @@ class CmdCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandl var totalBytesRead = 0 while (totalBytesRead < expectedBytesLength) { val numRead: Int = - serviceOutput.readStdin(buffer, 0, Math.min(buffer.size, expectedBytesLength - totalBytesRead)) + shellCommandOutput.readStdin(buffer, 0, Math.min(buffer.size, expectedBytesLength - totalBytesRead)) if (numRead < 0) { break } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/DumpsysCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/DumpsysCommandHandler.kt index 72a86064aa..d8dc3cb9dc 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/DumpsysCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/DumpsysCommandHandler.kt @@ -18,19 +18,19 @@ package com.android.fakeadbserver.shellcommandhandlers import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput import java.io.IOException class DumpsysCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandler( shellProtocolType,"dumpsys") { override fun execute( - fakeAdbServer: FakeAdbServer, - statusWriter: StatusWriter, - serviceOutput: ServiceOutput, - device: DeviceState, - shellCommand: String, - shellCommandArgs: String? + fakeAdbServer: FakeAdbServer, + statusWriter: StatusWriter, + shellCommandOutput: ShellCommandOutput, + device: DeviceState, + shellCommand: String, + shellCommandArgs: String? ) { try { if (shellCommandArgs == null) { @@ -45,7 +45,7 @@ class DumpsysCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellH else -> "" } - serviceOutput.writeStdout(response) + shellCommandOutput.writeStdout(response) } catch (ignored: IOException) { } } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/EchoCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/EchoCommandHandler.kt index 1c8ef64095..8464b1c3a9 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/EchoCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/EchoCommandHandler.kt @@ -18,7 +18,7 @@ package com.android.fakeadbserver.shellcommandhandlers import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput /** * A shell command handler that writes its argument(s) to `stdout`, followed by a newline @@ -28,15 +28,15 @@ class EchoCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHand ) { override fun execute( - fakeAdbServer: FakeAdbServer, - statusWriter: StatusWriter, - serviceOutput: ServiceOutput, - device: DeviceState, - shellCommand: String, - shellCommandArgs: String? + fakeAdbServer: FakeAdbServer, + statusWriter: StatusWriter, + shellCommandOutput: ShellCommandOutput, + device: DeviceState, + shellCommand: String, + shellCommandArgs: String? ) { statusWriter.writeOk() - shellCommandArgs?.also { serviceOutput.writeStdout(shellCommandArgs) } - serviceOutput.writeStdout("\n") + shellCommandArgs?.also { shellCommandOutput.writeStdout(shellCommandArgs) } + shellCommandOutput.writeStdout("\n") } } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/GetPropCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/GetPropCommandHandler.kt index 802697b7ef..bcf8cbbb5d 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/GetPropCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/GetPropCommandHandler.kt @@ -18,7 +18,7 @@ package com.android.fakeadbserver.shellcommandhandlers import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput /** * A [SimpleShellHandler] that outputs a hard-coded list of lines that follows the format @@ -27,12 +27,12 @@ import com.android.fakeadbserver.services.ServiceOutput class GetPropCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandler(shellProtocolType, "getprop") { override fun execute( - fakeAdbServer: FakeAdbServer, - statusWriter: StatusWriter, - serviceOutput: ServiceOutput, - device: DeviceState, - shellCommand: String, - shellCommandArgs: String? + fakeAdbServer: FakeAdbServer, + statusWriter: StatusWriter, + shellCommandOutput: ShellCommandOutput, + device: DeviceState, + shellCommand: String, + shellCommandArgs: String? ) { statusWriter.writeOk() val buf = StringBuilder() @@ -42,7 +42,7 @@ class GetPropCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellH for (entry in device.properties) { buf.append("[${entry.key}]: [${entry.value}]\n") } - serviceOutput.writeStdout(buf.toString()) - serviceOutput.writeExitCode(0) + shellCommandOutput.writeStdout(buf.toString()) + shellCommandOutput.writeExitCode(0) } } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/LogcatCommandHandler.java b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/LogcatCommandHandler.java index ceb41f1a07..216382f53e 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/LogcatCommandHandler.java +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/LogcatCommandHandler.java @@ -22,7 +22,7 @@ import com.android.fakeadbserver.DeviceState; import com.android.fakeadbserver.DeviceState.LogcatChangeHandlerSubscriptionResult; import com.android.fakeadbserver.FakeAdbServer; import com.android.fakeadbserver.ShellProtocolType; -import com.android.fakeadbserver.services.ServiceOutput; +import com.android.fakeadbserver.services.ShellCommandOutput; import com.android.fakeadbserver.statechangehubs.ClientStateChangeHandlerFactory; import java.nio.charset.Charset; import java.util.Arrays; @@ -44,7 +44,7 @@ public class LogcatCommandHandler extends SimpleShellHandler { public void execute( @NonNull FakeAdbServer fakeAdbServer, @NonNull StatusWriter statusWriter, - @NonNull ServiceOutput serviceOutput, + @NonNull ShellCommandOutput shellCommandOutput, @NonNull DeviceState device, @NonNull String shellCommand, @Nullable String shellCommandArgs) { @@ -82,7 +82,7 @@ public class LogcatCommandHandler extends SimpleShellHandler { public Callable<HandlerResult> createLogcatMessageAdditionHandler( @NonNull String message) { return () -> { - serviceOutput.writeStdout( + shellCommandOutput.writeStdout( message.getBytes(Charset.defaultCharset())); return new HandlerResult(true); }; @@ -95,7 +95,7 @@ public class LogcatCommandHandler extends SimpleShellHandler { try { for (String message : subscriptionResult.mLogcatContents) { - serviceOutput.writeStdout(message); + shellCommandOutput.writeStdout(message); } while (true) { try { diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/PackageManagerCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/PackageManagerCommandHandler.kt index fc361b81b2..576219c6f3 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/PackageManagerCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/PackageManagerCommandHandler.kt @@ -18,19 +18,19 @@ package com.android.fakeadbserver.shellcommandhandlers import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput class PackageManagerCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandler( shellProtocolType, "pm" ) { override fun execute( - fakeAdbServer: FakeAdbServer, - statusWriter: StatusWriter, - serviceOutput: ServiceOutput, - device: DeviceState, - shellCommand: String, - shellCommandArgs: String? + fakeAdbServer: FakeAdbServer, + statusWriter: StatusWriter, + shellCommandOutput: ShellCommandOutput, + device: DeviceState, + shellCommand: String, + shellCommandArgs: String? ) { statusWriter.writeOk() @@ -44,6 +44,6 @@ class PackageManagerCommandHandler(shellProtocolType: ShellProtocolType) : Simpl shellCommandArgs?.let { params.addAll(it.split(" ")) } - device.serviceManager.processCommand(params, serviceOutput) + device.serviceManager.processCommand(params, shellCommandOutput) } } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/execcommandhandlers/PingExecCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/PingCommandHandler.kt index b817228677..51e07e6f6a 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/execcommandhandlers/PingExecCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/PingCommandHandler.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,31 +13,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.fakeadbserver.execcommandhandlers +package com.android.fakeadbserver.shellcommandhandlers -import com.android.fakeadbserver.CommandHandler import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer -import java.net.Socket - -class PingExecCommandHandler : SimpleExecHandler(PING_EXEC) { +import com.android.fakeadbserver.ShellProtocolType +import com.android.fakeadbserver.services.ShellCommandOutput +class PingCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandler( + shellProtocolType, "ping" +) { companion object { - - const val PING_EXEC = "ping" - const val PING_EXEC_OUTPUT = "pong" + const val PING_COMMAND_FAKE_OUTPUT = "pong" } override fun execute( - fakeAdbServer: FakeAdbServer, - responseSocket: Socket, - device: DeviceState, - args: String? + fakeAdbServer: FakeAdbServer, + statusWriter: StatusWriter, + shellCommandOutput: ShellCommandOutput, + device: DeviceState, + shellCommand: String, + shellCommandArgs: String? ) { - val output = responseSocket.getOutputStream() - CommandHandler.writeOkay(output) - - val response = PING_EXEC_OUTPUT - CommandHandler.writeString(output, response) + statusWriter.writeOk() + shellCommandOutput.writeStdout(PING_COMMAND_FAKE_OUTPUT) } } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/RmCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/RmCommandHandler.kt index a032ad67e7..2d65f0702e 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/RmCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/RmCommandHandler.kt @@ -18,24 +18,24 @@ package com.android.fakeadbserver.shellcommandhandlers import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput class RmCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandler( shellProtocolType, "rm" ) { override fun execute( - fakeAdbServer: FakeAdbServer, - statusWriter: StatusWriter, - serviceOutput: ServiceOutput, - device: DeviceState, - shellCommand: String, - shellCommandArgs: String? + fakeAdbServer: FakeAdbServer, + statusWriter: StatusWriter, + shellCommandOutput: ShellCommandOutput, + device: DeviceState, + shellCommand: String, + shellCommandArgs: String? ) { statusWriter.writeOk() if (shellCommandArgs == null) { - serviceOutput.writeStderr("rm: Needs 1 argument (see \"rm --help\")") + shellCommandOutput.writeStderr("rm: Needs 1 argument (see \"rm --help\")") return } val parameters = shellCommandArgs.split(" ") diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/SetPropCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/SetPropCommandHandler.kt index d5fed86e2b..8935d7a44e 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/SetPropCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/SetPropCommandHandler.kt @@ -18,19 +18,19 @@ package com.android.fakeadbserver.shellcommandhandlers import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput class SetPropCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandler( shellProtocolType, "setprop" ) { override fun execute( - fakeAdbServer: FakeAdbServer, - statusWriter: StatusWriter, - serviceOutput: ServiceOutput, - device: DeviceState, - shellCommand: String, - shellCommandArgs: String? + fakeAdbServer: FakeAdbServer, + statusWriter: StatusWriter, + shellCommandOutput: ShellCommandOutput, + device: DeviceState, + shellCommand: String, + shellCommandArgs: String? ) { statusWriter.writeOk() } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/ShellHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/ShellHandler.kt index d132d08426..8afb17337c 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/ShellHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/ShellHandler.kt @@ -19,7 +19,7 @@ import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType import com.android.fakeadbserver.devicecommandhandlers.DeviceCommandHandler -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput import com.google.common.base.Charsets import java.net.Socket @@ -76,18 +76,18 @@ abstract class ShellHandler protected constructor( * This is the main execution method of the command. * * @param fakeAdbServer Fake ADB Server itself. - * @param serviceOutput Shell protocol for standard in/out + * @param shellCommandOutput Shell protocol for standard in/out * @param device Target device for the command, if any. * @param shellCommand Shell command, e.g. for "adb shell ls -l" [shellCommand] would be "ls" * @param shellCommandArgs Arguments for the command, e.g. for "adb shell ls -l" [shellCommandArgs] would be "-l" */ abstract fun execute( - fakeAdbServer: FakeAdbServer, - statusWriter: StatusWriter, - serviceOutput: ServiceOutput, - device: DeviceState, - shellCommand: String, - shellCommandArgs: String? + fakeAdbServer: FakeAdbServer, + statusWriter: StatusWriter, + shellCommandOutput: ShellCommandOutput, + device: DeviceState, + shellCommand: String, + shellCommandArgs: String? ) } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/ShellProtocolEchoCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/ShellProtocolEchoCommandHandler.kt index 817b717118..ae520d624c 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/ShellProtocolEchoCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/ShellProtocolEchoCommandHandler.kt @@ -19,7 +19,7 @@ import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType import com.android.fakeadbserver.ShellV2Protocol -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput import java.nio.ByteBuffer /** @@ -32,12 +32,12 @@ class ShellProtocolEchoCommandHandler() : SimpleShellHandler( ) { override fun execute( - fakeAdbServer: FakeAdbServer, - statusWriter: StatusWriter, - serviceOutput: ServiceOutput, - device: DeviceState, - shellCommand: String, - shellCommandArgs: String? + fakeAdbServer: FakeAdbServer, + statusWriter: StatusWriter, + shellCommandOutput: ShellCommandOutput, + device: DeviceState, + shellCommand: String, + shellCommandArgs: String? ) { // Forward `stdin`, `stderr` and `exit` lines as `stdout` packets statusWriter.writeOk() @@ -48,14 +48,14 @@ class ShellProtocolEchoCommandHandler() : SimpleShellHandler( val stdinProcessor = StdinProcessor { line -> when { line.startsWith(stdoutPrefix) -> { - serviceOutput.writeStdout( + shellCommandOutput.writeStdout( line.takeLast(line.length - stdoutPrefix.length) .trimStart() ) } line.startsWith(stderrPrefix) -> { - serviceOutput.writeStderr( + shellCommandOutput.writeStderr( line.takeLast(line.length - stderrPrefix.length) .trimStart() ) @@ -70,10 +70,10 @@ class ShellProtocolEchoCommandHandler() : SimpleShellHandler( } while (true) { val buffer = ByteArray(100) - val numRead = serviceOutput.readStdin(buffer, 0, buffer.size) + val numRead = shellCommandOutput.readStdin(buffer, 0, buffer.size) if (numRead < 0) { stdinProcessor.flush() - serviceOutput.writeExitCode(exitCode) + shellCommandOutput.writeExitCode(exitCode) break } stdinProcessor.process(if (numRead == buffer.size) buffer else buffer.copyOfRange( diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/StatCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/StatCommandHandler.kt index 4524fcf9bf..bdb10e9325 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/StatCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/StatCommandHandler.kt @@ -18,7 +18,7 @@ package com.android.fakeadbserver.shellcommandhandlers import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput class StatCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandler( shellProtocolType, @@ -28,12 +28,12 @@ class StatCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHand val PROC_ID_REG = Regex("/proc/(\\d+)") override fun execute( - fakeAdbServer: FakeAdbServer, - statusWriter: StatusWriter, - serviceOutput: ServiceOutput, - device: DeviceState, - shellCommand: String, - shellCommandArgs: String? + fakeAdbServer: FakeAdbServer, + statusWriter: StatusWriter, + shellCommandOutput: ShellCommandOutput, + device: DeviceState, + shellCommand: String, + shellCommandArgs: String? ) { val appId = getAppId(device, shellCommandArgs) if (appId == null) { @@ -42,7 +42,7 @@ class StatCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHand } statusWriter.writeOk() - serviceOutput.writeStdout("package:$appId ") + shellCommandOutput.writeStdout("package:$appId ") } private fun getAppId(device: DeviceState, args: String?): String? { diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/WindowManagerCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/WindowManagerCommandHandler.kt index 38b35858e6..3aa3eca0a1 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/WindowManagerCommandHandler.kt +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/WindowManagerCommandHandler.kt @@ -18,19 +18,19 @@ package com.android.fakeadbserver.shellcommandhandlers import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput class WindowManagerCommandHandler(shellProtocolType: ShellProtocolType) : SimpleShellHandler( shellProtocolType, "wm" ) { override fun execute( - fakeAdbServer: FakeAdbServer, - statusWriter: StatusWriter, - serviceOutput: ServiceOutput, - device: DeviceState, - shellCommand: String, - shellCommandArgs: String? + fakeAdbServer: FakeAdbServer, + statusWriter: StatusWriter, + shellCommandOutput: ShellCommandOutput, + device: DeviceState, + shellCommand: String, + shellCommandArgs: String? ) { statusWriter.writeOk() } diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/WriteNoStopCommandHandler.java b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/WriteNoStopCommandHandler.java index 19ea481835..f2743eb8c9 100644 --- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/WriteNoStopCommandHandler.java +++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/WriteNoStopCommandHandler.java @@ -20,7 +20,7 @@ import com.android.annotations.Nullable; import com.android.fakeadbserver.DeviceState; import com.android.fakeadbserver.FakeAdbServer; import com.android.fakeadbserver.ShellProtocolType; -import com.android.fakeadbserver.services.ServiceOutput; +import com.android.fakeadbserver.services.ShellCommandOutput; /** shell:write-no-stop continuously write to the output stream without stopping. */ public class WriteNoStopCommandHandler extends SimpleShellHandler { @@ -33,14 +33,14 @@ public class WriteNoStopCommandHandler extends SimpleShellHandler { public void execute( @NonNull FakeAdbServer fakeAdbServer, @NonNull StatusWriter statusWriter, - @NonNull ServiceOutput serviceOutput, + @NonNull ShellCommandOutput shellCommandOutput, @NonNull DeviceState device, @NonNull String shellCommand, @Nullable String shellCommandArgs) { try { statusWriter.writeOk(); // Send ok first. while (true) { - serviceOutput.writeStdout("write-no-stop test in progress\n"); + shellCommandOutput.writeStdout("write-no-stop test in progress\n"); Thread.sleep(200); } } catch (InterruptedException ignored) { diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/ExecutionImpl.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/ExecutionImpl.kt new file mode 100644 index 0000000000..3ea45bb5ce --- /dev/null +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/ExecutionImpl.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2023 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.tools.firebase.testlab.gradle + +import com.google.firebase.testlab.gradle.Execution + +abstract class ExecutionImpl : Execution { + init { + timeoutMinutes = 15 + + maxTestReruns = 0 + + failFast = false + + numUniformShards = 0 + } +} diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/FixtureImpl.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/FixtureImpl.kt new file mode 100644 index 0000000000..0418fbbdaf --- /dev/null +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/FixtureImpl.kt @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2023 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.tools.firebase.testlab.gradle + +import com.google.firebase.testlab.gradle.Fixture + +abstract class FixtureImpl : Fixture { + private var _grantedPermissions: GrantedPermissions = GrantedPermissions.ALL + override var grantedPermissions: String + set(value) { + _grantedPermissions = try { + GrantedPermissions.valueOf(value.uppercase()) + } catch (_: IllegalArgumentException) { + error("$value is invalid. Available options are " + + "[${GrantedPermissions.values().joinToString(", ")}].") + } + } + get() = _grantedPermissions.name + + /** + * Supported options for [grantedPermissions]. + */ + enum class GrantedPermissions { + /** + * All permissions are granted. + */ + ALL, + + /** + * No permissions are granted. + */ + NONE, + } +} diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/ManagedDeviceImpl.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/ManagedDeviceImpl.kt index ba26af15d7..0b8953bdce 100644 --- a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/ManagedDeviceImpl.kt +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/ManagedDeviceImpl.kt @@ -17,7 +17,6 @@ package com.android.tools.firebase.testlab.gradle import com.google.firebase.testlab.gradle.ManagedDevice -import com.google.firebase.testlab.gradle.Orientation import javax.inject.Inject import org.gradle.api.tasks.Input import org.gradle.api.tasks.Internal @@ -36,8 +35,34 @@ open class ManagedDeviceImpl @Inject constructor(private val name: String) : Man @get:Input override var apiLevel = -1 + private var _orientation: Orientation = Orientation.DEFAULT + @get:Input - override var orientation = Orientation.DEFAULT + override var orientation: String + set(value) { + _orientation = try { + Orientation.valueOf(value.uppercase()) + } catch (_: IllegalArgumentException) { + error("$value is invalid. Available options are " + + "[${Orientation.values().joinToString(", ")}].") + } + } + get() { + return _orientation.name + } + + /** + * Specifies the Orientation that tests should be run on the [ManagedDevice] + */ + enum class Orientation { + /** The default orientation for that device. */ + DEFAULT, + /** Explicitly set the orientation to portrait. */ + PORTRAIT, + /** Explicitly set the orientation to landscape. */ + LANDSCAPE, + } + @get:Input override var locale = "en-US" diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/ResultsImpl.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/ResultsImpl.kt new file mode 100644 index 0000000000..35ba81ebe7 --- /dev/null +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/ResultsImpl.kt @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2023 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.tools.firebase.testlab.gradle + +import com.google.firebase.testlab.gradle.Results + +abstract class ResultsImpl : Results { + + init { + recordVideo = false + + performanceMetrics = false + } +} diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/TestLabGradlePlugin.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/TestLabGradlePlugin.kt index 6f763e39c1..04909d3a6e 100644 --- a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/TestLabGradlePlugin.kt +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/TestLabGradlePlugin.kt @@ -43,6 +43,11 @@ class TestLabGradlePlugin : Plugin<Project> { error("Android Gradle plugin version 8.1.0-alpha09 or higher is required." + " Current version is $agpVersion.") } + if (agpVersion >= AndroidPluginVersion(8, 3, 0).alpha(1) && + agpVersion.previewType != "dev") { + error("Firebase TestLab plugin is an experimental feature. It requires Android " + + "Gradle plugin version 8.2.0. Current version is $agpVersion.") + } // Registering with the Device registry will take care of the test options binding. project.extensions.getByType(AndroidComponentsExtension::class.java) @@ -68,7 +73,7 @@ class TestLabGradlePlugin : Plugin<Project> { TestLabBuildService.RegistrationAction( project.extensions.getByType(TestLabGradlePluginExtension::class.java), project.providers, - ).registerIfAbsent(project.gradle.sharedServices) + ).registerIfAbsent(project) } } } diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/TestLabGradlePluginExtensionImpl.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/TestLabGradlePluginExtensionImpl.kt index 686833eedc..dab4ec103c 100644 --- a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/TestLabGradlePluginExtensionImpl.kt +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/TestLabGradlePluginExtensionImpl.kt @@ -19,8 +19,9 @@ package com.android.tools.firebase.testlab.gradle import com.android.build.api.dsl.ManagedDevices import com.google.firebase.testlab.gradle.ManagedDevice import com.google.firebase.testlab.gradle.TestLabGradlePluginExtension +import com.google.firebase.testlab.gradle.TestOptions +import org.gradle.api.Action import org.gradle.api.NamedDomainObjectContainer -import org.gradle.api.file.RegularFileProperty import org.gradle.api.model.ObjectFactory import javax.inject.Inject @@ -28,10 +29,6 @@ abstract class TestLabGradlePluginExtensionImpl @Inject constructor( objectFactory: ObjectFactory, devicesBlock: ManagedDevices ): TestLabGradlePluginExtension { - - override val serviceAccountCredentials: RegularFileProperty = - objectFactory.fileProperty() - override val managedDevices: NamedDomainObjectContainer<ManagedDevice> = objectFactory.domainObjectContainer( ManagedDevice::class.java, @@ -41,5 +38,14 @@ abstract class TestLabGradlePluginExtensionImpl @Inject constructor( devicesBlock.devices.add(device) } } + override val testOptions: TestOptions = objectFactory.newInstance(TestOptionsImpl::class.java) + + override fun testOptions(action: TestOptions.() -> Unit) { + testOptions.action() + } + // Runtime only for groovy decorator to generate the closure based block. + fun testOptions(action: Action<TestOptions>) { + action.execute(testOptions) + } } diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/TestOptionsImpl.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/TestOptionsImpl.kt new file mode 100644 index 0000000000..440a1aa282 --- /dev/null +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/TestOptionsImpl.kt @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2023 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.tools.firebase.testlab.gradle + +import com.google.firebase.testlab.gradle.Execution +import com.google.firebase.testlab.gradle.Results +import com.google.firebase.testlab.gradle.Fixture +import com.google.firebase.testlab.gradle.TestOptions +import org.gradle.api.Action +import org.gradle.api.model.ObjectFactory +import javax.inject.Inject + +abstract class TestOptionsImpl @Inject constructor(objectFactory: ObjectFactory) : TestOptions { + override val fixture: Fixture = objectFactory.newInstance(FixtureImpl::class.java) + + // (Implementing interface for kotlin) + override fun fixture(action: Fixture.() -> Unit) { + fixture.action() + } + + // Runtime only for groovy decorator to generate the closure based block. + fun fixture(action: Action<Fixture>) { + action.execute(fixture) + } + + override val execution: Execution = objectFactory.newInstance(ExecutionImpl::class.java) + + // (Implementing interface for kotlin) + override fun execution(action: Execution.() -> Unit) { + execution.action() + } + + // Runtime only for groovy decorator to generate the closure based block. + fun execution(action: Action<Execution>) { + action.execute(execution) + } + + override val results: Results = objectFactory.newInstance(ResultsImpl::class.java) + + // (Implementing interface for kotlin) + override fun results(action: Results.() -> Unit) { + results.action() + } + + // Runtime only for groovy decorator to generate the closure based block. + fun results(action: Action<Results>) { + action.execute(results) + } +} diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/device/DeviceTestRunInput.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/device/DeviceTestRunInput.kt index f3c5a6d5ee..190dabea2a 100644 --- a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/device/DeviceTestRunInput.kt +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/device/DeviceTestRunInput.kt @@ -17,7 +17,8 @@ package com.android.tools.firebase.testlab.gradle.device import com.android.tools.firebase.testlab.gradle.services.TestLabBuildService -import com.google.firebase.testlab.gradle.Orientation +import com.android.tools.firebase.testlab.gradle.ManagedDeviceImpl.Orientation +import org.gradle.api.provider.MapProperty import org.gradle.api.provider.Property import org.gradle.api.tasks.Input import org.gradle.api.tasks.Internal @@ -39,4 +40,10 @@ abstract class DeviceTestRunInput: @get: Internal abstract val buildService: Property<TestLabBuildService> + + @get: Input + abstract val numUniformShards: Property<Int> + + @get:Input + abstract val extraDeviceFiles: MapProperty<String, String> } diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/device/SetupConfigureAction.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/device/SetupConfigureAction.kt index fe149b6801..d3db0999bc 100644 --- a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/device/SetupConfigureAction.kt +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/device/SetupConfigureAction.kt @@ -19,13 +19,13 @@ package com.android.tools.firebase.testlab.gradle.device import com.android.build.api.instrumentation.manageddevice.DeviceSetupConfigureAction import com.android.tools.firebase.testlab.gradle.services.TestLabBuildService import com.google.firebase.testlab.gradle.ManagedDevice +import org.gradle.api.Project import org.gradle.api.model.ObjectFactory -import org.gradle.api.services.BuildServiceRegistry import javax.inject.Inject open class SetupConfigureAction @Inject constructor( private val objectFactory: ObjectFactory, - private val buildServiceRegistry: BuildServiceRegistry, + private val project: Project, ) : DeviceSetupConfigureAction<ManagedDevice, DeviceSetupInput> { override fun configureTaskInput(deviceDsl: ManagedDevice): DeviceSetupInput { @@ -39,8 +39,7 @@ open class SetupConfigureAction @Inject constructor( apiLevel.set(deviceDsl.apiLevel) apiLevel.disallowChanges() - buildService.set( - TestLabBuildService.RegistrationAction.getBuildService(buildServiceRegistry)) + buildService.set(TestLabBuildService.RegistrationAction.getBuildService(project)) buildService.disallowChanges() } } diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/device/TestRunConfigureAction.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/device/TestRunConfigureAction.kt index abd5482b96..138002c5c2 100644 --- a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/device/TestRunConfigureAction.kt +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/device/TestRunConfigureAction.kt @@ -17,15 +17,18 @@ package com.android.tools.firebase.testlab.gradle.device import com.android.build.api.instrumentation.manageddevice.DeviceTestRunConfigureAction +import com.android.tools.firebase.testlab.gradle.ManagedDeviceImpl import com.android.tools.firebase.testlab.gradle.services.TestLabBuildService import com.google.firebase.testlab.gradle.ManagedDevice -import javax.inject.Inject +import org.gradle.api.Project import org.gradle.api.model.ObjectFactory -import org.gradle.api.services.BuildServiceRegistry +import org.gradle.api.provider.ProviderFactory +import javax.inject.Inject open class TestRunConfigureAction @Inject constructor( private val objectFactory: ObjectFactory, - private val buildServiceRegistry: BuildServiceRegistry, + private val providerFactory: ProviderFactory, + private val project: Project, ): DeviceTestRunConfigureAction<ManagedDevice, DeviceTestRunInput> { override fun configureTaskInput(deviceDSL: ManagedDevice): DeviceTestRunInput = @@ -36,14 +39,22 @@ open class TestRunConfigureAction @Inject constructor( apiLevel.set(deviceDSL.apiLevel) apiLevel.disallowChanges() - orientation.set(deviceDSL.orientation) + orientation.set(ManagedDeviceImpl.Orientation.valueOf(deviceDSL.orientation)) orientation.disallowChanges() locale.set(deviceDSL.locale) locale.disallowChanges() buildService.set( - TestLabBuildService.RegistrationAction.getBuildService(buildServiceRegistry)) + TestLabBuildService.RegistrationAction.getBuildService(project)) buildService.disallowChanges() + + numUniformShards.set( + providerFactory.provider { buildService.get().numUniformShards }) + numUniformShards.disallowChanges() + + extraDeviceFiles.set(providerFactory.provider { + buildService.get().parameters.extraDeviceFiles.get() }) + extraDeviceFiles.disallowChanges() } } diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/services/TestLabBuildService.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/services/TestLabBuildService.kt index cd5515a052..e3a138d014 100644 --- a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/services/TestLabBuildService.kt +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/android/tools/firebase/testlab/gradle/services/TestLabBuildService.kt @@ -18,6 +18,8 @@ package com.android.tools.firebase.testlab.gradle.services import com.android.build.api.instrumentation.StaticTestData import com.android.builder.testing.api.DeviceConfigProvider +import com.android.tools.firebase.testlab.gradle.FixtureImpl +import com.android.tools.firebase.testlab.gradle.ManagedDeviceImpl import com.android.tools.firebase.testlab.gradle.UtpTestSuiteResultMerger import com.android.tools.utp.plugins.host.device.info.proto.AndroidTestDeviceInfoProto import com.google.api.client.googleapis.auth.oauth2.GoogleCredential @@ -26,6 +28,7 @@ import com.google.api.client.googleapis.util.Utils import com.google.api.client.http.GenericUrl import com.google.api.client.http.HttpRequestFactory import com.google.api.client.http.HttpRequestInitializer +import com.google.api.client.http.HttpTransport import com.google.api.client.http.InputStreamContent import com.google.api.client.json.GenericJson import com.google.api.client.json.JsonObjectParser @@ -40,15 +43,19 @@ import com.google.api.services.testing.model.AndroidDeviceList import com.google.api.services.testing.model.AndroidInstrumentationTest import com.google.api.services.testing.model.AndroidModel import com.google.api.services.testing.model.ClientInfo +import com.google.api.services.testing.model.DeviceFile import com.google.api.services.testing.model.EnvironmentMatrix import com.google.api.services.testing.model.GoogleCloudStorage +import com.google.api.services.testing.model.RegularFile import com.google.api.services.testing.model.ResultStorage import com.google.api.services.testing.model.TestExecution import com.google.api.services.testing.model.TestMatrix +import com.google.api.services.testing.model.TestSetup import com.google.api.services.testing.model.TestSpecification +import com.google.api.services.testing.model.ToolResultsHistory import com.google.api.services.toolresults.ToolResults +import com.google.api.services.toolresults.model.History import com.google.api.services.toolresults.model.StackTrace -import com.google.firebase.testlab.gradle.Orientation import com.google.firebase.testlab.gradle.TestLabGradlePluginExtension import com.google.testing.platform.proto.api.core.ErrorProto.Error import com.google.testing.platform.proto.api.core.IssueProto.Issue @@ -61,14 +68,16 @@ import com.google.testing.platform.proto.api.core.TestResultProto.TestResult import com.google.testing.platform.proto.api.core.TestStatusProto.TestStatus import com.google.testing.platform.proto.api.core.TestSuiteResultProto.TestSuiteMetaData import com.google.testing.platform.proto.api.core.TestSuiteResultProto.TestSuiteResult +import org.gradle.api.Project import org.gradle.api.file.RegularFileProperty import org.gradle.api.logging.Logging +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.MapProperty import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.provider.ProviderFactory import org.gradle.api.services.BuildService import org.gradle.api.services.BuildServiceParameters -import org.gradle.api.services.BuildServiceRegistry import org.w3c.dom.Element import org.w3c.dom.Node import java.io.File @@ -77,6 +86,8 @@ import java.io.FileOutputStream import java.nio.charset.StandardCharsets import java.util.Locale import java.util.UUID +import java.util.logging.Level +import java.util.logging.Logger import javax.xml.parsers.DocumentBuilderFactory import javax.xml.transform.TransformerFactory import javax.xml.transform.dom.DOMSource @@ -87,12 +98,20 @@ import javax.xml.transform.stream.StreamResult */ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters> { + init { + Logger.getLogger("com.google.api.client").level = Level.WARNING + } + companion object { const val TEST_RESULT_PB_FILE_NAME = "test-result.pb" const val clientApplicationName: String = "Firebase TestLab Gradle Plugin" const val xGoogUserProjectHeaderKey: String = "X-Goog-User-Project" val cloudStorageUrlRegex = Regex("""gs://(.*?)/(.*)""") + const val INSTRUMENTATION_TEST_SHARD_FIELD = "shardingOption" + const val TEST_MATRIX_FLAKY_TEST_ATTEMPTS_FIELD = "flakyTestAttempts" + const val TEST_MATRIX_FAIL_FAST_FIELD = "failFast" + const val CHECK_TEST_STATE_WAIT_MS = 10 * 1000L; val oauthScope = listOf( @@ -133,6 +152,14 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters class FileReference: GenericJson() { @Key var fileUri: String? = null } + + class UniformSharding: GenericJson() { + @Key var numShards: Int? = null + } + + class ShardingOption: GenericJson() { + @Key var uniformSharding: UniformSharding? = null + } } private val logger = Logging.getLogger(this.javaClass) @@ -143,10 +170,24 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters interface Parameters : BuildServiceParameters { val quotaProjectName: Property<String> val credentialFile: RegularFileProperty + val cloudStorageBucket: Property<String> + val timeoutMinutes: Property<Int> + val maxTestReruns: Property<Int> + val failFast: Property<Boolean> + val numUniformShards: Property<Int> + val grantedPermissions: Property<String> + val extraDeviceFiles: MapProperty<String, String> + val networkProfile: Property<String> + val resultsHistoryName: Property<String> + val directoriesToPull: ListProperty<String> + val recordVideo: Property<Boolean> + val performanceMetrics: Property<Boolean> } - private val credential = parameters.credentialFile.get().asFile.inputStream().use { - GoogleCredential.fromStream(it).createScoped(oauthScope) + internal open val credential: GoogleCredential by lazy { + parameters.credentialFile.get().asFile.inputStream().use { + GoogleCredential.fromStream(it).createScoped(oauthScope) + } } private val httpRequestInitializer: HttpRequestInitializer = HttpRequestInitializer { request -> @@ -157,12 +198,17 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters private val jacksonFactory: JacksonFactory get() = JacksonFactory.getDefaultInstance() + internal open val httpTransport: HttpTransport + get() = GoogleNetHttpTransport.newTrustedTransport() + val numUniformShards: Int + get() = parameters.numUniformShards.getOrNull() ?: 0 + fun runTestsOnDevice( deviceName: String, deviceId: String, deviceApiLevel: Int, deviceLocale: Locale, - deviceOrientation: Orientation, + deviceOrientation: ManagedDeviceImpl.Orientation, ftlDeviceModel: AndroidModel, testData: StaticTestData, resultsOutDir: File, @@ -176,21 +222,23 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters } val projectName = parameters.quotaProjectName.get() - val requestId = UUID.randomUUID().toString() + val runRequestId = UUID.randomUUID().toString() val toolResultsClient = ToolResults.Builder( - GoogleNetHttpTransport.newTrustedTransport(), + httpTransport, jacksonFactory, httpRequestInitializer ).apply { applicationName = clientApplicationName }.build() - val defaultBucketName = toolResultsClient.projects().initializeSettings(projectName) - .execute().defaultBucket + val initSettingsResult = + toolResultsClient.projects().initializeSettings(projectName).execute() + val bucketName = parameters.cloudStorageBucket.orNull?.ifBlank { null } + ?: initSettingsResult.defaultBucket val storageClient = Storage.Builder( - GoogleNetHttpTransport.newTrustedTransport(), + httpTransport, jacksonFactory, httpRequestInitializer ).apply { @@ -198,7 +246,7 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters }.build() val testApkStorageObject = uploadToCloudStorage( - testData.testApk, requestId, storageClient, defaultBucketName + testData.testApk, runRequestId, storageClient, bucketName ) val configProvider = createConfigProvider( @@ -206,13 +254,13 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters ) val appApkStorageObject = uploadToCloudStorage( testData.testedApkFinder(configProvider).first(), - requestId, + runRequestId, storageClient, - defaultBucketName + bucketName ) val testingClient = Testing.Builder( - GoogleNetHttpTransport.newTrustedTransport(), + httpTransport, jacksonFactory, httpRequestInitializer ).apply { @@ -221,22 +269,61 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters val testMatricesClient = testingClient.projects().testMatrices() + val testHistoryName = parameters.resultsHistoryName.getOrElse("").ifBlank { + testData.testedApplicationId ?: testData.applicationId + } + val historyId = getOrCreateHistory(toolResultsClient, projectName, testHistoryName) + val testMatrix = TestMatrix().apply { projectId = projectName clientInfo = ClientInfo().apply { name = clientApplicationName } testSpecification = TestSpecification().apply { + testSetup = TestSetup().apply { + set("dontAutograntPermissions", parameters.grantedPermissions.orNull == + FixtureImpl.GrantedPermissions.NONE.name) + if(parameters.networkProfile.getOrElse("").isNotBlank()) { + networkProfile = parameters.networkProfile.get() + } + filesToPush = mutableListOf() + parameters.extraDeviceFiles.get().forEach { (onDevicePath, filePath) -> + val gcsFilePath = if (filePath.startsWith("gs://")) { + filePath + } else { + val file = File(filePath) + check(file.exists()) { "$filePath doesn't exist." } + check(file.isFile) { "$filePath must be file." } + val storageObject = uploadToCloudStorage( + file, runRequestId, storageClient, bucketName) + "gs://$bucketName/${storageObject.name}" + } + filesToPush.add(DeviceFile().apply { + regularFile = RegularFile().apply { + content = com.google.api.services.testing.model.FileReference().apply { + gcsPath = gcsFilePath + } + devicePath = onDevicePath + } + }) + } + + directoriesToPull = parameters.directoriesToPull.get() + } androidInstrumentationTest = AndroidInstrumentationTest().apply { testApk = com.google.api.services.testing.model.FileReference().apply { - gcsPath = "gs://$defaultBucketName/${testApkStorageObject.name}" + gcsPath = "gs://$bucketName/${testApkStorageObject.name}" } appApk = com.google.api.services.testing.model.FileReference().apply { - gcsPath = "gs://$defaultBucketName/${appApkStorageObject.name}" + gcsPath = "gs://$bucketName/${appApkStorageObject.name}" } appPackageId = testData.testedApplicationId testPackageId = testData.applicationId testRunnerClass = testData.instrumentationRunner + + createShardingOption()?.also { sharding -> + this.set(INSTRUMENTATION_TEST_SHARD_FIELD, sharding) + } } environmentMatrix = EnvironmentMatrix().apply { androidDeviceList = AndroidDeviceList().apply { @@ -252,17 +339,27 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters } resultStorage = ResultStorage().apply { googleCloudStorage = GoogleCloudStorage().apply { - gcsPath = "gs://$defaultBucketName/$requestId/results" + gcsPath = "gs://$bucketName/$runRequestId/results" + } + toolResultsHistory = ToolResultsHistory().apply { + projectId = projectName + this.historyId = historyId } } + testTimeout = "${parameters.timeoutMinutes.get() * 60}s" + disablePerformanceMetrics = !parameters.performanceMetrics.get() + disableVideoRecording = !parameters.recordVideo.get() } + set(TEST_MATRIX_FLAKY_TEST_ATTEMPTS_FIELD, parameters.maxTestReruns.get()) + set(TEST_MATRIX_FAIL_FAST_FIELD, parameters.failFast.get()) } val updatedTestMatrix = testMatricesClient.create(projectName, testMatrix).apply { - this.requestId = requestId + this.requestId = runRequestId }.execute() lateinit var resultTestMatrix: TestMatrix var previousTestMatrixState = "" + var printResultsUrl = true while (true) { val latestTestMatrix = testMatricesClient.get( projectName, updatedTestMatrix.testMatrixId).execute() @@ -270,6 +367,15 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters previousTestMatrixState = latestTestMatrix.state logger.lifecycle("Firebase TestLab Test execution state: $previousTestMatrixState") } + if (printResultsUrl) { + val resultsUrl = latestTestMatrix.resultStorage?.get("resultsUrl") as String? + if (!resultsUrl.isNullOrBlank()) { + logger.lifecycle( + "Test request for device $deviceName has been submitted to " + + "Firebase TestLab: $resultsUrl") + printResultsUrl = false + } + } val testFinished = when (latestTestMatrix.state) { "VALIDATING", "PENDING", "RUNNING" -> false else -> true @@ -296,7 +402,7 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters testExecution.toolResultsStep.stepId ).execute() executionStep.testExecutionStep.testSuiteOverviews?.forEach { suiteOverview -> - downloadFromCloudStorage(storageClient, suiteOverview.xmlSource.fileUri) { + downloadFromCloudStorage(storageClient, suiteOverview.xmlSource.fileUri, runRequestId) { File(resultsOutDir, "TEST-${it.replace("/", "_")}") }?.also { updateTestResultXmlFile(it, deviceName, projectPath, variantName) @@ -310,6 +416,7 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters deviceInfoFile, storageClient, resultsOutDir, + runRequestId, ) val testSuitePassed = testSuiteResult.testStatus.isPassedOrSkipped() @@ -334,9 +441,27 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters return ftlTestRunResults } + fun getOrCreateHistory( + toolResultsClient: ToolResults, + projectId: String, historyName: String): String { + val historyList = toolResultsClient.projects().histories().list(projectId).apply { + filterByName = historyName + }.execute() + historyList?.histories?.firstOrNull()?.historyId?.let { return it } + + return toolResultsClient.projects().histories().create( + projectId, + History().apply { + name = historyName + displayName = historyName + }).apply { + requestId = UUID.randomUUID().toString() + }.execute().historyId + } + fun catalog(): AndroidDeviceCatalog { val testingClient = Testing.Builder( - GoogleNetHttpTransport.newTrustedTransport(), + httpTransport, jacksonFactory, httpRequestInitializer, ).apply { @@ -350,6 +475,17 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters return catalog.androidDeviceCatalog } + private fun createShardingOption(): ShardingOption? { + if (numUniformShards == 0) { + return null + } + return ShardingOption().apply { + uniformSharding = UniformSharding().apply { + numShards = numUniformShards + } + } + } + private fun getTestSuiteResult( toolResultsClient: ToolResults, testMatrix: TestMatrix, @@ -357,6 +493,7 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters deviceInfoFile: File, storageClient: Storage, resultsOutDir: File, + runRequestId: String, ): TestSuiteResult { val testSuiteResult = TestSuiteResult.newBuilder() @@ -377,7 +514,7 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters testSuiteMetaData = TestSuiteMetaData.newBuilder().apply { testSuiteName = step.name var scheduledTestCount = 0 - for (testSuiteOverview in step.testExecutionStep.testSuiteOverviews) { + step.testExecutionStep.testSuiteOverviews?.forEach { testSuiteOverview -> scheduledTestCount += testSuiteOverview.totalCount } scheduledTestCaseCount = scheduledTestCount @@ -389,21 +526,25 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters "skipped" -> TestStatus.SKIPPED else -> TestStatus.TEST_STATUS_UNSPECIFIED } - addOutputArtifact( - Artifact.newBuilder().apply { - label = Label.newBuilder().apply { - label = "firebase.xmlSource" - namespace = "android" - }.build() - sourcePath = Path.newBuilder().apply { - path = step.testExecutionStep.testSuiteOverviews[0].xmlSource.fileUri - }.build() - type = ArtifactType.TEST_DATA - }.build() - ) + val testResultXmlFilePath = + step.testExecutionStep.testSuiteOverviews?.get(0)?.xmlSource?.fileUri.orEmpty() + if (testResultXmlFilePath.isNotBlank()) { + addOutputArtifact( + Artifact.newBuilder().apply { + label = Label.newBuilder().apply { + label = "firebase.xmlSource" + namespace = "android" + }.build() + sourcePath = Path.newBuilder().apply { + path = testResultXmlFilePath + }.build() + type = ArtifactType.TEST_DATA + }.build() + ) + } } - for (log in step.testExecutionStep.toolExecution.toolLogs) { + step.testExecutionStep.toolExecution?.toolLogs?.forEach { log -> testSuiteResult.apply { addOutputArtifact(Artifact.newBuilder().apply { label = Label.newBuilder().apply { @@ -418,7 +559,8 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters }.build()) } } - for (toolOutput in step.testExecutionStep.toolExecution.toolOutputs) { + + step.testExecutionStep.toolExecution?.toolOutputs?.forEach { toolOutput -> val outputArtifact = Artifact.newBuilder().apply { label = Label.newBuilder().apply { label = "firebase.toolOutput" @@ -462,7 +604,7 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters } } - for (testIssue in step.testExecutionStep.testIssues) { + step.testExecutionStep?.testIssues?.forEach { testIssue -> testSuiteResult.apply { addIssue(Issue.newBuilder().apply { message = testIssue.errorMessage @@ -483,10 +625,35 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters } } - // Need latest version of google-api-client to use + step.testExecutionStep?.toolExecution?.toolOutputs?.forEach { toolOutput -> + if (toolOutput?.output?.fileUri != null) { + val fileUri = requireNotNull(toolOutput.output.fileUri) + val download = parameters.directoriesToPull.get().any { directoriesToPull -> + fileUri.contains(directoriesToPull) + } + if (download) { + val downloadedFile = downloadFromCloudStorage( + storageClient, fileUri, runRequestId) { + File(resultsOutDir, it) + } ?: return@forEach + testSuiteResult.addOutputArtifactBuilder().apply { + labelBuilder.apply { + label = "firebase.toolOutput" + namespace = "android" + } + sourcePathBuilder.apply { + path = downloadedFile.path + }.build() + type = ArtifactType.TEST_DATA + } + } + } + } + + // Need the latest version of google-api-client to use // toolResultsClient.projects().histories().executions().steps().testCases().list(). // Manually calling this API until this is available. - val httpRequestFactory: HttpRequestFactory = GoogleNetHttpTransport.newTrustedTransport().createRequestFactory(httpRequestInitializer) + val httpRequestFactory: HttpRequestFactory = httpTransport.createRequestFactory(httpRequestInitializer) val url = "https://toolresults.googleapis.com/toolresults/v1beta3/projects/$projectId/histories/$historyId/executions/$executionId/steps/$stepId/testCases" val request = httpRequestFactory.buildGetRequest(GenericUrl(url)) val parser = JsonObjectParser(Utils.getDefaultJsonFactory()) @@ -497,7 +664,7 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters it, StandardCharsets.UTF_8, TestCases::class.java ) - for (case in testCaseContents["testCases"] as List<TestCase>) { + (testCaseContents["testCases"] as? List<TestCase>)?.forEach { case -> testSuiteResult.apply { addTestResult(TestResult.newBuilder().apply { testCase = TestCaseProto.TestCase.newBuilder().apply { @@ -536,7 +703,8 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters for (toolOutput in (case.toolOutputs as List<ToolOutputReference>)) { if (toolOutput.output!!.fileUri!!.endsWith("logcat")) { val logcatFile = downloadFromCloudStorage( - storageClient, toolOutput.output!!.fileUri!!) { + storageClient, toolOutput.output!!.fileUri!!, + runRequestId) { File(resultsOutDir, it) } if (logcatFile != null) { @@ -551,17 +719,6 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters type = ArtifactType.TEST_DATA } } - } else { - addOutputArtifactBuilder().apply { - labelBuilder.apply { - label = "firebase.toolOutput" - namespace = "android" - } - sourcePathBuilder.apply { - path = toolOutput.output!!.fileUri - }.build() - type = ArtifactType.TEST_DATA - } } } } @@ -691,10 +848,10 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters */ private fun downloadFromCloudStorage( storageClient: Storage, fileUri: String, - destination: (objectName: String) -> File): File? { + runId: String, destination: (objectName: String) -> File): File? { val matchResult = cloudStorageUrlRegex.find(fileUri) ?: return null val (bucketName, objectName) = matchResult.destructured - return destination(objectName).apply { + return destination(objectName.removePrefix("$runId/")).apply { parentFile.mkdirs() outputStream().use { storageClient.objects() @@ -800,13 +957,13 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters * Copied from * com.android.build.gradle.internal.services.BuildServicesKt.getBuildServiceName. */ - private fun getBuildServiceName(type: Class<*>): String { - return type.name + "_" + perClassLoaderConstant + private fun getBuildServiceName(type: Class<*>, project: Project): String { + return type.name + "_" + perClassLoaderConstant + "_" + project.path } - fun getBuildService(registry: BuildServiceRegistry): Provider<TestLabBuildService> { - val serviceName = getBuildServiceName(TestLabBuildService::class.java) - return registry.registerIfAbsent( + fun getBuildService(project: Project): Provider<TestLabBuildService> { + val serviceName = getBuildServiceName(TestLabBuildService::class.java, project) + return project.gradle.sharedServices.registerIfAbsent( serviceName, TestLabBuildService::class.java, ) { @@ -879,9 +1036,9 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters /** * Register [TestLabBuildService] to a registry if absent. */ - fun registerIfAbsent(registry: BuildServiceRegistry): Provider<TestLabBuildService> { - return registry.registerIfAbsent( - getBuildServiceName(TestLabBuildService::class.java), + fun registerIfAbsent(project: Project): Provider<TestLabBuildService> { + return project.gradle.sharedServices.registerIfAbsent( + getBuildServiceName(TestLabBuildService::class.java, project), TestLabBuildService::class.java, ) { buildServiceSpec -> configure(buildServiceSpec.parameters) @@ -899,6 +1056,39 @@ abstract class TestLabBuildService : BuildService<TestLabBuildService.Parameters params.quotaProjectName.set(params.credentialFile.map { getQuotaProjectName(it.asFile) }) + params.cloudStorageBucket.set(providerFactory.provider { + testLabExtension.testOptions.results.cloudStorageBucket + }) + + params.timeoutMinutes.set(providerFactory.provider { + testLabExtension.testOptions.execution.timeoutMinutes + }) + params.maxTestReruns.set(providerFactory.provider { + testLabExtension.testOptions.execution.maxTestReruns + }) + params.failFast.set(providerFactory.provider { + testLabExtension.testOptions.execution.failFast + }) + params.numUniformShards.set( providerFactory.provider { + testLabExtension.testOptions.execution.numUniformShards + }) + params.grantedPermissions.set(providerFactory.provider { + testLabExtension.testOptions.fixture.grantedPermissions + }) + params.extraDeviceFiles.set(testLabExtension.testOptions.fixture.extraDeviceFiles) + params.networkProfile.set(providerFactory.provider { + testLabExtension.testOptions.fixture.networkProfile + }) + params.resultsHistoryName.set(providerFactory.provider { + testLabExtension.testOptions.results.resultsHistoryName + }) + params.directoriesToPull.set(testLabExtension.testOptions.results.directoriesToPull) + params.recordVideo.set(providerFactory.provider { + testLabExtension.testOptions.results.recordVideo + }) + params.performanceMetrics.set(providerFactory.provider { + testLabExtension.testOptions.results.performanceMetrics + }) } } } diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/Execution.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/Execution.kt new file mode 100644 index 0000000000..7616c44bfd --- /dev/null +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/Execution.kt @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2023 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.google.firebase.testlab.gradle + +import org.gradle.api.Incubating + +/** + * A DSL for configuring test execution. + */ +@Incubating +interface Execution { + /** + * The maximum time to run the test execution before cancellation + * measured in minutes. Does not include the setup/teardown of device and + * is handled server side. + * + * The maximum possible testing time is 45 minutes on physical devices + * and 60 minutes on virtual devices. As specified by FTL. + * + * Default value is 15 minutes. + */ + @get:Incubating + @set:Incubating + var timeoutMinutes: Int + + /** + * Number of times the test should be rerun if tests fail. + * The number of times a Test Execution should be re-attempted if one + * or more of its test cases fail. + * + * The maximum possible test reruns are 10. Default value is 0. + */ + @get:Incubating + @set:Incubating + var maxTestReruns: Int + + /** + * Ensures only a single attempt will be made for each execution if + * an infrastructure issue occurs. + * This does not affect [maxTestReruns]. Normally, 2 or more attempts + * are made by FTL if a potential infrastructure issue is detected. This + * is best enabled for latency sensitive workloads. The # of execution + * failures may be significantly greater with failFast enabled. + * + * Default value is false. + */ + @get:Incubating + @set:Incubating + var failFast: Boolean + + /** + * Specifies the number of shards across which to distribute test cases The shards are run + * in parallel on separate devices through FTL. + * + * This is based on the sharding mechanism AndroidJUnitRunner uses, and as such there is no + * guarantee that test cases will be distributed with perfect uniformity. + * + * The number of shards specified must always be a positive number that is no greater than the + * total number of test cases. + * + * For FTL physical devices the number of shards should be <= 50. + * + * For FTL virtual devices the number of shards should be <= 100. + * + * The Default value is 0, in which case, no uniform sharding will be used. + */ + @get:Incubating + @set:Incubating + var numUniformShards: Int +} diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/Fixture.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/Fixture.kt new file mode 100644 index 0000000000..76fac8104f --- /dev/null +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/Fixture.kt @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2023 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.google.firebase.testlab.gradle + +import org.gradle.api.Incubating +import org.gradle.api.provider.MapProperty + +/** + * A DSL for configuring test fixture. + */ +@Incubating +interface Fixture { + /** + * Whether to grant permissions on the device before tests begin. + * + * Value must be "all" or "none". By default, all permissions are granted. + */ + @get:Incubating + @set:Incubating + var grantedPermissions: String + + /** + * Map of files to push to the device before starting the test. + * + * The key is location on the device. + * The value is the location of the file, either local or in Google Cloud. + */ + @get:Incubating + val extraDeviceFiles: MapProperty<String, String> + + /** + * The name of the network traffic profile + * + * Specifies network conditions to emulate when running tests. + */ + @get:Incubating + var networkProfile: String +} diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/ManagedDevice.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/ManagedDevice.kt index b2ec77231d..a7e341ee4f 100644 --- a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/ManagedDevice.kt +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/ManagedDevice.kt @@ -47,8 +47,10 @@ interface ManagedDevice : Device { /** * The orientation the device should have when tests are run. + * + * Available options are ["DEFAULT", "PORTRAIT", "LANDSCAPE"] */ - var orientation: Orientation + var orientation: String /** * The locale that the device should be set to. diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/Results.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/Results.kt new file mode 100644 index 0000000000..a409740566 --- /dev/null +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/Results.kt @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2023 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.google.firebase.testlab.gradle + +import org.gradle.api.Incubating +import org.gradle.api.provider.ListProperty + +/** + * A DSL for configuring test results. + */ +@Incubating +interface Results { + /** + * The name of the cloud storage bucket where the test results will be stored. + * + * If unspecified, Firebase provides the default bucket. + */ + @get:Incubating + @set:Incubating + var cloudStorageBucket: String + + /** + * History name of test results. + * + * All tests with the same history name will have their results grouped + * together in the Firebase console in a time-ordered test history list. + * + * If unspecified, the application label in Android manifest is used. + */ + @get:Incubating + @set:Incubating + var resultsHistoryName: String + + /** + * List of paths that will be copied from the test device's storage to the test result folder. + * + * This will copy from GCloud to local storage. + * These must be absolute paths under /sdcard or /data/local/tmp. + */ + @get:Incubating + val directoriesToPull: ListProperty<String> + + /** + * Enable Video recording during the test. + * + * Default value is false. + */ + @get:Incubating + @set:Incubating + var recordVideo: Boolean + + /** + * Whether performance metrics are enabled. + * Monitor and record performance metrics: CPU, memory, network usage, etc. + * + * Default value is false. + */ + @get:Incubating + @set:Incubating + var performanceMetrics: Boolean +} diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/TestLabGradlePluginExtension.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/TestLabGradlePluginExtension.kt index 2371310128..e49aa988a0 100644 --- a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/TestLabGradlePluginExtension.kt +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/TestLabGradlePluginExtension.kt @@ -26,7 +26,6 @@ import org.gradle.api.file.RegularFileProperty */ @Incubating interface TestLabGradlePluginExtension { - /** * A path to a JSON file that contains service account credentials to access to * a Firebase TestLab project. @@ -43,4 +42,12 @@ interface TestLabGradlePluginExtension { @get:Incubating val managedDevices: NamedDomainObjectContainer<ManagedDevice> + /** + * A configuration block for test options. + */ + @get:Incubating + val testOptions: TestOptions + + @Incubating + fun testOptions(action: TestOptions.() -> Unit) } diff --git a/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/TestOptions.kt b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/TestOptions.kt new file mode 100644 index 0000000000..2bab5abbbb --- /dev/null +++ b/firebase/testlab/testlab-gradle-plugin/src/main/java/com/google/firebase/testlab/gradle/TestOptions.kt @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2023 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.google.firebase.testlab.gradle + +import org.gradle.api.Incubating + +/** + * A DSL for configuring test options. + */ +@Incubating +interface TestOptions { + /** + * A configuration block for test setup options. + */ + @get:Incubating + val fixture: Fixture + + @Incubating + fun fixture(action: Fixture.() -> Unit) + + /** + * A configuration block for test execution options. + */ + @get:Incubating + val execution: Execution + + @Incubating + fun execution(action: Execution.() -> Unit) + + /** + * A configuration block for test results options. + */ + @get:Incubating + val results: Results + + @Incubating + fun results(action: Results.() -> Unit) +} diff --git a/firebase/testlab/testlab-gradle-plugin/src/test/java/com/android/tools/firebase/testlab/gradle/TestLabGradlePluginTest.kt b/firebase/testlab/testlab-gradle-plugin/src/test/java/com/android/tools/firebase/testlab/gradle/TestLabGradlePluginTest.kt new file mode 100644 index 0000000000..25bc3c529d --- /dev/null +++ b/firebase/testlab/testlab-gradle-plugin/src/test/java/com/android/tools/firebase/testlab/gradle/TestLabGradlePluginTest.kt @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2023 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.tools.firebase.testlab.gradle + +import com.android.build.api.AndroidPluginVersion +import com.android.build.api.dsl.CommonExtension +import com.android.build.api.variant.AndroidComponentsExtension +import com.android.build.gradle.api.AndroidBasePlugin +import com.android.testutils.MockitoKt.argumentCaptor +import com.android.testutils.MockitoKt.capture +import com.android.testutils.MockitoKt.eq +import com.google.common.truth.Truth.assertThat +import com.google.firebase.testlab.gradle.TestLabGradlePluginExtension +import org.gradle.api.Action +import org.gradle.api.Project +import org.junit.Assert.assertThrows +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.mockito.Answers +import org.mockito.Mock +import org.mockito.Mockito.atLeastOnce +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` +import org.mockito.junit.MockitoJUnit +import org.mockito.junit.MockitoRule + +/** + * Unit tests for [TestLabGradlePlugin] + */ +class TestLabGradlePluginTest { + + @get:Rule + val mockitoJUnitRule: MockitoRule = MockitoJUnit.rule() + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + lateinit var mockProject: Project + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + lateinit var mockAndroidPlugin: AndroidComponentsExtension<*, *, *> + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + lateinit var mockCommonExtension: CommonExtension<*, *, *, *, *> + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + lateinit var mockTestLabExtension: TestLabGradlePluginExtension + + @Before + fun setupMocks() { + `when`(mockProject.extensions.getByType(eq(AndroidComponentsExtension::class.java))).thenReturn(mockAndroidPlugin) + `when`(mockProject.extensions.getByType(eq(CommonExtension::class.java))).thenReturn(mockCommonExtension) + `when`(mockProject.extensions.getByType(eq(TestLabGradlePluginExtension::class.java))).thenReturn(mockTestLabExtension) + } + + private fun applyFtlPlugin( + agpVersion: AndroidPluginVersion = AndroidPluginVersion(8, 1)) { + `when`(mockAndroidPlugin.pluginVersion).thenReturn(agpVersion) + + val plugin = TestLabGradlePlugin() + plugin.apply(mockProject) + + val captor = argumentCaptor<Action<AndroidBasePlugin>>() + verify(mockProject.plugins, atLeastOnce()) + .withType(eq(AndroidBasePlugin::class.java), capture(captor)) + + captor.value.execute(AndroidBasePlugin()) + } + + @Test + fun agpVersionCheck() { + val unsupportedVersionsTooOld = listOf( + AndroidPluginVersion(8, 1, 0).alpha(8), + ) + val supportedVersions = listOf( + AndroidPluginVersion(8, 1, 0).alpha(9), + AndroidPluginVersion(8, 1), + AndroidPluginVersion(8, 2), + AndroidPluginVersion(8, 3, 0).dev(), + ) + val unsupportedVersionsTooRecent = listOf( + AndroidPluginVersion(8, 3, 0).alpha(1), + AndroidPluginVersion(8, 3, 0), + ) + + unsupportedVersionsTooOld.forEach { + val e = assertThrows(IllegalStateException::class.java) { + applyFtlPlugin(it) + } + assertThat(e).hasMessageThat() + .contains("Android Gradle plugin version 8.1.0-alpha09 or higher is required.") + } + + supportedVersions.forEach { + applyFtlPlugin(it) + } + + unsupportedVersionsTooRecent.forEach { + val e = assertThrows(IllegalStateException::class.java) { + applyFtlPlugin(it) + } + assertThat(e).hasMessageThat().contains("It requires Android Gradle plugin version 8.2.0.") + } + } +} diff --git a/firebase/testlab/testlab-gradle-plugin/src/test/java/com/android/tools/firebase/testlab/gradle/services/TestLabBuildServiceTest.kt b/firebase/testlab/testlab-gradle-plugin/src/test/java/com/android/tools/firebase/testlab/gradle/services/TestLabBuildServiceTest.kt index 13d3ce3d5a..5916988a48 100644 --- a/firebase/testlab/testlab-gradle-plugin/src/test/java/com/android/tools/firebase/testlab/gradle/services/TestLabBuildServiceTest.kt +++ b/firebase/testlab/testlab-gradle-plugin/src/test/java/com/android/tools/firebase/testlab/gradle/services/TestLabBuildServiceTest.kt @@ -19,14 +19,18 @@ package com.android.tools.firebase.testlab.gradle.services import com.android.testutils.MockitoKt.any import com.android.testutils.MockitoKt.eq import com.android.testutils.MockitoKt.mock +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential +import com.google.api.client.http.HttpTransport +import com.google.api.client.testing.http.MockHttpTransport +import com.google.api.client.testing.http.MockLowLevelHttpResponse +import com.google.common.truth.Truth.assertThat import com.google.firebase.testlab.gradle.TestLabGradlePluginExtension -import java.io.File import org.gradle.api.Action +import org.gradle.api.Project import org.gradle.api.Transformer import org.gradle.api.file.RegularFile import org.gradle.api.provider.Provider import org.gradle.api.provider.ProviderFactory -import org.gradle.api.services.BuildServiceRegistry import org.gradle.api.services.BuildServiceSpec import org.junit.Rule import org.junit.Test @@ -40,6 +44,9 @@ import org.mockito.Mockito.`when` import org.mockito.Mockito.withSettings import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoRule +import java.io.File +import java.util.logging.Level +import java.util.logging.Logger /** * Unit tests for [TestLabBuildService]. @@ -52,12 +59,9 @@ class TestLabBuildServiceTest { @get:Rule val temporaryFolderRule = TemporaryFolder() - @Mock + @Mock(answer = Answers.RETURNS_DEEP_STUBS) lateinit var mockExtension: TestLabGradlePluginExtension - @Mock(answer = Answers.RETURNS_MOCKS) - lateinit var mockBuildServiceRegistry: BuildServiceRegistry - @Mock lateinit var mockProviderFactory: ProviderFactory @@ -81,11 +85,13 @@ class TestLabBuildServiceTest { val credentialFileRegularFile = mock<RegularFile>() `when`(credentialFileRegularFile.asFile).thenReturn(credentialFile) + val mockProject = mock<Project>(withSettings().defaultAnswer(Answers.RETURNS_DEEP_STUBS)) + `when`(mockProject.path).thenReturn("mockProjectPath") TestLabBuildService.RegistrationAction(mockExtension, mockProviderFactory) - .registerIfAbsent(mockBuildServiceRegistry) + .registerIfAbsent(mockProject) lateinit var configAction: Action<in BuildServiceSpec<TestLabBuildService.Parameters>> - verify(mockBuildServiceRegistry).registerIfAbsent( + verify(mockProject.gradle.sharedServices).registerIfAbsent( startsWith("com.android.tools.firebase.testlab.gradle.services.TestLabBuildService_"), eq(TestLabBuildService::class.java), argThat { @@ -113,4 +119,48 @@ class TestLabBuildServiceTest { it.get() == "test_quota_project_id" }) } + + @Test + fun logLevelShouldBeWarning() { + val credentialFile = temporaryFolderRule.newFile("testCredentialFile") + object: TestLabBuildService() { + override fun getParameters(): Parameters { + val params = mock<Parameters>( + withSettings().defaultAnswer(Answers.RETURNS_DEEP_STUBS)) + `when`(params.credentialFile.get().asFile).thenReturn(credentialFile) + return params + } + } + assertThat(Logger.getLogger("com.google.api.client").level).isEqualTo(Level.WARNING) + } + + @Test + fun catalog() { + val service = object: TestLabBuildService() { + override val credential: GoogleCredential + get() = mock() + override val httpTransport: HttpTransport + get() = MockHttpTransport.Builder().apply { + setLowLevelHttpResponse(MockLowLevelHttpResponse().apply { + setContent(""" + { + "androidDeviceCatalog": { + "models": [ + { + "id": "test_device_id" + } + ] + } + } + """.trimIndent()) + }) + }.build() + override fun getParameters() = mock<Parameters>( + withSettings().defaultAnswer(Answers.RETURNS_DEEP_STUBS)) + } + + val catalog = service.catalog() + assertThat(catalog.models).hasSize(1) + assertThat(catalog.models[0].id).isEqualTo("test_device_id") + } } diff --git a/gmaven/src/test/java/com/android/tools/test/GmavenZipTest.java b/gmaven/src/test/java/com/android/tools/test/GmavenZipTest.java index 73b2ba89ae..663a3ec85a 100644 --- a/gmaven/src/test/java/com/android/tools/test/GmavenZipTest.java +++ b/gmaven/src/test/java/com/android/tools/test/GmavenZipTest.java @@ -123,6 +123,9 @@ public class GmavenZipTest { "com/android/zipflinger", "com/android/zipflinger:sources"); + private static final Set<String> APPARENTLY_FLAKY = + ImmutableSet.of("com/android/tools/build/gradle:sources"); + private static class PomInfo implements Comparable<PomInfo> { private static final DocumentBuilder documentBuilder; @@ -463,7 +466,7 @@ public class GmavenZipTest { + repo + ".\n" + "Remove it from MISSING_LICENSE"); - } else if (!found && !knownMissing) { + } else if (!found && !knownMissing && !APPARENTLY_FLAKY.contains(key)) { expect.fail("No license file in " + jarPath + " with key " + key); } } diff --git a/gmaven/src/test/resources/com/android/tools/test/gmaven-jars.txt b/gmaven/src/test/resources/com/android/tools/test/gmaven-jars.txt index ceaab1963a..9003b0102b 100644 --- a/gmaven/src/test/resources/com/android/tools/test/gmaven-jars.txt +++ b/gmaven/src/test/resources/com/android/tools/test/gmaven-jars.txt @@ -704,6 +704,7 @@ com/android/tools/dvlib com/android/dvlib/devices-4.xsd com/android/dvlib/devices-5.xsd com/android/dvlib/devices-6.xsd + com/android/dvlib/devices-7.xsd com/android/tools/emulator/proto META-INF/ @@ -2817,6 +2818,14 @@ com/android/tools/sdk-common versions-offline/androidx/asynclayoutinflater/group-index.xml versions-offline/androidx/autofill/ versions-offline/androidx/autofill/group-index.xml + versions-offline/androidx/baselineprofile/ + versions-offline/androidx/baselineprofile/apptarget/ + versions-offline/androidx/baselineprofile/apptarget/group-index.xml + versions-offline/androidx/baselineprofile/consumer/ + versions-offline/androidx/baselineprofile/consumer/group-index.xml + versions-offline/androidx/baselineprofile/group-index.xml + versions-offline/androidx/baselineprofile/producer/ + versions-offline/androidx/baselineprofile/producer/group-index.xml versions-offline/androidx/benchmark/ versions-offline/androidx/benchmark/group-index.xml versions-offline/androidx/biometric/ @@ -2859,6 +2868,10 @@ com/android/tools/sdk-common versions-offline/androidx/coordinatorlayout/group-index.xml versions-offline/androidx/core/ versions-offline/androidx/core/group-index.xml + versions-offline/androidx/core/uwb/ + versions-offline/androidx/core/uwb/group-index.xml + versions-offline/androidx/credentials/ + versions-offline/androidx/credentials/group-index.xml versions-offline/androidx/cursoradapter/ versions-offline/androidx/cursoradapter/group-index.xml versions-offline/androidx/customview/ @@ -2891,16 +2904,24 @@ com/android/tools/sdk-common versions-offline/androidx/gaming/group-index.xml versions-offline/androidx/glance/ versions-offline/androidx/glance/group-index.xml + versions-offline/androidx/graphics/ + versions-offline/androidx/graphics/group-index.xml versions-offline/androidx/gridlayout/ versions-offline/androidx/gridlayout/group-index.xml versions-offline/androidx/health/ + versions-offline/androidx/health/connect/ + versions-offline/androidx/health/connect/group-index.xml versions-offline/androidx/health/group-index.xml versions-offline/androidx/heifwriter/ versions-offline/androidx/heifwriter/group-index.xml versions-offline/androidx/hilt/ versions-offline/androidx/hilt/group-index.xml + versions-offline/androidx/input/ + versions-offline/androidx/input/group-index.xml versions-offline/androidx/interpolator/ versions-offline/androidx/interpolator/group-index.xml + versions-offline/androidx/javascriptengine/ + versions-offline/androidx/javascriptengine/group-index.xml versions-offline/androidx/leanback/ versions-offline/androidx/leanback/group-index.xml versions-offline/androidx/legacy/ @@ -2939,6 +2960,15 @@ com/android/tools/sdk-common versions-offline/androidx/preference/group-index.xml versions-offline/androidx/print/ versions-offline/androidx/print/group-index.xml + versions-offline/androidx/privacysandbox/ + versions-offline/androidx/privacysandbox/ads/ + versions-offline/androidx/privacysandbox/ads/group-index.xml + versions-offline/androidx/privacysandbox/sdkruntime/ + versions-offline/androidx/privacysandbox/sdkruntime/group-index.xml + versions-offline/androidx/privacysandbox/tools/ + versions-offline/androidx/privacysandbox/tools/group-index.xml + versions-offline/androidx/privacysandbox/ui/ + versions-offline/androidx/privacysandbox/ui/group-index.xml versions-offline/androidx/profileinstaller/ versions-offline/androidx/profileinstaller/group-index.xml versions-offline/androidx/recommendation/ @@ -2987,6 +3017,8 @@ com/android/tools/sdk-common versions-offline/androidx/tracing/group-index.xml versions-offline/androidx/transition/ versions-offline/androidx/transition/group-index.xml + versions-offline/androidx/tv/ + versions-offline/androidx/tv/group-index.xml versions-offline/androidx/tvprovider/ versions-offline/androidx/tvprovider/group-index.xml versions-offline/androidx/ui/ @@ -3003,6 +3035,8 @@ com/android/tools/sdk-common versions-offline/androidx/wear/compose/ versions-offline/androidx/wear/compose/group-index.xml versions-offline/androidx/wear/group-index.xml + versions-offline/androidx/wear/protolayout/ + versions-offline/androidx/wear/protolayout/group-index.xml versions-offline/androidx/wear/tiles/ versions-offline/androidx/wear/tiles/group-index.xml versions-offline/androidx/wear/watchface/ @@ -3010,6 +3044,9 @@ com/android/tools/sdk-common versions-offline/androidx/webkit/ versions-offline/androidx/webkit/group-index.xml versions-offline/androidx/window/ + versions-offline/androidx/window/extensions/ + versions-offline/androidx/window/extensions/core/ + versions-offline/androidx/window/extensions/core/group-index.xml versions-offline/androidx/window/group-index.xml versions-offline/androidx/work/ versions-offline/androidx/work/group-index.xml @@ -3032,9 +3069,14 @@ com/android/tools/sdk-common versions-offline/com/android/databinding/group-index.xml versions-offline/com/android/dynamic-feature/ versions-offline/com/android/dynamic-feature/group-index.xml + versions-offline/com/android/fused-library/ + versions-offline/com/android/fused-library/group-index.xml versions-offline/com/android/group-index.xml versions-offline/com/android/installreferrer/ versions-offline/com/android/installreferrer/group-index.xml + versions-offline/com/android/internal/ + versions-offline/com/android/internal/settings/ + versions-offline/com/android/internal/settings/group-index.xml versions-offline/com/android/java/ versions-offline/com/android/java/tools/ versions-offline/com/android/java/tools/build/ @@ -3046,8 +3088,12 @@ com/android/tools/sdk-common versions-offline/com/android/ndk/ versions-offline/com/android/ndk/thirdparty/ versions-offline/com/android/ndk/thirdparty/group-index.xml + versions-offline/com/android/privacy-sandbox-sdk/ + versions-offline/com/android/privacy-sandbox-sdk/group-index.xml versions-offline/com/android/reporting/ versions-offline/com/android/reporting/group-index.xml + versions-offline/com/android/settings/ + versions-offline/com/android/settings/group-index.xml versions-offline/com/android/support/ versions-offline/com/android/support/constraint/ versions-offline/com/android/support/constraint/group-index.xml @@ -3101,6 +3147,8 @@ com/android/tools/sdk-common versions-offline/com/android/tools/metalava/group-index.xml versions-offline/com/android/tools/pixelprobe/ versions-offline/com/android/tools/pixelprobe/group-index.xml + versions-offline/com/android/tools/smali/ + versions-offline/com/android/tools/smali/group-index.xml versions-offline/com/android/tools/utp/ versions-offline/com/android/tools/utp/group-index.xml versions-offline/com/android/volley/ @@ -3118,6 +3166,9 @@ com/android/tools/sdk-common versions-offline/com/google/ads/interactivemedia/v3/group-index.xml versions-offline/com/google/ads/mediation/ versions-offline/com/google/ads/mediation/group-index.xml + versions-offline/com/google/ambient/ + versions-offline/com/google/ambient/crossdevice/ + versions-offline/com/google/ambient/crossdevice/group-index.xml versions-offline/com/google/android/ versions-offline/com/google/android/ads/ versions-offline/com/google/android/ads/consent/ @@ -3129,6 +3180,9 @@ com/android/tools/sdk-common versions-offline/com/google/android/apps/common/testing/accessibility/ versions-offline/com/google/android/apps/common/testing/accessibility/framework/ versions-offline/com/google/android/apps/common/testing/accessibility/framework/group-index.xml + versions-offline/com/google/android/car/ + versions-offline/com/google/android/car/connectionservice/ + versions-offline/com/google/android/car/connectionservice/group-index.xml versions-offline/com/google/android/datatransport/ versions-offline/com/google/android/datatransport/group-index.xml versions-offline/com/google/android/enterprise/ @@ -3153,11 +3207,18 @@ com/android/tools/sdk-common versions-offline/com/google/android/libraries/ versions-offline/com/google/android/libraries/car/ versions-offline/com/google/android/libraries/car/group-index.xml + versions-offline/com/google/android/libraries/cloud/ + versions-offline/com/google/android/libraries/cloud/telco/ + versions-offline/com/google/android/libraries/cloud/telco/subgraph/ + versions-offline/com/google/android/libraries/cloud/telco/subgraph/group-index.xml versions-offline/com/google/android/libraries/enterprise/ versions-offline/com/google/android/libraries/enterprise/amapi/ versions-offline/com/google/android/libraries/enterprise/amapi/group-index.xml versions-offline/com/google/android/libraries/healthdata/ versions-offline/com/google/android/libraries/healthdata/group-index.xml + versions-offline/com/google/android/libraries/identity/ + versions-offline/com/google/android/libraries/identity/googleid/ + versions-offline/com/google/android/libraries/identity/googleid/group-index.xml versions-offline/com/google/android/libraries/maps/ versions-offline/com/google/android/libraries/maps/group-index.xml versions-offline/com/google/android/libraries/mapsplatform/ @@ -3165,6 +3226,11 @@ com/android/tools/sdk-common versions-offline/com/google/android/libraries/mapsplatform/secrets-gradle-plugin/group-index.xml versions-offline/com/google/android/libraries/places/ versions-offline/com/google/android/libraries/places/group-index.xml + versions-offline/com/google/android/libraries/play/ + versions-offline/com/google/android/libraries/play/games/ + versions-offline/com/google/android/libraries/play/games/group-index.xml + versions-offline/com/google/android/livesharing/ + versions-offline/com/google/android/livesharing/group-index.xml versions-offline/com/google/android/material/ versions-offline/com/google/android/material/group-index.xml versions-offline/com/google/android/mediahome/ @@ -3173,10 +3239,14 @@ com/android/tools/sdk-common versions-offline/com/google/android/odml/group-index.xml versions-offline/com/google/android/play/ versions-offline/com/google/android/play/group-index.xml + versions-offline/com/google/android/recaptcha/ + versions-offline/com/google/android/recaptcha/group-index.xml versions-offline/com/google/android/support/ versions-offline/com/google/android/support/group-index.xml versions-offline/com/google/android/things/ versions-offline/com/google/android/things/group-index.xml + versions-offline/com/google/android/tv/ + versions-offline/com/google/android/tv/group-index.xml versions-offline/com/google/android/ump/ versions-offline/com/google/android/ump/group-index.xml versions-offline/com/google/android/wearable/ @@ -3194,8 +3264,13 @@ com/android/tools/sdk-common versions-offline/com/google/assistant/appactions/group-index.xml versions-offline/com/google/assistant/suggestion/ versions-offline/com/google/assistant/suggestion/group-index.xml + versions-offline/com/google/camerax/ + versions-offline/com/google/camerax/effects/ + versions-offline/com/google/camerax/effects/group-index.xml versions-offline/com/google/chromeos/ versions-offline/com/google/chromeos/group-index.xml + versions-offline/com/google/d2c/ + versions-offline/com/google/d2c/group-index.xml versions-offline/com/google/devtools/ versions-offline/com/google/devtools/ksp/ versions-offline/com/google/devtools/ksp/group-index.xml @@ -3209,6 +3284,8 @@ com/android/tools/sdk-common versions-offline/com/google/firebase/firebase-perf/ versions-offline/com/google/firebase/firebase-perf/group-index.xml versions-offline/com/google/firebase/group-index.xml + versions-offline/com/google/firebase/testlab/ + versions-offline/com/google/firebase/testlab/group-index.xml versions-offline/com/google/gms/ versions-offline/com/google/gms/google-services/ versions-offline/com/google/gms/google-services/group-index.xml @@ -3219,10 +3296,15 @@ com/android/tools/sdk-common versions-offline/com/google/mediapipe/group-index.xml versions-offline/com/google/mlkit/ versions-offline/com/google/mlkit/group-index.xml + versions-offline/com/google/net/ + versions-offline/com/google/net/cronet/ + versions-offline/com/google/net/cronet/group-index.xml versions-offline/com/google/oboe/ versions-offline/com/google/oboe/group-index.xml versions-offline/com/google/prefab/ versions-offline/com/google/prefab/group-index.xml + versions-offline/com/google/relay/ + versions-offline/com/google/relay/group-index.xml versions-offline/com/google/test/ versions-offline/com/google/test/platform/ versions-offline/com/google/test/platform/group-index.xml diff --git a/gmaven/src/test/resources/com/android/tools/test/gmaven-poms.txt b/gmaven/src/test/resources/com/android/tools/test/gmaven-poms.txt index 2db00792a4..2d129941de 100644 --- a/gmaven/src/test/resources/com/android/tools/test/gmaven-poms.txt +++ b/gmaven/src/test/resources/com/android/tools/test/gmaven-poms.txt @@ -365,8 +365,6 @@ com.android.tools.apkparser:apkanalyzer com.android.tools.smali:smali-baksmali (runtime) com.android.tools.smali:smali-dexlib2 (runtime) com.google.guava:guava (runtime) - org.smali:baksmali (runtime) - org.smali:dexlib2 (runtime) com.android.tools.apkparser:binary-resources pomName=Binary Resources parser diff --git a/layoutlib-api/src/main/java/com/android/ide/common/rendering/api/RenderResources.java b/layoutlib-api/src/main/java/com/android/ide/common/rendering/api/RenderResources.java index 017b8ff749..dc31f18e1b 100644 --- a/layoutlib-api/src/main/java/com/android/ide/common/rendering/api/RenderResources.java +++ b/layoutlib-api/src/main/java/com/android/ide/common/rendering/api/RenderResources.java @@ -60,10 +60,13 @@ public class RenderResources { public void clearStyles() { } + /** Clears all themes, from the resolution list, including the default theme. */ + public void clearAllThemes() {} + /** - * Returns a list of {@link StyleResourceValue} containing a list of themes to be used for - * resolving resources. The order of the themes in the list specifies the order in which they - * should be used to resolve resources. + * Returns an immutable list of {@link StyleResourceValue} containing a list of themes to be + * used for resolving resources. The order of the themes in the list specifies the order in + * which they should be used to resolve resources. */ @NonNull public List<StyleResourceValue> getAllThemes() { diff --git a/lint/cli/src/main/java/com/android/tools/lint/LintCliClient.kt b/lint/cli/src/main/java/com/android/tools/lint/LintCliClient.kt index dc402341cc..c90de310da 100644 --- a/lint/cli/src/main/java/com/android/tools/lint/LintCliClient.kt +++ b/lint/cli/src/main/java/com/android/tools/lint/LintCliClient.kt @@ -1488,7 +1488,8 @@ open class LintCliClient : LintClient { val config = UastEnvironment.Configuration.create( - enableKotlinScripting = mayNeedKotlinScripting(allProjects) + enableKotlinScripting = mayNeedKotlinScripting(allProjects), + useFirUast = flags.useK2Uast() || useFirUast() ) config.javaLanguageLevel = maxLevel config.addSourceRoots(sourceRoots.toList()) diff --git a/lint/cli/src/main/java/com/android/tools/lint/LintCliFlags.java b/lint/cli/src/main/java/com/android/tools/lint/LintCliFlags.java index 7c37ba824d..c13085940f 100644 --- a/lint/cli/src/main/java/com/android/tools/lint/LintCliFlags.java +++ b/lint/cli/src/main/java/com/android/tools/lint/LintCliFlags.java @@ -82,6 +82,7 @@ public class LintCliFlags { private boolean printInternalErrorStackTrace; private boolean allowBaselineSuppress; private boolean offline; + private boolean useK2Uast; private File cacheDir; public static final int ERRNO_SUCCESS = 0; @@ -846,4 +847,23 @@ public class LintCliFlags { public void setOffline(boolean offline) { this.offline = offline; } + + /** + * Returns true if lint is using K2 UAST, formerly known as FIR UAST. K1 UAST, retroactively + * named as FE1.0 UAST, by default. + * + * @return whether to use K2 UAST + */ + public boolean useK2Uast() { + return useK2Uast; + } + + /** + * Sets whether lint needs to use K2 UAST. + * + * @param useK2Uast whether to use K2 UAST + */ + public void setUseK2Uast(boolean useK2Uast) { + this.useK2Uast = useK2Uast; + } } diff --git a/lint/cli/src/main/java/com/android/tools/lint/Main.java b/lint/cli/src/main/java/com/android/tools/lint/Main.java index 22c884ba86..d9fae0b1e6 100644 --- a/lint/cli/src/main/java/com/android/tools/lint/Main.java +++ b/lint/cli/src/main/java/com/android/tools/lint/Main.java @@ -1480,6 +1480,8 @@ public class Main { } else { return ERRNO_ERRORS; } + } else if (arg.equals("--XuseK2Uast")) { + flags.setUseK2Uast(true); } else if (arg.equals(ARG_PRINT_INTERNAL_ERROR_STACKTRACE)) { flags.setPrintInternalErrorStackTrace(true); } else if (arg.equals(ARG_ANALYZE_ONLY)) { diff --git a/lint/cli/src/main/java/com/android/tools/lint/UastEnvironment.kt b/lint/cli/src/main/java/com/android/tools/lint/UastEnvironment.kt index ead4e92e63..37f44f7b48 100644 --- a/lint/cli/src/main/java/com/android/tools/lint/UastEnvironment.kt +++ b/lint/cli/src/main/java/com/android/tools/lint/UastEnvironment.kt @@ -34,7 +34,7 @@ import org.jetbrains.kotlin.config.languageVersionSettings /** JVM system property to enable FIR UAST or K2 UAST, as per the new compiler name */ const val FIR_UAST_KEY = "lint.use.fir.uast" -private fun useFirUast(): Boolean = System.getProperty(FIR_UAST_KEY, "false").toBoolean() +internal fun useFirUast(): Boolean = System.getProperty(FIR_UAST_KEY, "false").toBoolean() /** * This interface provides the setup and configuration needed to use VFS/PSI/UAST on the command diff --git a/lint/docs/usage/changes.md.html b/lint/docs/usage/changes.md.html index 71db1b81d8..4f005799b4 100644 --- a/lint/docs/usage/changes.md.html +++ b/lint/docs/usage/changes.md.html @@ -19,6 +19,9 @@ lint check authors, see the API Guide. `UnsafeImplicitIntentLaunch` | Implicit intent matches an internal non-exported component `ShortcutUsageDetector` | Shortcut usage should be reported `UseTomlInstead` | Mixing and matching Gradle build file and TOML dependencies + `KaptUsageInsteadOfKsp` | Using kapt where KSP would also be available + `BomWithoutPlatform` | BOM artifact added as a dependency instead of as a platform + `ProviderReadPermissionOnly` | Provider with readPermission only and implemented write APIs (The `NoOp` and `UnsafeImplicitIntentLaunch` lint checks are currently disabled by default.) diff --git a/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/LintUtils.kt b/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/LintUtils.kt index 12a8573323..bb4f006005 100644 --- a/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/LintUtils.kt +++ b/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/LintUtils.kt @@ -593,21 +593,6 @@ fun UArrayAccessExpression.resolveOperator(skipOverloadedSetter: Boolean = true) } /** - * Returns the layout resource name for the given layout file - * - * @param layoutFile the file pointing to the layout - * @return the layout resource name, not including the `@layout` prefix - */ -fun getLayoutName(layoutFile: File): String { - var name = layoutFile.name - val dotIndex = name.indexOf('.') - if (dotIndex != -1) { - name = name.substring(0, dotIndex) - } - return name -} - -/** * Splits the given path into its individual parts, attempting to be tolerant about path separators * (: or ;). It can handle possibly ambiguous paths, such as `c:\foo\bar:\other`, though of course * these are to be avoided if possible. @@ -2430,7 +2415,7 @@ object LintUtils { replaceWith = ReplaceWith("com.android.tools.lint.detector.api.getLayoutName(layoutFile)") ) fun getLayoutName(layoutFile: File): String { - return com.android.tools.lint.detector.api.getLayoutName(layoutFile) + return SdkUtils.getLayoutName(layoutFile) } @JvmStatic diff --git a/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Location.kt b/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Location.kt index fd6cc265f4..66741c1471 100644 --- a/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Location.kt +++ b/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Location.kt @@ -240,6 +240,15 @@ protected constructor( return start == null || end == null || start.sameLine(end) } + /** Returns true if the other location is within the range of this location. */ + operator fun contains(other: Location): Boolean { + val thisStart = this.start ?: DefaultPosition(0, 0, 0) + val otherStart = other.start ?: DefaultPosition(0, 0, 0) + val thisEnd = this.end ?: DefaultPosition(Int.MAX_VALUE, 0, Int.MAX_VALUE) + val otherEnd = other.end ?: DefaultPosition(Int.MAX_VALUE, 0, Int.MAX_VALUE) + return thisStart <= otherStart && thisEnd >= otherEnd + } + override fun toString(): String = "Location [file=${file.name}, start=$start, end=$end, message=$message]" diff --git a/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Position.kt b/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Position.kt index 4b0db10e11..c52e4eeee2 100644 --- a/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Position.kt +++ b/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Position.kt @@ -17,7 +17,7 @@ package com.android.tools.lint.detector.api /** Information about a position in a file/document. */ -abstract class Position { +abstract class Position : Comparable<Position> { /** * Returns the line number (0-based where the first line is line 0) * @@ -43,4 +43,10 @@ abstract class Position { open fun sameLine(end: Position): Boolean { return line == end.line } + + override operator fun compareTo(other: Position): Int { + return if (this.line == other.line && this.offset == other.offset) 0 + else if (this.line < other.line || this.line == other.line && this.offset < other.offset) -1 + else 1 + } } diff --git a/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Project.java b/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Project.java index 1f6bf7c934..9349094bcd 100644 --- a/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Project.java +++ b/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Project.java @@ -76,6 +76,7 @@ import com.google.common.base.Splitter; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.common.io.Closeables; +import com.intellij.core.CoreApplicationEnvironment; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.PsiClass; import java.io.BufferedInputStream; @@ -162,6 +163,8 @@ public class Project { private com.intellij.openapi.project.Project ideaProject; private Map<Object, Object> clientProperties; + private CoreApplicationEnvironment env; + /** * Creates a new {@link Project} for the given directory. * @@ -1571,4 +1574,12 @@ public class Project { public LintClient getClient() { return client; } + + public void setEnv(CoreApplicationEnvironment env) { + this.env = env; + } + + public CoreApplicationEnvironment getEnv() { + return env; + } } diff --git a/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/UastLintUtils.kt b/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/UastLintUtils.kt index 9d825d15bf..725a60730c 100644 --- a/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/UastLintUtils.kt +++ b/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/UastLintUtils.kt @@ -34,6 +34,7 @@ import com.intellij.psi.PsiModifier import com.intellij.psi.PsiModifierListOwner import com.intellij.psi.PsiParameter import com.intellij.psi.PsiVariable +import com.intellij.psi.util.InheritanceUtil import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil.getNonStrictParentOfType import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass @@ -78,12 +79,15 @@ import org.jetbrains.uast.UastFacade import org.jetbrains.uast.UastPrefixOperator import org.jetbrains.uast.getContainingUMethod import org.jetbrains.uast.getParentOfType +import org.jetbrains.uast.getQualifiedName +import org.jetbrains.uast.getUCallExpression import org.jetbrains.uast.internal.acceptList import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds import org.jetbrains.uast.skipParenthesizedExprDown import org.jetbrains.uast.skipParenthesizedExprUp import org.jetbrains.uast.toUElement import org.jetbrains.uast.toUElementOfType +import org.jetbrains.uast.tryResolve import org.jetbrains.uast.visitor.UastVisitor class UastLintUtils { @@ -160,7 +164,7 @@ class UastLintUtils { } @JvmStatic - fun findLastAssignment(variable: PsiVariable, call: UElement): UExpression? { + fun findLastAssignment(variable: PsiVariable, endAt: UElement): UExpression? { var currVariable = variable var lastAssignment: UElement? = null @@ -172,9 +176,9 @@ class UastLintUtils { !currVariable.hasModifierProperty(PsiModifier.FINAL) && (currVariable is PsiLocalVariable || currVariable is PsiParameter) ) { - val containingFunction = call.getContainingUMethod() + val containingFunction = endAt.getContainingUMethod() if (containingFunction != null) { - val finder = ConstantEvaluatorImpl.LastAssignmentFinder(currVariable, call, null, -1) + val finder = ConstantEvaluatorImpl.LastAssignmentFinder(currVariable, endAt, null, -1) containingFunction.accept(finder) lastAssignment = finder.lastAssignment } @@ -212,6 +216,93 @@ class UastLintUtils { return findArgument(node, node.resolve() ?: return null, type) } + /** + * Finds the initialization method (factory method or constructor) of a variable whose type is a + * specific class. + * + * @param fullQualifiedClassName fully qualified class name to be searched for. + * @param origExpression the variable or the initialization method itself. + * @param endAt where the search ends + * @param includeSubClass if true, include constructor of a subclass of the specified class. + */ + fun findConstruction( + fullQualifiedClassName: String, + origExpression: UExpression, + endAt: UElement, + includeSubClass: Boolean = false + ): UCallExpression? { + val expression = origExpression.skipParenthesizedExprDown() + + val call = expression.getUCallExpression(1) + if (call != null) { + // handle the case of a default constructor, in which case the call cannot be resolved if + // not defined. + val classRef = call.classReference + if ( + classRef != null && + (call.classReference?.getQualifiedName() == fullQualifiedClassName || + includeSubClass && + InheritanceUtil.isInheritor( + classRef.resolve() as? PsiClass, + true, + fullQualifiedClassName + )) + ) { + return call + } else if (expression is UQualifiedReferenceExpression) { + return if (isReturningContext(call)) { + // eg. filter.apply { addAction("abc") } --> use filter variable. + findConstruction(fullQualifiedClassName, expression.receiver, endAt, includeSubClass) + } else { // eg. IntentFilter.create("abc") --> use create("abc") UCallExpression. + findConstruction(fullQualifiedClassName, call, endAt, includeSubClass) + } + } + } + + return when (val resolved = expression.tryResolve()) { + is PsiVariable -> { + val assignment = findLastAssignment(resolved, endAt) ?: return null + findConstruction(fullQualifiedClassName, assignment, endAt, includeSubClass) + } + is PsiMethod -> { + if (isFactoryMethodForClass(fullQualifiedClassName, resolved, includeSubClass)) { + expression as? UCallExpression + } else { + null + } + } + else -> null + } + } + + private fun isFactoryMethodForClass( + fullQualifiedClassName: String, + method: PsiMethod, + includeSubClass: Boolean = false + ): Boolean { + return (method.returnType?.canonicalText == fullQualifiedClassName || method.isConstructor) && + (isMemberInClass(method, fullQualifiedClassName) || + includeSubClass && isMemberInSubClassOf(method, fullQualifiedClassName)) + } + + fun isMemberInSubClassOf( + member: PsiMember, + className: String, + strict: Boolean = false + ): Boolean { + val containingClass = member.containingClass + return containingClass != null && + InheritanceUtil.isInheritor(containingClass, strict, className) + } + + fun isMemberInClass(member: PsiMember?, className: String): Boolean { + if (member == null) { + return false + } + val containingClass = member.containingClass?.qualifiedName + return className == containingClass + } + @JvmStatic fun getReferenceName(expression: UReferenceExpression): String? { if (expression is USimpleNameReferenceExpression) { diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/BroadcastReceiverUtils.kt b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/BroadcastReceiverUtils.kt index 55ccea41fb..816bac6591 100644 --- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/BroadcastReceiverUtils.kt +++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/BroadcastReceiverUtils.kt @@ -15,18 +15,24 @@ */ package com.android.tools.lint.checks +import com.android.tools.lint.client.api.JavaEvaluator import com.android.tools.lint.detector.api.ConstantEvaluator -import com.android.tools.lint.detector.api.UastLintUtils.Companion.findLastAssignment +import com.android.tools.lint.detector.api.UastLintUtils.Companion.findConstruction import com.android.tools.lint.detector.api.getMethodName -import com.android.tools.lint.detector.api.isReturningContext +import com.intellij.psi.PsiField import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiVariable +import com.intellij.psi.PsiParameter +import org.jetbrains.uast.UBinaryExpression import org.jetbrains.uast.UCallExpression import org.jetbrains.uast.UElement import org.jetbrains.uast.UExpression import org.jetbrains.uast.UParenthesizedExpression -import org.jetbrains.uast.UQualifiedReferenceExpression +import org.jetbrains.uast.UReturnExpression +import org.jetbrains.uast.UastBinaryOperator +import org.jetbrains.uast.getContainingUClass import org.jetbrains.uast.getContainingUMethod +import org.jetbrains.uast.skipParenthesizedExprUp +import org.jetbrains.uast.toUElement import org.jetbrains.uast.tryResolve @SuppressWarnings("WrongTerminology") @@ -35,75 +41,78 @@ object BroadcastReceiverUtils { fun checkIsProtectedReceiverAndReturnUnprotectedActions( filterArg: UExpression, node: UCallExpression, - evaluator: ConstantEvaluator + javaEvaluator: JavaEvaluator, ): Pair<Boolean, List<String>> { // isProtected, unprotectedActions + val constantEvaluator = ConstantEvaluator().allowFieldInitializers() val actions = mutableSetOf<String>() + + val filterField = filterArg.tryResolve() as? PsiField + if (filterField != null && javaEvaluator.isPrivate(filterField)) { + // Special case for class fields. + // If a private class field is used for the intent filter, try to evaluate + // all the calls in the class, gathering the intent filter's actions but exiting + // if the field escapes the class's scope. + val clazz = node.getContainingUClass() ?: return Pair(false, listOf()) + val dfa = IntentFilterFieldDataFlowAnalyzer(filterField, javaEvaluator, constantEvaluator) + clazz.accept(dfa) + actions.addAll(dfa.actions) + val isProtected = actions.all(::isProtectedBroadcast) && !dfa.escaped + val unprotected = actions.filterNot(::isProtectedBroadcast) + return Pair(isProtected, unprotected) + } + val construction = findIntentFilterConstruction(filterArg, node) ?: return Pair(false, listOf()) val constructorActionArg = construction.getArgumentForParameter(0) - (constructorActionArg?.let(evaluator::evaluate) as? String)?.let(actions::add) + (constructorActionArg?.let(constantEvaluator::evaluate) as? String)?.let(actions::add) - val actionCollectorVisitor = ActionCollectorVisitor(setOf(construction), node, evaluator) + val actionCollectorVisitor = + ActionCollectorVisitor(setOf(construction), node, constantEvaluator) val parent = node.getContainingUMethod() parent?.accept(actionCollectorVisitor) actions.addAll(actionCollectorVisitor.actions) - val isProtected = - actions.all(::isProtectedBroadcast) && !actionCollectorVisitor.intentFilterEscapesScope + val isProtected = actions.all(::isProtectedBroadcast) && !actionCollectorVisitor.escaped val unprotectedActionsList = actions.filterNot(::isProtectedBroadcast) return Pair(isProtected, unprotectedActionsList) } /** * For the supplied expression (e.g. intent filter argument), attempts to find its construction. - * This will be an `IntentFilter()` constructor, an `IntentFilter.create()` call, or `null`. + * This will be an `IntentFilter()` constructor, an `IntentFilter.create()` call, or `null`. It + * will only be found if the intent filter is constructed within the body of the supplied call + * expression (as in, it is a local variable defined within the function). */ private fun findIntentFilterConstruction( expression: UExpression, - node: UCallExpression + endAt: UElement, ): UCallExpression? { - val resolved = expression.tryResolve() - - if (resolved is PsiVariable) { - val assignment = findLastAssignment(resolved, node) ?: return null - return findIntentFilterConstruction(assignment, node) - } - - if (expression is UParenthesizedExpression) { - return findIntentFilterConstruction(expression.expression, node) - } + return findConstruction("android.content.IntentFilter", expression, endAt) + } - if (expression is UQualifiedReferenceExpression) { - val call = expression.selector as? UCallExpression ?: return null - return if (isReturningContext(call)) { - // eg. filter.apply { addAction("abc") } --> use filter variable. - findIntentFilterConstruction(expression.receiver, node) - } else { - // eg. IntentFilter.create("abc") --> use create("abc") UCallExpression. - findIntentFilterConstruction(call, node) - } - } + private fun isIntentFilterFactoryMethod(method: PsiMethod?) = + method != null && + (method.containingClass?.qualifiedName == "android.content.IntentFilter" && + (method.returnType?.canonicalText == "android.content.IntentFilter" || + method.isConstructor)) - val method = resolved as? PsiMethod ?: return null - return if (isIntentFilterFactoryMethod(method)) { - expression as? UCallExpression - } else { - null - } + private fun addActionArg( + call: UCallExpression, + evaluator: ConstantEvaluator, + actions: MutableSet<String>, + ) { + val actionArg = call.getArgumentForParameter(0) ?: return + val action = evaluator.evaluate(actionArg) as? String ?: return + actions.add(action) } - private fun isIntentFilterFactoryMethod(method: PsiMethod) = - (method.containingClass?.qualifiedName == "android.content.IntentFilter" && - (method.returnType?.canonicalText == "android.content.IntentFilter" || method.isConstructor)) - private class ActionCollectorVisitor( start: Collection<UElement>, val functionCall: UCallExpression, val evaluator: ConstantEvaluator, - ) : DataFlowAnalyzer(start) { + ) : EscapeCheckingDataFlowAnalyzer(start) { private var finished = false - var intentFilterEscapesScope = false val actions = mutableSetOf<String>() override fun argument(call: UCallExpression, reference: UElement) { @@ -111,19 +120,101 @@ object BroadcastReceiverUtils { finished -> return // We've reached the registerReceiver*() call in question. call == functionCall -> finished = true - // The filter 'intentFilterEscapesScope' to a method which could modify it. - getMethodName(call)!! !in BROADCAST_RECEIVER_METHOD_NAMES -> intentFilterEscapesScope = true + // Suppress escape checking if the intentFilter is passed to a registerReceiver method + getMethodName(call)!! !in BROADCAST_RECEIVER_METHOD_NAMES -> super.argument(call, reference) } } override fun receiver(call: UCallExpression) { if (!finished && getMethodName(call) == "addAction") { - val actionArg = call.getArgumentForParameter(0) - if (actionArg != null) { - val action = evaluator.evaluate(actionArg) as? String - if (action != null) actions.add(action) + addActionArg(call, evaluator, actions) + } + } + } + + /** + * Visits the provided class, accumulating the actions added to `intentFilterField`. Detects if + * `intentFilterField` escapes the class's scope. + */ + private class IntentFilterFieldDataFlowAnalyzer( + val intentFilterField: PsiField, + val javaEvaluator: JavaEvaluator, + val constantEvaluator: ConstantEvaluator, + ) : EscapeCheckingDataFlowAnalyzer(listOfNotNull(intentFilterField.toUElement())) { + val actions: MutableSet<String> = mutableSetOf() + + override fun returns(expression: UReturnExpression) { + val method = expression.jumpTarget?.tryResolve() as? PsiMethod + if (method != null && javaEvaluator.isPrivate(method)) return + super.returns(expression) + } + + override fun ignoreArgument(call: UCallExpression, reference: UElement): Boolean { + val resolved = call.resolve() ?: return super.ignoreArgument(call, reference) + // We don't care about registerReceiver methods (the overarching logic starts with those) + if ( + getMethodName(call) == "registerReceiver" && + javaEvaluator.isMemberInSubClassOf(resolved, "android.content.Context") + ) { + return true + } + return super.ignoreArgument(call, reference) + } + + override fun returnsSelf(call: UCallExpression): Boolean { + if (getMethodName(call) == "addAction") { + addActionArg(call, constantEvaluator, actions) + } + return super.returnsSelf(call) + } + + /** + * If `intentFilterField` can be set via a public method's parameter, then it escapes the class' + * scope because we don't know what actions may have been added externally before passing in + * said parameter. + */ + override fun visitBinaryExpression(node: UBinaryExpression): Boolean { + if (escaped) return super.visitBinaryExpression(node) + if ( + node.operator == UastBinaryOperator.ASSIGN && + node.leftOperand.tryResolve() == intentFilterField + ) { + val parameter = node.rightOperand.tryResolve() as? PsiParameter + val method = parameter?.let { it.declarationScope as? PsiMethod } + if ( + method?.containingClass == intentFilterField.containingClass && + !javaEvaluator.isPrivate(method) + ) { + escaped = true } } + + return super.visitBinaryExpression(node) + } + + override fun visitCallExpression(node: UCallExpression): Boolean { + if (isIntentFilterFieldConstruction(node)) { + addActionArg(node, constantEvaluator, actions) + } + + return super.visitCallExpression(node) + } + + /** + * detect if the call is the construction of `intentFilterField` itself, e.g. field = new + * IntentFilter("action") + */ + private fun isIntentFilterFieldConstruction(node: UCallExpression): Boolean { + if (!isIntentFilterFactoryMethod(node.resolve())) return false + val parent = + if (node.uastParent is UParenthesizedExpression) { + skipParenthesizedExprUp(node.uastParent as? UExpression) + } else node.uastParent + if (parent?.sourcePsi == intentFilterField) return true + return (parent as? UBinaryExpression)?.let { + it.operator == UastBinaryOperator.ASSIGN && it.leftOperand.tryResolve() == intentFilterField + } + ?: false } } diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/BuiltinIssueRegistry.kt b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/BuiltinIssueRegistry.kt index 0e7ec394bd..c55a9ffc02 100644 --- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/BuiltinIssueRegistry.kt +++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/BuiltinIssueRegistry.kt @@ -154,6 +154,7 @@ open class BuiltinIssueRegistry : IssueRegistry() { GradleDetector.ACCIDENTAL_OCTAL, GradleDetector.AGP_DEPENDENCY, GradleDetector.ANNOTATION_PROCESSOR_ON_COMPILE_PATH, + GradleDetector.BOM_WITHOUT_PLATFORM, GradleDetector.BUNDLED_GMS, GradleDetector.CHROMEOS_ABI_SUPPORT, GradleDetector.COMPATIBILITY, @@ -349,6 +350,7 @@ open class BuiltinIssueRegistry : IssueRegistry() { PropertyFileDetector.ESCAPE, PropertyFileDetector.HTTP, PropertyFileDetector.PROXY_PASSWORD, + ProviderPermissionDetector.PROVIDER_READ_PERMISSION_ONLY, PxUsageDetector.DP_ISSUE, PxUsageDetector.IN_MM_ISSUE, PxUsageDetector.PX_ISSUE, diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/DuplicateIdDetector.java b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/DuplicateIdDetector.java index c166a72b88..1e24d34152 100644 --- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/DuplicateIdDetector.java +++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/DuplicateIdDetector.java @@ -45,6 +45,7 @@ import com.android.tools.lint.detector.api.Location; import com.android.tools.lint.detector.api.Scope; import com.android.tools.lint.detector.api.Severity; import com.android.tools.lint.detector.api.XmlContext; +import com.android.utils.SdkUtils; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import java.io.File; @@ -362,7 +363,7 @@ public class DuplicateIdDetector extends LayoutDetector { } String getLayoutName() { - return Lint.getLayoutName(mFile); + return SdkUtils.getLayoutName(mFile); } String getDisplayName(@NonNull LintClient client) { @@ -422,7 +423,7 @@ public class DuplicateIdDetector extends LayoutDetector { Multimap<String, Layout> nameToLayout = ArrayListMultimap.create(mFileToLayout.size(), 4); for (File file : mFileToLayout.keySet()) { - String name = Lint.getLayoutName(file); + String name = SdkUtils.getLayoutName(file); nameToLayout.put(name, mFileToLayout.get(file)); } diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/GradleDetector.kt b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/GradleDetector.kt index 49e94ce6a9..5e6cb4d37e 100644 --- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/GradleDetector.kt +++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/GradleDetector.kt @@ -280,8 +280,6 @@ open class GradleDetector : Detector(), GradleScanner, TomlScanner { "November $MINIMUM_TARGET_SDK_VERSION_YEAR." val highest = context.client.highestKnownApiLevel - val label = "Update $property to $highest" - val fix = fix().name(label).replace().text(value).with(highest.toString()).build() // Don't report if already suppressed with EXPIRING val alreadySuppressed = @@ -290,7 +288,7 @@ open class GradleDetector : Detector(), GradleScanner, TomlScanner { context.isSuppressedWithComment(statementCookie, issue) if (!alreadySuppressed) { - report(context, statementCookie, issue, message, fix, true) + report(context, statementCookie, issue, message, null, true) } warned = true } @@ -590,6 +588,7 @@ open class GradleDetector : Detector(), GradleScanner, TomlScanner { if (property == "kapt") { checkKaptUsage(dependency, libTomlValue, context, statementCookie) } + checkForBomUsageWithoutPlatform(property, dependency, value, context, valueCookie) } } } else if (property == "packageNameSuffix") { @@ -2070,6 +2069,30 @@ open class GradleDetector : Detector(), GradleScanner, TomlScanner { report(context, cookie, KTX_EXTENSION_AVAILABLE, msg, fix) } + private fun checkForBomUsageWithoutPlatform( + property: String, + dependency: String, + value: String, + context: GradleContext, + valueCookie: Any + ) { + if ( + dependency.substringBeforeLast(':') in commonBoms && + (CompileConfiguration.IMPLEMENTATION.matches(property) || + CompileConfiguration.API.matches(property)) + ) { + val message = "BOM should be added with a call to platform()" + val fix = + fix() + .name("Add platform() to BOM declaration", true) + .replace() + .text(value) + .with("platform($value)") + .build() + report(context, valueCookie, BOM_WITHOUT_PLATFORM, message, fix) + } + } + /** * Report any blocked dependencies that weren't found in the build.gradle source file during * processing (we don't have accurate position info at this point) @@ -3211,6 +3234,24 @@ open class GradleDetector : Detector(), GradleScanner, TomlScanner { ) @JvmField + val BOM_WITHOUT_PLATFORM = + Issue.create( + id = "BomWithoutPlatform", + briefDescription = "Using a BOM without platform call", + explanation = + """ + When including a BOM, the dependency's coordinates must be wrapped \ + in a call to `platform()` for Gradle to interpret it correctly. + """, + category = Category.CORRECTNESS, + priority = 4, + severity = Severity.WARNING, + androidSpecific = true, + implementation = IMPLEMENTATION_WITH_TOML, + moreInfo = "https://developer.android.com/r/tools/gradle-bom-docs" + ) + + @JvmField val JAVA_PLUGIN_LANGUAGE_LEVEL = Issue.create( id = "JavaPluginLanguageLevel", @@ -3842,6 +3883,36 @@ open class GradleDetector : Detector(), GradleScanner, TomlScanner { "com.airbnb.android:paris-processor" to "com.airbnb.android:paris-processor", ) + private val commonBoms: Set<String> = + setOf( + // Google + "androidx.compose:compose-bom", + "com.google.firebase:firebase-bom", + // JetBrains + "org.jetbrains.kotlin:kotlin-bom", + "org.jetbrains.kotlinx:kotlinx-coroutines-bom", + "io.ktor:ktor-bom", + // Network and serialization + "com.squareup.okio:okio-bom", + "com.squareup.okhttp3:okhttp-bom", + "com.squareup.wire:wire-bom", + "com.fasterxml.jackson:jackson-bom", + "io.grpc:grpc-bom", + "org.http4k:http4k-bom", + "org.http4k:http4k-connect-bom", + // Testing + "org.junit:junit-bom", + "io.kotest:kotest-bom", + "io.cucumber:cucumber-bom", + // Others + "io.arrow-kt:arrow-stack", + "io.sentry:sentry-bom", + "dev.chrisbanes.compose:compose-bom", + "org.ow2.asm:asm-bom", + "software.amazon.awssdk:bom", + "com.walletconnect:android-bom", + ) + private fun libraryHasKtxExtension(mavenName: String): Boolean { // From https://developer.android.com/kotlin/ktx/extensions-list. return when (mavenName) { diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/LayoutConsistencyDetector.java b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/LayoutConsistencyDetector.java index 7bd4799a6b..d13c2e9edc 100644 --- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/LayoutConsistencyDetector.java +++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/LayoutConsistencyDetector.java @@ -39,6 +39,7 @@ import com.android.tools.lint.detector.api.Severity; import com.android.tools.lint.detector.api.SourceCodeScanner; import com.android.tools.lint.detector.api.XmlContext; import com.android.utils.Pair; +import com.android.utils.SdkUtils; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -131,7 +132,7 @@ public class LayoutConsistencyDetector extends LayoutDetector implements SourceC getFileMapList(context).add(Pair.of(context.file, fileMap)); } else { - String name = Lint.getLayoutName(context.file); + String name = SdkUtils.getLayoutName(context.file); Map<String, List<Location>> map = mLocations.get(name); if (map != null) { lookupLocations(context, root, map); @@ -142,7 +143,7 @@ public class LayoutConsistencyDetector extends LayoutDetector implements SourceC @NonNull private List<Pair<File, Map<String, String>>> getFileMapList(@NonNull XmlContext context) { - String name = Lint.getLayoutName(context.file); + String name = SdkUtils.getLayoutName(context.file); List<Pair<File, Map<String, String>>> list = mMap.get(name); if (list == null) { list = Lists.newArrayListWithCapacity(4); diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/MediaBrowserServiceCompatVersionDetector.kt b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/MediaBrowserServiceCompatVersionDetector.kt index 836b08bd96..3d74ca7bb0 100644 --- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/MediaBrowserServiceCompatVersionDetector.kt +++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/MediaBrowserServiceCompatVersionDetector.kt @@ -16,8 +16,7 @@ package com.android.tools.lint.checks import com.android.SdkConstants.SUPPORT_LIB_ARTIFACT -import com.android.ide.common.repository.GradleCoordinate -import com.android.ide.common.repository.GradleCoordinate.COMPARE_PLUS_HIGHER +import com.android.ide.common.gradle.Version import com.android.tools.lint.detector.api.Category import com.android.tools.lint.detector.api.Detector import com.android.tools.lint.detector.api.Implementation @@ -59,7 +58,7 @@ class MediaBrowserServiceCompatVersionDetector : Detector(), SourceCodeScanner { * Minimum recommended support library version that has the necessary fixes to ensure that * MediaBrowserServiceCompat is forward compatible with N. */ - val MIN_SUPPORT_V4_VERSION: GradleCoordinate = GradleCoordinate.parseVersionOnly("24.0.0") + val MIN_SUPPORT_V4_VERSION = Version.parse("24.0.0") const val MEDIA_BROWSER_SERVICE_COMPAT = "android.support.v4.media.MediaBrowserServiceCompat" } @@ -79,8 +78,8 @@ class MediaBrowserServiceCompatVersionDetector : Detector(), SourceCodeScanner { ?: return val mc = library.resolvedCoordinates if (mc.version.isNotBlank()) { - val libVersion = GradleCoordinate.parseVersionOnly(mc.version) - if (COMPARE_PLUS_HIGHER.compare(libVersion, MIN_SUPPORT_V4_VERSION) < 0) { + val libVersion = Version.parse(mc.version) + if (libVersion < MIN_SUPPORT_V4_VERSION) { val location = GradleDetector.getDependencyLocation(context, mc) val message = "Using a version of the class that is not forward compatible" context.report(ISSUE, location, message) diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/MergeRootFrameLayoutDetector.kt b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/MergeRootFrameLayoutDetector.kt index e85e9d00b3..3cf2d3a637 100644 --- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/MergeRootFrameLayoutDetector.kt +++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/MergeRootFrameLayoutDetector.kt @@ -48,10 +48,10 @@ import com.android.tools.lint.detector.api.Severity import com.android.tools.lint.detector.api.SourceCodeScanner import com.android.tools.lint.detector.api.UastLintUtils.Companion.toAndroidReferenceViaResolve import com.android.tools.lint.detector.api.XmlContext -import com.android.tools.lint.detector.api.getLayoutName import com.android.tools.lint.detector.api.getStyleAttributes import com.android.tools.lint.detector.api.isRootElement import com.android.utils.Pair +import com.android.utils.SdkUtils import com.intellij.psi.PsiMethod import java.util.ArrayList import java.util.EnumSet @@ -142,7 +142,7 @@ class MergeRootFrameLayoutDetector : LayoutDetector(), SourceCodeScanner { } } - val layout = getLayoutName(context.file) + val layout = SdkUtils.getLayoutName(context.file) val handle = context.createLocationHandle(element) handle.clientData = element val pending = pending ?: ArrayList<Pair<String, Location.Handle>>().also { pending = it } diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/OverdrawDetector.java b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/OverdrawDetector.java index 925361b9c5..c2da6f2ba0 100644 --- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/OverdrawDetector.java +++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/OverdrawDetector.java @@ -50,7 +50,6 @@ import com.android.tools.lint.detector.api.Implementation; import com.android.tools.lint.detector.api.Issue; import com.android.tools.lint.detector.api.JavaContext; import com.android.tools.lint.detector.api.LayoutDetector; -import com.android.tools.lint.detector.api.Lint; import com.android.tools.lint.detector.api.Location; import com.android.tools.lint.detector.api.Project; import com.android.tools.lint.detector.api.Scope; @@ -58,6 +57,7 @@ import com.android.tools.lint.detector.api.Severity; import com.android.tools.lint.detector.api.SourceCodeScanner; import com.android.tools.lint.detector.api.XmlContext; import com.android.utils.Pair; +import com.android.utils.SdkUtils; import com.intellij.psi.PsiClass; import java.io.File; import java.util.ArrayList; @@ -297,7 +297,7 @@ public class OverdrawDetector extends LayoutDetector implements SourceCodeScanne if (activity.startsWith(".")) { activity = context.getProject().getPackage() + activity; } - registerLayoutActivity(Lint.getLayoutName(context.file), activity); + registerLayoutActivity(SdkUtils.getLayoutName(context.file), activity); } } } diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/ProviderPermissionDetector.kt b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/ProviderPermissionDetector.kt new file mode 100644 index 0000000000..329e9864fb --- /dev/null +++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/ProviderPermissionDetector.kt @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2022 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.tools.lint.checks + +import com.android.SdkConstants.ANDROID_URI +import com.android.SdkConstants.ATTR_PERMISSION +import com.android.SdkConstants.ATTR_READ_PERMISSION +import com.android.SdkConstants.ATTR_WRITE_PERMISSION +import com.android.SdkConstants.CLASS_CONTENTPROVIDER +import com.android.SdkConstants.TAG_APPLICATION +import com.android.SdkConstants.TAG_PROVIDER +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Context +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Incident +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.LintMap +import com.android.tools.lint.detector.api.LocationType +import com.android.tools.lint.detector.api.PartialResult +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import com.android.tools.lint.detector.api.SourceCodeScanner +import com.android.tools.lint.detector.api.resolveManifestName +import com.android.utils.next +import com.android.utils.subtag +import org.jetbrains.uast.UBlockExpression +import org.jetbrains.uast.UCallExpression +import org.jetbrains.uast.UClass +import org.jetbrains.uast.UExpression +import org.jetbrains.uast.ULiteralExpression +import org.jetbrains.uast.UMethod +import org.jetbrains.uast.UReturnExpression +import org.jetbrains.uast.USimpleNameReferenceExpression +import org.jetbrains.uast.UThrowExpression +import org.jetbrains.uast.skipParenthesizedExprDown +import org.w3c.dom.Element + +/** + * Looks for an issue related to manifests declaring only a readPermission for ContentProviders that + * implement any of the write APIs (insert, update, and delete), thereby exposing these write APIs + * to other apps with no permission check. + */ +class ProviderPermissionDetector : Detector(), SourceCodeScanner { + override fun applicableSuperClasses(): List<String> = listOf(CLASS_CONTENTPROVIDER) + + /** + * For each ContentProvider implementation, if any of its write APIs are implemented, adds its + * location and implemented write methods into the lint map. Here, implemented API is defined by + * [isImplemented]. + */ + override fun visitClass(context: JavaContext, declaration: UClass) { + val providerName = declaration.qualifiedName ?: return + val implWriteMethods = + declaration.methods.filter { it.isProviderAbstractWriteMethod() && it.isImplemented() } + if (implWriteMethods.isEmpty()) return + val implementedWriteMethodNames = + implWriteMethods.joinToString(prefix = "{", separator = ", ", postfix = "}") { + "`${it.name}`" + } + val providerMap = LintMap() + providerMap.put(KEY_LOCATION, context.getNameLocation(declaration)) + providerMap.put(KEY_IMPL_WRITE_METHODS, implementedWriteMethodNames) + context.getPartialResults(PROVIDER_READ_PERMISSION_ONLY).map().put(providerName, providerMap) + } + + override fun afterCheckRootProject(context: Context) { + if (context.isGlobalAnalysis()) { + checkPartialResults(context, context.getPartialResults(PROVIDER_READ_PERMISSION_ONLY)) + } + } + + /** + * Only considers the main app. Iterates over all provider tags and reports + * [PROVIDER_READ_PERMISSION_ONLY] issue if it occurs. + */ + override fun checkPartialResults(context: Context, partialResults: PartialResult) { + if (!context.driver.isIsolated() && context.project.isLibrary) return + val mergedManifest = context.mainProject.mergedManifest ?: return + val root = mergedManifest.documentElement ?: return + val application = root.subtag(TAG_APPLICATION) ?: return + var provider = application.subtag(TAG_PROVIDER) + // Combine lint maps from all partial analysis runs into one lint map + // of providerName -> Map(implementedWriteMethods: String, location: Location) + val combinedMap = LintMap() + partialResults.maps().forEach { combinedMap.putAll(it) } + while (provider != null) { + reportIfProviderReadPermissionOnlyOccurs(context, provider, combinedMap) + provider = provider.next(TAG_PROVIDER) + } + } + + /** + * [PROVIDER_READ_PERMISSION_ONLY] issue occurs if a provider satisfies all of these conditions: + * - It has a readPermission attribute. + * - It doesn't have permission and writePermission attributes. + * - It has at least one implemented write API which is identified by the provider's existence in + * the lint map. + * + * If the detector is running "on-the-fly", the issue will be reported in the location of the + * corresponding ContentProvider. + * + * If the detector isn't running "on-the-fly", the issue will be reported in the location of the + * provider's manifest entry. + */ + private fun reportIfProviderReadPermissionOnlyOccurs( + context: Context, + provider: Element, + providersMap: LintMap + ) { + val readPermission = provider.getAttributeNodeNS(ANDROID_URI, ATTR_READ_PERMISSION) ?: return + provider.getAttributeNodeNS(ANDROID_URI, ATTR_WRITE_PERMISSION)?.let { + return + } + provider.getAttributeNodeNS(ANDROID_URI, ATTR_PERMISSION)?.let { + return + } + val providerName = resolveManifestName(provider) + val providerMap = providersMap.getMap(providerName) ?: return + val classLocation = providerMap.getLocation(KEY_LOCATION) ?: return + val implementedWriteMethods = providerMap.getString(KEY_IMPL_WRITE_METHODS) ?: return + val manifestLocation = context.getLocation(readPermission, LocationType.NAME) + val reportLocation = if (context.driver.isIsolated()) classLocation else manifestLocation + context.report( + Incident( + PROVIDER_READ_PERMISSION_ONLY, + reportLocation, + "$providerName implements $implementedWriteMethods write APIs but " + + "does not protect them with a permission. Update the <provider> tag to use " + + "android:permission or android:writePermission", + fix() + .replace() + .text(ATTR_READ_PERMISSION) + .with(ATTR_PERMISSION) + .range(manifestLocation) + .build() + ) + ) + } + + /** + * A method is considered to be implemented if any of these conditions is true: + * - Its body has more than 1 statement. + * - Its body has 1 statement and that statement is neither of these: + * - a throw expression + * - a return of a literal (String, Number or null) + * - a constructor call to error + * - a constructor call to to do + */ + private fun UMethod.isImplemented(): Boolean { + val body = this.uastBody ?: return false + val expressions = if (body is UBlockExpression) body.expressions else listOf(body) + val first = expressions.firstOrNull()?.skipParenthesizedExprDown() + return expressions.size > 1 || + !(first.isThrowExpression() || first.isReturnLiteral() || first.isError() || first.isTodo()) + } + + private fun UExpression?.isThrowExpression(): Boolean { + return this.getInsideReturnOrThis() is UThrowExpression + } + + private fun UExpression?.isReturnLiteral(): Boolean { + return this is UReturnExpression && this.returnExpression is ULiteralExpression + } + + private fun UExpression?.isError(): Boolean { + return this.getConstructorName() == "error" + } + + private fun UExpression?.isTodo(): Boolean { + return this.getConstructorName() == "TODO" + } + + private fun UExpression?.getInsideReturnOrThis(): UExpression? { + return (this as? UReturnExpression)?.returnExpression?.skipParenthesizedExprDown() ?: this + } + + private fun UExpression?.getConstructorName(): String? { + return ((this.getInsideReturnOrThis() as? UCallExpression)?.classReference + as? USimpleNameReferenceExpression) + ?.identifier + } + + private fun UMethod.isProviderAbstractWriteMethod(): Boolean { + val paramSize = this.uastParameters.size + return when (this.name) { + "insert" -> paramSize == 2 + "delete" -> paramSize == 3 + "update" -> paramSize == 4 + else -> false + } + } + + companion object { + @JvmField + val PROVIDER_READ_PERMISSION_ONLY: Issue = + Issue.create( + id = "ProviderReadPermissionOnly", + briefDescription = "Provider with readPermission only and implemented write APIs", + explanation = + """ + This check looks for Content Providers that only have the `readPermission` \ + attribute but implement write APIs. + + If `android:readPermission` is specified and both `android:permission` and \ + `android:writePermission` are omitted, other apps can access any write operations \ + that this provider exposes with no permission check. For a quick fix, changing the \ + existing `android:readPermission` to `android:permission` will protect both read \ + and write access with the same permission. Alternatively, declaring a separate \ + `android:writePermission` can protect write access with a different permission. + """, + category = Category.SECURITY, + priority = 5, + severity = Severity.WARNING, + androidSpecific = true, + implementation = + Implementation(ProviderPermissionDetector::class.java, Scope.JAVA_FILE_SCOPE) + ) + + const val KEY_LOCATION = "location" + const val KEY_IMPL_WRITE_METHODS = "implementedWriteMethods" + } +} diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/RegisterReceiverFlagDetector.kt b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/RegisterReceiverFlagDetector.kt index c27dd59f34..2465cb1619 100644 --- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/RegisterReceiverFlagDetector.kt +++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/RegisterReceiverFlagDetector.kt @@ -54,7 +54,11 @@ class RegisterReceiverFlagDetector : Detector(), SourceCodeScanner { val evaluator = ConstantEvaluator().allowFieldInitializers() val (isProtected, unprotectedActionsList) = - checkIsProtectedReceiverAndReturnUnprotectedActions(filterArg, node, evaluator) + checkIsProtectedReceiverAndReturnUnprotectedActions( + filterArg, + node, + context.evaluator, + ) if (!isProtected) { val flags = evaluator.evaluate(flagsArg) as? Int diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/RequiredAttributeDetector.java b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/RequiredAttributeDetector.java index 42c79b7c57..aa291236e9 100644 --- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/RequiredAttributeDetector.java +++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/RequiredAttributeDetector.java @@ -39,7 +39,6 @@ import static com.android.SdkConstants.VIEW_INCLUDE; import static com.android.SdkConstants.VIEW_MERGE; import static com.android.resources.ResourceFolderType.LAYOUT; import static com.android.resources.ResourceFolderType.VALUES; -import static com.android.tools.lint.detector.api.Lint.getLayoutName; import com.android.annotations.NonNull; import com.android.annotations.Nullable; @@ -59,6 +58,7 @@ import com.android.tools.lint.detector.api.Scope; import com.android.tools.lint.detector.api.Severity; import com.android.tools.lint.detector.api.SourceCodeScanner; import com.android.tools.lint.detector.api.XmlContext; +import com.android.utils.SdkUtils; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -457,7 +457,7 @@ public class RequiredAttributeDetector extends LayoutDetector implements SourceC boolean isRoot = isRootElement(element); if (isRoot || isRootElement(element.getParentNode()) && VIEW_MERGE.equals(parentTag)) { - String name = LAYOUT_RESOURCE_PREFIX + getLayoutName(context.file); + String name = LAYOUT_RESOURCE_PREFIX + SdkUtils.getLayoutName(context.file); if (!hasWidth && mIncludedWidths != null) { hasWidth = mIncludedWidths.contains(name); // If the layout is *also* included in a context where the width diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/UnsafeIntentLaunchDetector.kt b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/UnsafeIntentLaunchDetector.kt index e43dce6aae..5bd51d4405 100644 --- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/UnsafeIntentLaunchDetector.kt +++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/UnsafeIntentLaunchDetector.kt @@ -20,6 +20,9 @@ import com.android.SdkConstants.ANDROID_URI import com.android.SdkConstants.ATTR_EXPORTED import com.android.SdkConstants.ATTR_NAME import com.android.SdkConstants.ATTR_PERMISSION +import com.android.SdkConstants.TAG_ACTIVITY +import com.android.SdkConstants.TAG_RECEIVER +import com.android.SdkConstants.TAG_SERVICE import com.android.tools.lint.checks.BroadcastReceiverUtils.BROADCAST_RECEIVER_METHOD_NAMES import com.android.tools.lint.client.api.JavaEvaluator import com.android.tools.lint.client.api.TYPE_INT @@ -38,25 +41,37 @@ import com.android.tools.lint.detector.api.Scope import com.android.tools.lint.detector.api.Severity import com.android.tools.lint.detector.api.SourceCodeScanner import com.android.tools.lint.detector.api.UastLintUtils +import com.android.tools.lint.detector.api.UastLintUtils.Companion.findConstruction import com.android.tools.lint.detector.api.UastLintUtils.Companion.findLastAssignment import com.android.tools.lint.detector.api.XmlContext import com.android.tools.lint.detector.api.XmlScanner import com.android.tools.lint.detector.api.findSelector +import com.android.tools.lint.detector.api.isReturningContext import com.android.tools.lint.detector.api.isReturningLambdaResult import com.android.tools.lint.detector.api.isScopingThis +import com.android.utils.iterator +import com.android.utils.subtag import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiSwitchLabelStatementBase import com.intellij.psi.PsiVariable import java.util.EnumSet +import org.jetbrains.uast.UBinaryExpression import org.jetbrains.uast.UCallExpression import org.jetbrains.uast.UClass import org.jetbrains.uast.UElement import org.jetbrains.uast.UExpression +import org.jetbrains.uast.UIfExpression import org.jetbrains.uast.ULambdaExpression import org.jetbrains.uast.UMethod import org.jetbrains.uast.UParameter +import org.jetbrains.uast.UQualifiedReferenceExpression +import org.jetbrains.uast.UReferenceExpression import org.jetbrains.uast.UReturnExpression import org.jetbrains.uast.USimpleNameReferenceExpression +import org.jetbrains.uast.USwitchClauseExpression +import org.jetbrains.uast.USwitchExpression import org.jetbrains.uast.UThisExpression +import org.jetbrains.uast.UastBinaryOperator import org.jetbrains.uast.getParentOfType import org.jetbrains.uast.getQualifiedName import org.jetbrains.uast.isNullLiteral @@ -88,24 +103,49 @@ class UnsafeIntentLaunchDetector : Detector(), SourceCodeScanner, XmlScanner { override fun getApplicableElements() = listOf( - SdkConstants.TAG_ACTIVITY, - SdkConstants.TAG_SERVICE, - SdkConstants.TAG_RECEIVER, + TAG_ACTIVITY, + TAG_SERVICE, + TAG_RECEIVER, ) override fun visitElement(context: XmlContext, element: Element) { - val exportedAttr = element.getAttributeNS(ANDROID_URI, ATTR_EXPORTED) + storeUnprotectedComponents(context, getProtectedComponent(context, element) ?: return) + } + + private fun isComponentExported( + context: Context, + root: Element, + incidentComponent: String? + ): Boolean { + val application = root.subtag(SdkConstants.TAG_APPLICATION) ?: return false + for (component in application) { + when (component.tagName) { + TAG_ACTIVITY, + TAG_RECEIVER, + TAG_SERVICE -> { + if (incidentComponent == getProtectedComponent(context, component)) return true + } + } + } + return false + } + + // Returns the fully qualified component name if the component is protected; otherwise, null + // The element passed in is guaranteed to be one of the activity, receiver or service tag. + private fun getProtectedComponent(context: Context, component: Element): String? { + val exportedAttr = component.getAttributeNS(ANDROID_URI, ATTR_EXPORTED) if ( "true" == exportedAttr || - exportedAttr.isEmpty() && element.getElementsByTagName("intent-filter").length > 0 + exportedAttr.isEmpty() && component.getElementsByTagName("intent-filter").length > 0 ) { - val permission = element.getAttributeNS(ANDROID_URI, ATTR_PERMISSION) + val permission = component.getAttributeNS(ANDROID_URI, ATTR_PERMISSION) if (!isProbablyProtectedBySignaturePermission(permission)) { - var componentName = element.getAttributeNS(ANDROID_URI, ATTR_NAME) + var componentName = component.getAttributeNS(ANDROID_URI, ATTR_NAME) if (componentName.startsWith(".")) componentName = context.project.`package` + componentName - storeUnprotectedComponents(context, componentName) + return componentName } } + return null } // Any permission that is not declared by the system as normal permission is considered as a @@ -144,10 +184,13 @@ class UnsafeIntentLaunchDetector : Detector(), SourceCodeScanner, XmlScanner { initial = setOf(intentParam ?: return), context = context, location = context.getLocation(intentParam.sourcePsi), + checkProtectedBroadcast = + UNSAFE_INTENT_AS_PARAMETER_METHODS[BROADCAST_RECEIVER_CLASS]?.contains(methodName) == + true ) method.accept(visitor) if (visitor.launched) { - storeIncidentsToPartialResults(context, visitor) + reportIncident(context, visitor) } } } @@ -175,18 +218,11 @@ class UnsafeIntentLaunchDetector : Detector(), SourceCodeScanner, XmlScanner { containingMethod?.accept(visitor) if (visitor.launched) { if (visitor.unprotectedReceiver) { - // The registered-at-runtime receiver case, report the issue immediately. - val message = - """ - This intent could be coming from an untrusted source. It is later launched by \ - an unprotected component. You could either make the component \ - protected; or sanitize this intent using \ - androidx.core.content.IntentSanitizer. - """ - .trimIndent() - context.report(Incident(ISSUE, visitor.location, message)) + // The anonymous component registered-at-runtime receiver case, report the issue + // immediately. + reportIssue(context, null, visitor.location) } else { - storeIncidentsToPartialResults(context, visitor) + reportIncident(context, visitor) } } } @@ -237,18 +273,19 @@ class UnsafeIntentLaunchDetector : Detector(), SourceCodeScanner, XmlScanner { val receiverArg = UastLintUtils.findArgument(call, method, BROADCAST_RECEIVER_CLASS) ?: return if (receiverArg.isNullLiteral()) return - if (!isRuntimeReceiverProtected(call, method)) { - val receiverVar = receiverArg.tryResolve() as? PsiVariable ?: return - val receiverAssignment = - findLastAssignment(receiverVar, call)?.skipParenthesizedExprDown() ?: return - val receiverConstructor = receiverAssignment.findSelector() as? UCallExpression + if (!isRuntimeReceiverProtected(call, method, context.evaluator)) { + val receiverConstructor = findConstruction(BROADCAST_RECEIVER_CLASS, receiverArg, call, true) val unprotectedReceiverClassName = receiverConstructor?.classReference.getQualifiedName() ?: return storeUnprotectedComponents(context, unprotectedReceiverClassName) } } - fun isRuntimeReceiverProtected(call: UCallExpression, method: PsiMethod): Boolean { + fun isRuntimeReceiverProtected( + call: UCallExpression, + method: PsiMethod, + javaEvaluator: JavaEvaluator + ): Boolean { // The parameter positions vary across the various registerReceiver*() methods, so rather // than hardcode them we simply look them up based on the parameter name and type. @@ -267,7 +304,7 @@ class UnsafeIntentLaunchDetector : Detector(), SourceCodeScanner, XmlScanner { BroadcastReceiverUtils.checkIsProtectedReceiverAndReturnUnprotectedActions( filterArg, call, - evaluator + javaEvaluator ) return isProtected @@ -281,18 +318,31 @@ class UnsafeIntentLaunchDetector : Detector(), SourceCodeScanner, XmlScanner { unprotectedComponents.put(unprotectedComponentName, true) } - private fun storeIncidentsToPartialResults(context: Context, visitor: IntentLaunchChecker) { - val lintMap = context.getPartialResults(ISSUE).map() - val incidents = lintMap.getMap(KEY_INCIDENTS) ?: map().also { lintMap.put(KEY_INCIDENTS, it) } - // key is not important. so the size of the map is used to make it unique. - incidents.put( - incidents.size.toString(), - map().apply { - put(KEY_LOCATION, visitor.location) - put(KEY_SECONDARY_LOCATION, visitor.location.secondary ?: return) - put(KEY_INCIDENT_CLASS, visitor.incidentClass ?: return) + private fun reportIncident(context: Context, visitor: IntentLaunchChecker) { + if (context.isGlobalAnalysis()) { + val incidentComponent = visitor.incidentClass + if ( + isComponentExported( + context, + context.mainProject.mergedManifest?.documentElement ?: return, + incidentComponent + ) + ) { + reportIssue(context, incidentComponent, visitor.location) } - ) + } else { + val lintMap = context.getPartialResults(ISSUE).map() + val incidents = lintMap.getMap(KEY_INCIDENTS) ?: map().also { lintMap.put(KEY_INCIDENTS, it) } + // key is not important. so the size of the map is used to make it unique. + incidents.put( + incidents.size.toString(), + map().apply { + put(KEY_LOCATION, visitor.location) + put(KEY_SECONDARY_LOCATION, visitor.location.secondary ?: return) + put(KEY_INCIDENT_CLASS, visitor.incidentClass ?: return) + } + ) + } } override fun afterCheckRootProject(context: Context) { @@ -310,19 +360,23 @@ class UnsafeIntentLaunchDetector : Detector(), SourceCodeScanner, XmlScanner { if (unprotectedComponents.containsKey(incidentComponent)) { val location = incidentMap.getLocation(KEY_LOCATION) ?: continue location.secondary = incidentMap.getLocation(KEY_SECONDARY_LOCATION) - val message = - """ - This intent could be coming from an untrusted source. It is later launched by \ - an unprotected component $incidentComponent. You could either make the component \ - $incidentComponent protected; or sanitize this intent using \ - androidx.core.content.IntentSanitizer. - """ - .trimIndent() - context.report(Incident(ISSUE, location, message)) + reportIssue(context, incidentComponent, location) } } } + private fun reportIssue(context: Context, incidentComponent: String?, location: Location) { + val component = if (incidentComponent.isNullOrBlank()) "" else " $incidentComponent" + val message = + """ + This intent could be coming from an untrusted source. It is later launched by \ + an unprotected component$component. You could either make the component$component \ + protected; or sanitize this intent using androidx.core.content.IntentSanitizer. + """ + .trimIndent() + context.report(Incident(ISSUE, location, message)) + } + private inner class IntentLaunchChecker( initial: Collection<UElement>, var context: JavaContext, @@ -331,7 +385,8 @@ class UnsafeIntentLaunchDetector : Detector(), SourceCodeScanner, XmlScanner { var launched: Boolean = false, var returned: Boolean = false, var unprotectedReceiver: Boolean = false, - var resolveCallDepth: Int = 0 + var resolveCallDepth: Int = 0, + var checkProtectedBroadcast: Boolean = false ) : DataFlowAnalyzer(initial) { override fun returnsSelf(call: UCallExpression): Boolean { @@ -374,9 +429,11 @@ class UnsafeIntentLaunchDetector : Detector(), SourceCodeScanner, XmlScanner { } } if (isIntentLaunchedBySystem(context.evaluator, call)) { - launched = true - location.secondary = context.getLocation(call) - location.secondary?.message = "The unsafe intent is launched here." + if (!checkProtectedBroadcast || !inProtectedBroadcastBranch(context, call, reference)) { + launched = true + location.secondary = context.getLocation(call) + location.secondary?.message = "The unsafe intent is launched here." + } } else { if (resolveCallDepth > MAX_CALL_DEPTH) return // escaped to another method call. check the method recursively. @@ -393,7 +450,7 @@ class UnsafeIntentLaunchDetector : Detector(), SourceCodeScanner, XmlScanner { ) containingMethod.accept(visitor) if (visitor.launched) { - storeIncidentsToPartialResults(context, visitor) + reportIncident(context, visitor) } else if (visitor.returned) { // if the visited method returns the passed-in unsafe Intent, add this call to track it. instances.add(call) @@ -401,6 +458,113 @@ class UnsafeIntentLaunchDetector : Detector(), SourceCodeScanner, XmlScanner { } } + /** Returns if the expression is evaluated to a protected broadcast action. */ + private fun isProtectedBroadcastAction(expression: UExpression?): Boolean { + return BroadcastReceiverUtils.isProtectedBroadcast( + ConstantEvaluator().allowFieldInitializers().evaluate(expression) as String + ) + } + + /** + * Check if the call is within a branch of code that is protected by a protected broadcast + * action. If could either be an if statement that checks if the action of the intent is equal + * to a protected action; or an equivalent of a switch case statement. + */ + private fun inProtectedBroadcastBranch( + context: JavaContext, + call: UCallExpression, + reference: UElement + ): Boolean { + return inProtectedBroadcastIfBranch(context, call, reference) || + inProtectedBroadcastSwitchCase(call, reference) + } + + private fun inProtectedBroadcastIfBranch( + context: JavaContext, + call: UCallExpression, + reference: UElement + ): Boolean { + var ifExp = call.getParentOfType<UIfExpression>() + while (ifExp != null) { + var op1: UExpression? = null + var op2: UExpression? = null + val condition = ifExp.condition + if (condition is UBinaryExpression && condition.operator === UastBinaryOperator.EQUALS) { + // handle kotlin == + op1 = condition.leftOperand + op2 = condition.rightOperand + } else if (condition is UQualifiedReferenceExpression) { + // handle java equals method. + val methodCall = condition.selector as? UCallExpression + if (methodCall?.methodName == "equals") { + op1 = condition.receiver + op2 = methodCall.valueArguments[0] + } + } + if ( + op1 != null && + op2 != null && + ((isIntentAction(op1, reference) && isProtectedBroadcastAction(op2)) || + (isIntentAction(op2, reference) && isProtectedBroadcastAction(op1))) + ) { + return context.getLocation(call) in context.getLocation(ifExp.thenExpression) + } + ifExp = ifExp.getParentOfType() + } + return false + } + + private fun inProtectedBroadcastSwitchCase( + call: UCallExpression, + reference: UElement + ): Boolean { + var switchExp = call.getParentOfType<USwitchExpression>() + while (switchExp != null) { + val subject = switchExp.expression as? UReferenceExpression + val caseExpression = call.getParentOfType<USwitchClauseExpression>() ?: return false + val caseValue = caseExpression.caseValues.firstOrNull() ?: return false + if ((caseValue.sourcePsi as? PsiSwitchLabelStatementBase)?.isDefaultCase == true) + return false + if (isIntentAction(subject, reference) && isProtectedBroadcastAction(caseValue)) return true + switchExp = switchExp.getParentOfType() + } + return false + } + + private fun isIntentAction(expression: UExpression?, intentRef: UElement): Boolean { + val actionAssignmentCall = findIntentActionAssignmentCall(expression) + return actionAssignmentCall?.receiver?.skipParenthesizedExprDown()?.tryResolve() === + intentRef.tryResolve() + } + + private fun findIntentActionAssignmentCall(expression: UExpression?): UCallExpression? { + val actionExpr = expression?.skipParenthesizedExprDown() + val resolved = actionExpr?.tryResolve() + + if (resolved is PsiVariable) { + val assignment = findLastAssignment(resolved, actionExpr) ?: return null + return findIntentActionAssignmentCall(assignment) + } + + if (actionExpr is UQualifiedReferenceExpression) { + val call = actionExpr.selector as? UCallExpression ?: return null + return if (isReturningContext(call)) { + // eg. intent.apply { setAction("abc") } --> use filter variable. + findIntentActionAssignmentCall(actionExpr.receiver) + } else { + // eg. intent.getAction("abc") --> use getAction("abc") UCallExpression. + findIntentActionAssignmentCall(call) + } + } + + val method = resolved as? PsiMethod ?: return null + return if ("getAction" == method.name) { + actionExpr as? UCallExpression + } else { + null + } + } + /** * Handles kotlin scoping function with "this" object reference, like run, with. If "this" is * tracked, get into the lambda function and keep track of "this". @@ -420,7 +584,7 @@ class UnsafeIntentLaunchDetector : Detector(), SourceCodeScanner, XmlScanner { ) lambda.body.accept(visitor) if (visitor.launched) { - storeIncidentsToPartialResults(context, visitor) + reportIncident(context, visitor) } } } @@ -488,7 +652,7 @@ class UnsafeIntentLaunchDetector : Detector(), SourceCodeScanner, XmlScanner { if (call.methodName in registerReceiverMethods) { val method = call.resolve() ?: return - if (!isRuntimeReceiverProtected(call, method)) { + if (!isRuntimeReceiverProtected(call, method, context.evaluator)) { result = true } } @@ -548,7 +712,8 @@ class UnsafeIntentLaunchDetector : Detector(), SourceCodeScanner, XmlScanner { private val IMPLEMENTATION = Implementation( UnsafeIntentLaunchDetector::class.java, - EnumSet.of(Scope.JAVA_FILE, Scope.MANIFEST) + EnumSet.of(Scope.JAVA_FILE, Scope.MANIFEST), + Scope.JAVA_FILE_SCOPE, ) /** Issue describing the problem and pointing to the detector implementation. */ diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/WatchFaceEditorDetector.kt b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/WatchFaceEditorDetector.kt index dc4724bad7..d483ccd9d7 100644 --- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/WatchFaceEditorDetector.kt +++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/WatchFaceEditorDetector.kt @@ -39,8 +39,8 @@ class WatchFaceEditorDetector : Detector(), XmlScanner { briefDescription = "Watch face editor must use launchMode=\"standard\"", explanation = """ - Watch face editor activities must be able to launch in the Wear OS app activity task \ - in order to work correctly. Thus only `launchMode="standard"` is allowed. The watch \ + Watch face editor activities must be able to launch in the Wear OS companion app activity \ + task in order to work correctly. Thus only `launchMode="standard"` is allowed. The watch \ face will not be shown on the watch if it does not satisfy this requirement. """, category = Category.CORRECTNESS, diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/MainTest.java b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/MainTest.java index 95f2efd439..4d8115d2d0 100644 --- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/MainTest.java +++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/MainTest.java @@ -124,7 +124,14 @@ public class MainTest extends AbstractCheckTest { } } if (expectedError != null && !expectedError.trim().equals(stderr.trim())) { - assertEquals(expectedError, stderr); // instead of fail: get difference in output + // TODO: https://youtrack.jetbrains.com/issue/KT-57715 + // Until then, we can't assert explicit "equals" yet. + if (Arrays.stream(args).anyMatch((arg) -> arg == "--XuseK2Uast")) { + assertThat(stderr).contains(expectedError); + } else { + // instead of fail: get difference in output + assertEquals(expectedError, stderr); + } } assertEquals("Unexpected exit code", expectedExitCode, exitCode); } finally { diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/ProjectInitializerTest.kt b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/ProjectInitializerTest.kt index 9ed7bcb097..cc701bb8d6 100644 --- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/ProjectInitializerTest.kt +++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/ProjectInitializerTest.kt @@ -58,8 +58,16 @@ import org.junit.rules.TemporaryFolder class ProjectInitializerTest { @Test - fun testManualProject() { + fun testManualProjectK1() { + testManualProject(isK2 = false) + } + @Test + fun testManualProjectK2() { + testManualProject(isK2 = true) + } + + private fun testManualProject(isK2: Boolean) { val library = project( manifest( @@ -210,8 +218,10 @@ class ProjectInitializerTest { val appProjectDir = projects[1] val appProjectPath = appProjectDir.path - val sdk = temp.newFolder("fake-sdk") - val cacheDir = temp.newFolder("cache") + // TO avoid already existing temp folders + val suffix = if (isK2) "-k2" else "-k1" + val sdk = temp.newFolder("fake-sdk$suffix") + val cacheDir = temp.newFolder("cache$suffix") @Language("XML") val mergedManifestXml = """ @@ -241,7 +251,7 @@ class ProjectInitializerTest { """ .trimIndent() - val mergedManifest = temp.newFile("merged-manifest") + val mergedManifest = temp.newFile("merged-manifest$suffix") Files.asCharSink(mergedManifest, Charsets.UTF_8).write(mergedManifestXml) @Language("XML") @@ -343,6 +353,12 @@ class ProjectInitializerTest { val canonicalRoot = root.canonicalPath + // TODO: https://youtrack.jetbrains.com/issue/KT-57715 + val expectedError = + if (isK2) + "WARN: ROOT/test.jar: ROOT/test.jar\n" + "java.nio.file.NoSuchFileException: ROOT/test.jar" + else "w: Classpath entry points to a non-existent location: ROOT/test.jar" + MainTest.checkDriver( """ baseline.xml: Information: 1 error was filtered out because it is listed in the baseline file, baseline.xml @@ -363,13 +379,14 @@ class ProjectInitializerTest { AndroidManifest.xml:8: Previous permission here 2 errors, 2 warnings (1 error filtered by baseline baseline.xml) """, - "w: Classpath entry points to a non-existent location: ROOT/test.jar", + expectedError, // Expected exit code ERRNO_SUCCESS, // Args arrayOf( + if (isK2) "--XuseK2Uast" else "", "--check", "UniquePermission,DuplicateDefinition,SdCardPath", "--config", diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/GradleDetectorTest.kt b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/GradleDetectorTest.kt index 2abf2438cc..d673a9be37 100644 --- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/GradleDetectorTest.kt +++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/GradleDetectorTest.kt @@ -22,13 +22,13 @@ import com.android.ide.common.repository.GoogleMavenRepository.Companion.MAVEN_G import com.android.ide.common.repository.GradleCoordinate import com.android.sdklib.AndroidVersion import com.android.sdklib.IAndroidTarget -import com.android.sdklib.SdkVersionInfo.HIGHEST_KNOWN_STABLE_API import com.android.sdklib.SdkVersionInfo.LOWEST_ACTIVE_API import com.android.testutils.MockitoKt.whenever import com.android.testutils.TestUtils import com.android.tools.lint.checks.GradleDetector.Companion.ACCIDENTAL_OCTAL import com.android.tools.lint.checks.GradleDetector.Companion.AGP_DEPENDENCY import com.android.tools.lint.checks.GradleDetector.Companion.ANNOTATION_PROCESSOR_ON_COMPILE_PATH +import com.android.tools.lint.checks.GradleDetector.Companion.BOM_WITHOUT_PLATFORM import com.android.tools.lint.checks.GradleDetector.Companion.BUNDLED_GMS import com.android.tools.lint.checks.GradleDetector.Companion.CHROMEOS_ABI_SUPPORT import com.android.tools.lint.checks.GradleDetector.Companion.COMPATIBILITY @@ -4780,18 +4780,6 @@ class GradleDetectorTest : AbstractCheckTest() { 2 errors, 0 warnings """ ) - .expectFixDiffs( - """ - Fix for build.gradle line 5: Update targetSdkVersion to $HIGHEST_KNOWN_STABLE_API: - @@ -5 +5 - - targetSdkVersion 17 - + targetSdkVersion $HIGHEST_KNOWN_STABLE_API - Fix for build.gradle line 6: Update targetSdk to $HIGHEST_KNOWN_STABLE_API: - @@ -6 +6 - - targetSdk 17 - + targetSdk $HIGHEST_KNOWN_STABLE_API - """ - ) } finally { GradleDetector.calendar = null } @@ -4832,14 +4820,6 @@ class GradleDetectorTest : AbstractCheckTest() { 1 errors, 0 warnings """ ) - .expectFixDiffs( - """ - Fix for build.gradle line 6: Update targetSdkVersion to $HIGHEST_KNOWN_STABLE_API: - @@ -6 +6 - - targetSdkVersion 30 - + targetSdkVersion $HIGHEST_KNOWN_STABLE_API - """ - ) } finally { GradleDetector.calendar = null } @@ -4877,14 +4857,6 @@ class GradleDetectorTest : AbstractCheckTest() { 1 errors, 0 warnings """ ) - .expectFixDiffs( - """ - Fix for build.gradle line 5: Update targetSdkVersion to $HIGHEST_KNOWN_STABLE_API: - @@ -5 +5 - - targetSdkVersion 17 - + targetSdkVersion $HIGHEST_KNOWN_STABLE_API - """ - ) } finally { GradleDetector.calendar = null } @@ -4922,14 +4894,6 @@ class GradleDetectorTest : AbstractCheckTest() { 1 errors, 0 warnings """ ) - .expectFixDiffs( - """ - Fix for build.gradle line 5: Update targetSdkVersion to $HIGHEST_KNOWN_STABLE_API: - @@ -5 +5 - - targetSdkVersion 'O' - + targetSdkVersion $HIGHEST_KNOWN_STABLE_API - """ - ) } finally { GradleDetector.calendar = null } @@ -6047,6 +6011,109 @@ class GradleDetectorTest : AbstractCheckTest() { ) } + fun testBomWithoutPlatform() { + lint() + .files( + gradleToml( + """ + [versions] + composeBom = "2023.01.00" + [libraries] + compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } + """ + ) + .indented(), + gradle( + """ + plugins { + id 'com.android.application' + id 'kotlin-android' + } + dependencies { + implementation(libs.compose.bom) + testImplementation(libs.compose.bom) + testImplementation "androidx.compose:compose-bom:2023.01.00" + api("androidx.compose:compose-bom:2023.01.00") + } + """ + ) + .indented() + ) + .issues(BOM_WITHOUT_PLATFORM) + .run() + .expect( + """ + build.gradle:6: Warning: BOM should be added with a call to platform() [BomWithoutPlatform] + implementation(libs.compose.bom) + ~~~~~~~~~~~~~~~~ + build.gradle:7: Warning: BOM should be added with a call to platform() [BomWithoutPlatform] + testImplementation(libs.compose.bom) + ~~~~~~~~~~~~~~~~ + build.gradle:8: Warning: BOM should be added with a call to platform() [BomWithoutPlatform] + testImplementation "androidx.compose:compose-bom:2023.01.00" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + build.gradle:9: Warning: BOM should be added with a call to platform() [BomWithoutPlatform] + api("androidx.compose:compose-bom:2023.01.00") + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 4 warnings + """ + ) + .expectFixDiffs( + """ + Fix for build.gradle line 6: Add platform() to BOM declaration: + @@ -6 +6 + - implementation(libs.compose.bom) + + implementation(platform(libs.compose.bom)) + Fix for build.gradle line 7: Add platform() to BOM declaration: + @@ -7 +7 + - testImplementation(libs.compose.bom) + + testImplementation(platform(libs.compose.bom)) + Fix for build.gradle line 8: Add platform() to BOM declaration: + @@ -8 +8 + - testImplementation "androidx.compose:compose-bom:2023.01.00" + + testImplementation platform("androidx.compose:compose-bom:2023.01.00") + Fix for build.gradle line 9: Add platform() to BOM declaration: + @@ -9 +9 + - api("androidx.compose:compose-bom:2023.01.00") + + api(platform("androidx.compose:compose-bom:2023.01.00")) + """ + ) + } + + fun testBomWithoutPlatformClean() { + lint() + .files( + gradleToml( + """ + [versions] + composeBom = "2023.01.00" + [libraries] + compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } + """ + ) + .indented(), + gradle( + """ + plugins { + id 'com.android.application' + id 'kotlin-android' + } + dependencies { + def composeBom = platform(libs.compose.bom) + implementation(composeBom) + implementation(platform(libs.compose.bom)) + api(platform("androidx.compose:compose-bom:2023.01.00")) + testImplementation(platform("androidx.compose:compose-bom:2023.01.00")) + } + """ + ) + .indented() + ) + .issues(BOM_WITHOUT_PLATFORM) + .run() + .expectClean() + } + fun testJavaLanguageLevelClean() { val sourceCompatibility = listOf( @@ -6914,6 +6981,15 @@ class GradleDetectorTest : AbstractCheckTest() { .trimIndent() ) task.networkData( + "https://maven.google.com/androidx/compose/group-index.xml", + """ + <?xml version="1.0" encoding="UTF-8"?> + <androidx.compose> + <compose-bom versions="2022.10.00,2022.11.00,2022.12.00,2023.01.00"/> + </androidx.compose> + """ + ) + task.networkData( "https://maven.google.com/androidx/compose/foundation/group-index.xml", """ <?xml version="1.0" encoding="UTF-8"?> diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/ProviderPermissionDetectorTest.kt b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/ProviderPermissionDetectorTest.kt new file mode 100644 index 0000000000..fc62664700 --- /dev/null +++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/ProviderPermissionDetectorTest.kt @@ -0,0 +1,908 @@ +/* + * Copyright (C) 2022 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.tools.lint.checks + +import com.android.tools.lint.checks.infrastructure.TestFile +import com.android.tools.lint.detector.api.Detector + +class ProviderPermissionDetectorTest : AbstractCheckTest() { + override fun getDetector(): Detector = ProviderPermissionDetector() + + fun testDocumentationExample() { + lint() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + <provider android:name="test.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + <provider android:name="test.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + </application> + </manifest> + """ + ) + .indented(), + javaSingleApi, + kotlinSingleApi + ) + .run() + .expect( + """ + AndroidManifest.xml:5: Warning: test.pkg.JavaTestContentProvider implements {insert} write APIs but does not protect them with a permission. Update the <provider> tag to use android:permission or android:writePermission [ProviderReadPermissionOnly] + <provider android:name="test.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + ~~~~~~~~~~~~~~~~~~~~~~ + AndroidManifest.xml:6: Warning: test.pkg.KotlinTestContentProvider implements {insert} write APIs but does not protect them with a permission. Update the <provider> tag to use android:permission or android:writePermission [ProviderReadPermissionOnly] + <provider android:name="test.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + ~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 2 warnings + """ + ) + .expectFixDiffs( + """ + Fix for AndroidManifest.xml line 5: Replace with permission: + @@ -5 +5 + - <provider android:name="test.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + + <provider android:name="test.pkg.JavaTestContentProvider" android:permission="android.permission.READ_DATA"/> + Fix for AndroidManifest.xml line 6: Replace with permission: + @@ -6 +6 + - <provider android:name="test.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + + <provider android:name="test.pkg.KotlinTestContentProvider" android:permission="android.permission.READ_DATA"/> + """ + ) + } + + fun testReadPermissionOnly_singleApiImplemented_shortProviderNamesWithDot_throwsWarnings() { + lint() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + <provider android:name=".JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + <provider android:name=".KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + </application> + </manifest> + """ + ) + .indented(), + javaSingleApi, + kotlinSingleApi + ) + .run() + .expect( + """ + AndroidManifest.xml:5: Warning: test.pkg.JavaTestContentProvider implements {insert} write APIs but does not protect them with a permission. Update the <provider> tag to use android:permission or android:writePermission [ProviderReadPermissionOnly] + <provider android:name=".JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + ~~~~~~~~~~~~~~~~~~~~~~ + AndroidManifest.xml:6: Warning: test.pkg.KotlinTestContentProvider implements {insert} write APIs but does not protect them with a permission. Update the <provider> tag to use android:permission or android:writePermission [ProviderReadPermissionOnly] + <provider android:name=".KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + ~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 2 warnings + """ + ) + .expectFixDiffs( + """ + Fix for AndroidManifest.xml line 5: Replace with permission: + @@ -5 +5 + - <provider android:name=".JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + + <provider android:name=".JavaTestContentProvider" android:permission="android.permission.READ_DATA"/> + Fix for AndroidManifest.xml line 6: Replace with permission: + @@ -6 +6 + - <provider android:name=".KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + + <provider android:name=".KotlinTestContentProvider" android:permission="android.permission.READ_DATA"/> + """ + ) + } + + fun testReadPermissionOnly_someWriteApisImplemented_throwsWarnings() { + lint() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + <provider android:name="test.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + <provider android:name="test.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + </application> + </manifest> + """ + ) + .indented(), + javaSomeApis, + kotlinSomeApis + ) + .run() + .expect( + """ + AndroidManifest.xml:5: Warning: test.pkg.JavaTestContentProvider implements {insert, delete} write APIs but does not protect them with a permission. Update the <provider> tag to use android:permission or android:writePermission [ProviderReadPermissionOnly] + <provider android:name="test.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + ~~~~~~~~~~~~~~~~~~~~~~ + AndroidManifest.xml:6: Warning: test.pkg.KotlinTestContentProvider implements {insert, delete} write APIs but does not protect them with a permission. Update the <provider> tag to use android:permission or android:writePermission [ProviderReadPermissionOnly] + <provider android:name="test.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + ~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 2 warnings + """ + ) + .expectFixDiffs( + """ + Fix for AndroidManifest.xml line 5: Replace with permission: + @@ -5 +5 + - <provider android:name="test.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + + <provider android:name="test.pkg.JavaTestContentProvider" android:permission="android.permission.READ_DATA"/> + Fix for AndroidManifest.xml line 6: Replace with permission: + @@ -6 +6 + - <provider android:name="test.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + + <provider android:name="test.pkg.KotlinTestContentProvider" android:permission="android.permission.READ_DATA"/> + """ + ) + } + + fun testReadPermissionOnly_noWriteApisImplemented_isClean() { + lint() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + <provider android:name="test.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + <provider android:name="test.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + <provider android:name="test.pkg.KotlinWithThrowsTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + </application> + </manifest> + """ + ) + .indented(), + javaNoApis, + kotlinNoApis, + kotlinNoApisWithThrows + ) + .run() + .expectClean() + } + + fun testPermissionExists_someWriteApisImplemented_isClean() { + lint() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + <provider android:name="test.pkg.JavaTestContentProvider" android:permission="android.permission.READ_DATA"/> + <provider android:name="test.pkg.KotlinTestContentProvider" android:permission="android.permission.READ_DATA"/> + </application> + </manifest> + """ + ) + .indented(), + javaSomeApis, + kotlinSomeApis + ) + .run() + .expectClean() + } + + fun testWritePermissionExists_someWriteApisImplemented_isClean() { + lint() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + <provider android:name="test.pkg.JavaTestContentProvider" android:writePermission="android.permission.READ_DATA"/> + <provider android:name="test.pkg.KotlinTestContentProvider" android:writePermission="android.permission.READ_DATA"/> + </application> + </manifest> + """ + ) + .indented(), + javaSomeApis, + kotlinSomeApis + ) + .run() + .expectClean() + } + + fun testIsolatedClass_ReadPermissionOnly_singleWriteApiImplemented_throwsWarningInClass() { + lint() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + <provider android:name=".JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + <provider android:name=".KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + </application> + </manifest> + """ + ) + .indented(), + javaSingleApi + ) + .isolated(javaSingleApiPath) + .run() + .expect( + """ + src/test/pkg/JavaTestContentProvider.java:7: Warning: test.pkg.JavaTestContentProvider implements {insert} write APIs but does not protect them with a permission. Update the <provider> tag to use android:permission or android:writePermission [ProviderReadPermissionOnly] + public class JavaTestContentProvider extends ContentProvider { + ~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """ + ) + .expectFixDiffs( + """ + Fix for src/test/pkg/JavaTestContentProvider.java line 7: Replace with permission: + AndroidManifest.xml: + @@ -5 +5 + - <provider android:name=".JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + + <provider android:name=".JavaTestContentProvider" android:permission="android.permission.READ_DATA"/> + """ + ) + } + fun testIsolatedLibraryClass_ReadPermissionOnly_singleWriteApiImplemented_throwsWarningInLibraryClass() { + val project1 = + project() + .files( + javaSingleApiJvModule, + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.jv.pkg"> + <application> + <provider android:name=".JavaTestContentProvider" android:readPermission="android.permission.READ_DATA" /> + </application> + </manifest> + """ + ) + .indented() + ) + + val project2 = + project() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + </application> + </manifest> + """ + ) + .indented() + ) + .dependsOn(project1) + + lint() + .projects(project1, project2) + .isolated("../lib/src/test/jv/pkg/JavaTestContentProvider.java") + .run() + .expect( + """ + ../lib/src/test/jv/pkg/JavaTestContentProvider.java:7: Warning: test.jv.pkg.JavaTestContentProvider implements {insert} write APIs but does not protect them with a permission. Update the <provider> tag to use android:permission or android:writePermission [ProviderReadPermissionOnly] + public class JavaTestContentProvider extends ContentProvider { + ~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """ + ) + .expectFixDiffs( + """ + Fix for ../lib/src/test/jv/pkg/JavaTestContentProvider.java line 7: Replace with permission: + AndroidManifest.xml: + @@ -5 +5 + - <provider android:name=".JavaTestContentProvider" android:readPermission="android.permission.READ_DATA" /> + + <provider android:name=".JavaTestContentProvider" android:permission="android.permission.READ_DATA" /> + """ + ) + } + + fun testIsolatedManifest_ReadPermissionOnly_singleWriteApiImplemented_isClean() { + lint() + .files( + manifest( + "AndroidManifest.xml", + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + <provider android:name=".JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + <provider android:name=".KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + </application> + </manifest> + """ + ) + .indented(), + javaSingleApi + ) + .isolated("AndroidManifest.xml") + .run() + .expectClean() + } + + fun testSuppressed_ReadPermissionOnly_someWriteApisImplemented_isClean() { + lint() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + <provider android:name="test.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA" tools:ignore="ProviderReadPermissionOnly"/> + <provider android:name="test.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA" tools:ignore="ProviderReadPermissionOnly"/> + </application> + </manifest> + """ + ) + .indented(), + javaSomeApis, + kotlinSomeApis + ) + .run() + .expectClean() + } + + fun testClassesInDifferentModules_ReadPermissionOnly_singleApiImplemented_throwsWarnings() { + val project1 = project().files(javaSingleApiJvModule) + + val project2 = project().files(kotlinSingleApiKtModule) + + val project3 = + project() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + <provider android:name="test.jv.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + <provider android:name="test.kt.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + </application> + </manifest> + """ + ) + .indented(), + ) + .dependsOn(project1) + .dependsOn(project2) + + lint() + .projects(project1, project2, project3) + .run() + .expect( + """ + AndroidManifest.xml:5: Warning: test.jv.pkg.JavaTestContentProvider implements {insert} write APIs but does not protect them with a permission. Update the <provider> tag to use android:permission or android:writePermission [ProviderReadPermissionOnly] + <provider android:name="test.jv.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + ~~~~~~~~~~~~~~~~~~~~~~ + AndroidManifest.xml:6: Warning: test.kt.pkg.KotlinTestContentProvider implements {insert} write APIs but does not protect them with a permission. Update the <provider> tag to use android:permission or android:writePermission [ProviderReadPermissionOnly] + <provider android:name="test.kt.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + ~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 2 warnings + """ + ) + .expectFixDiffs( + """ + Fix for AndroidManifest.xml line 5: Replace with permission: + @@ -5 +5 + - <provider android:name="test.jv.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + + <provider android:name="test.jv.pkg.JavaTestContentProvider" android:permission="android.permission.READ_DATA"/> + Fix for AndroidManifest.xml line 6: Replace with permission: + @@ -6 +6 + - <provider android:name="test.kt.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + + <provider android:name="test.kt.pkg.KotlinTestContentProvider" android:permission="android.permission.READ_DATA"/> + """ + ) + } + + fun testClassesInDifferentModules_Suppressed_ReadPermissionOnly_singleApiImplemented_isClean() { + val project1 = project().files(javaSingleApiJvModule) + val project2 = project().files(kotlinSingleApiKtModule) + val project3 = + project() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + <provider android:name="test.jv.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA" tools:ignore="ProviderReadPermissionOnly"/> + <provider android:name="test.kt.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA" tools:ignore="ProviderReadPermissionOnly"/> + </application> + </manifest> + """ + ) + .indented(), + ) + .dependsOn(project1) + .dependsOn(project2) + + lint().projects(project1, project2, project3).run().expectClean() + } + + fun testHalfClassesInDifferentModulesReadPermissionOnly_singleApiImplemented_throwsWarnings() { + val project1 = project().files(javaSingleApiJvModule) + + val project2 = + project() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + <provider android:name="test.jv.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + <provider android:name=".KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + </application> + </manifest> + """ + ) + .indented(), + kotlinSingleApi + ) + .dependsOn(project1) + + lint() + .projects(project1, project2) + .run() + .expect( + """ + AndroidManifest.xml:5: Warning: test.jv.pkg.JavaTestContentProvider implements {insert} write APIs but does not protect them with a permission. Update the <provider> tag to use android:permission or android:writePermission [ProviderReadPermissionOnly] + <provider android:name="test.jv.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + ~~~~~~~~~~~~~~~~~~~~~~ + AndroidManifest.xml:6: Warning: test.pkg.KotlinTestContentProvider implements {insert} write APIs but does not protect them with a permission. Update the <provider> tag to use android:permission or android:writePermission [ProviderReadPermissionOnly] + <provider android:name=".KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + ~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 2 warnings + """ + ) + .expectFixDiffs( + """ + Fix for AndroidManifest.xml line 5: Replace with permission: + @@ -5 +5 + - <provider android:name="test.jv.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + + <provider android:name="test.jv.pkg.JavaTestContentProvider" android:permission="android.permission.READ_DATA"/> + Fix for AndroidManifest.xml line 6: Replace with permission: + @@ -6 +6 + - <provider android:name=".KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + + <provider android:name=".KotlinTestContentProvider" android:permission="android.permission.READ_DATA"/> + """ + ) + } + + fun testMainManifestOverridesDefinition_ReadPermissionOnly_mainDependentNoApisImplemented_librarySingleApiImplemented_isClean() { + val project1 = + project() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.jv.pkg"> + <application> + <provider android:name="test.kt.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + </application> + </manifest> + """ + ) + .indented(), + javaNoApisJvModule + ) + val project2 = project().files(kotlinSingleApiKtModule) + val project3 = + project() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + <provider android:name="test.jv.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + <provider android:name="test.kt.pkg.KotlinTestContentProvider" android:permission="android.permission.READ_DATA"/> + </application> + </manifest> + """ + ) + .indented(), + ) + .dependsOn(project1) + .dependsOn(project2) + + lint().projects(project1, project2, project3).run().expectClean() + } + + fun testDifferentModulesManifestsImpactMain_ReadPermissionOnly_mainDependentNoApisImplemented_librarySingleApiImplemented_throwsWarnings() { + val project1 = + project() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.jv.pkg"> + <application> + <provider android:name="test.kt.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + </application> + </manifest> + """ + ) + .indented(), + javaNoApisJvModule + ) + val project2 = project().files(kotlinSingleApiKtModule) + val project3 = + project() + .files( + manifest( + """ + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="test.pkg"> + <application> + <provider android:name="test.jv.pkg.JavaTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + </application> + </manifest> + """ + ) + .indented(), + ) + .dependsOn(project1) + .dependsOn(project2) + + lint() + .projects(project1, project2, project3) + .run() + .expect( + """ + ../lib/AndroidManifest.xml:5: Warning: test.kt.pkg.KotlinTestContentProvider implements {insert} write APIs but does not protect them with a permission. Update the <provider> tag to use android:permission or android:writePermission [ProviderReadPermissionOnly] + <provider android:name="test.kt.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + ~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """ + ) + .expectFixDiffs( + """ + Fix for lib/AndroidManifest.xml line 5: Replace with permission: + @@ -5 +5 + - <provider android:name="test.kt.pkg.KotlinTestContentProvider" android:readPermission="android.permission.READ_DATA"/> + + <provider android:name="test.kt.pkg.KotlinTestContentProvider" android:permission="android.permission.READ_DATA"/> + """ + ) + } + + private val javaSingleApiPath = "src/test/pkg/JavaTestContentProvider.java" + private val javaSingleApi: TestFile = + java( + javaSingleApiPath, + """ + package test.pkg; + + import android.content.ContentProvider; + import android.net.Uri; + import android.os.Bundle; + + public class JavaTestContentProvider extends ContentProvider { + @Override + public Uri insert(Uri uri, ContentValues values) { + return insert(uri, values, null); + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + throw new UnsupportedOperationException(""); + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + return 0; + } + + private Uri insert(Uri uri, ContentValues values, Bundle extras) { + System.out.println(uri); + } + } + """ + ) + .indented() + private val kotlinSingleApi: TestFile = + kotlin( + """ + package test.pkg + + import android.content.ContentProvider + import android.net.Uri + + class KotlinTestContentProvider : ContentProvider() { + override fun insert(uri: Uri, values: ContentValues?): Uri? = insert(uri, values, null) ?: null + + override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int { + throw UnsupportedOperationException() + } + + override fun update( + uri: Uri, + values: ContentValues?, + selection: String?, + selectionArgs: Array<String>? + ): Int = 0 + + private fun insert(uri: Uri, values: ContentValues?, extras: Bundle?): Int? { + println(uri) + return null + } + } + """ + ) + .indented() + private val javaSomeApis: TestFile = + java( + """ + package test.pkg; + + import android.content.ContentProvider; + import android.net.Uri; + import android.os.Bundle; + + public class JavaTestContentProvider extends ContentProvider { + @Override + public Uri insert(Uri uri, ContentValues values) { + return insert(uri, values, null); + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + foo(); + return 0; + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + return 0; + } + + private Uri insert(Uri uri, ContentValues values, Bundle extras) { + System.out.println(uri); + } + + private void foo() { + int a = 10; + } + } + """ + ) + .indented() + private val kotlinSomeApis: TestFile = + kotlin( + """ + package test.pkg + + import android.content.ContentProvider + import android.net.Uri + + class KotlinTestContentProvider : ContentProvider() { + override fun insert(uri: Uri, values: ContentValues?): Uri? = insert(uri, values, null) ?: null + + override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int { + foo() + return 0 + } + + override fun update( + uri: Uri, + values: ContentValues?, + selection: String?, + selectionArgs: Array<String>? + ): Int = 0 + + private fun insert(uri: Uri, values: ContentValues?, extras: Bundle?): Int? { + println(uri) + return null + } + + private fun foo() { + val a = 10 + } + } + """ + ) + .indented() + private val javaNoApis: TestFile = + java( + """ + package test.pkg; + + import android.content.ContentProvider; + import android.net.Uri; + import android.os.Bundle; + + public class JavaTestContentProvider extends ContentProvider { + @Override + public Uri insert(Uri uri, ContentValues values) { + throw new UnsupportedOperationException(); + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + return 0; + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + return 0; + } + } + """ + ) + .indented() + private val kotlinNoApis = + kotlin( + """ + package test.pkg + + import android.content.ContentProvider + import android.net.Uri + + class KotlinTestContentProvider : ContentProvider() { + override fun insert(uri: Uri, values: ContentValues?): Uri? = throw UnsupportedOperationException() + + override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int { + return 0 + } + + override fun update( + uri: Uri, + values: ContentValues?, + selection: String?, + selectionArgs: Array<String>? + ): Int = 0 + } + """ + ) + .indented() + private val kotlinNoApisWithThrows = + kotlin( + """ + package test.pkg + + import android.content.ContentProvider + import android.net.Uri + + class KotlinWithThrowsTestContentProvider : ContentProvider() { + override fun insert(uri: Uri, values: ContentValues?): Uri? = throw NotImplementedError() + + override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int { + error("Not supported") + } + + override fun update( + uri: Uri, + values: ContentValues?, + selection: String?, + selectionArgs: Array<String>? + ): Int = TODO() + } + """ + ) + .indented() + private val javaSingleApiJvModule: TestFile = + java( + """ + package test.jv.pkg; + + import android.content.ContentProvider; + import android.net.Uri; + import android.os.Bundle; + + public class JavaTestContentProvider extends ContentProvider { + @Override + public Uri insert(Uri uri, ContentValues values) { + return insert(uri, values, null); + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + throw new UnsupportedOperationException(""); + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + return 0; + } + + private Uri insert(Uri uri, ContentValues values, Bundle extras) { + System.out.println(uri); + } + } + """ + ) + .indented() + private val kotlinSingleApiKtModule: TestFile = + kotlin( + """ + package test.kt.pkg + + import android.content.ContentProvider + import android.net.Uri + + class KotlinTestContentProvider : ContentProvider() { + override fun insert(uri: Uri, values: ContentValues?): Uri? = insert(uri, values, null) + + override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int { + throw UnsupportedOperationException() + } + + override fun update( + uri: Uri, + values: ContentValues?, + selection: String?, + selectionArgs: Array<String>? + ): Int = 0 + + private fun insert(uri: Uri, values: ContentValues?, extras: Bundle?) { + println(uri) + } + } + """ + ) + .indented() + private val javaNoApisJvModule: TestFile = + java( + """ + package test.jv.pkg; + + import android.content.ContentProvider; + import android.net.Uri; + import android.os.Bundle; + + public class JavaTestContentProvider extends ContentProvider { + @Override + public Uri insert(Uri uri, ContentValues values) { + throw new UnsupportedOperationException(); + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + return 0; + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + return 0; + } + } + """ + ) + .indented() +} diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/RegisterReceiverFlagDetectorTest.kt b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/RegisterReceiverFlagDetectorTest.kt index e3ac2ed41e..50d9dabdf0 100644 --- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/RegisterReceiverFlagDetectorTest.kt +++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/RegisterReceiverFlagDetectorTest.kt @@ -100,38 +100,340 @@ class RegisterReceiverFlagDetectorTest : AbstractCheckTest() { .expectClean() } + fun testIntentFilterIsFieldWithProtectedActions() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + import android.content.IntentFilter; + public class TestClass1 { + private Context mContext; + private final IntentFilter myIntentFilter; + private TestClass1(Context context) { + mContext = context; + myIntentFilter = new IntentFilter(); + myIntentFilter.addAction(Intent.ACTION_BATTERY_LOW); + myIntentFilter.addAction(Intent.ACTION_BATTERY_OKAY); + } + public void testMethod(BroadcastReceiver receiver) { + mContext.registerReceiver(receiver, myIntentFilter); + } + } + """ + ) + ) + .run() + .expectClean() + } + + fun testIntentFilterIsFieldWithProtectedActions_multipleRegisterCalls() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + import android.content.IntentFilter; + public class TestClass1 { + private Context mContext; + private IntentFilter myIntentFilter; + private TestClass1(Context context) { + mContext = context; + myIntentFilter = new IntentFilter(); + myIntentFilter.addAction(Intent.ACTION_BATTERY_LOW); + myIntentFilter.addAction(Intent.ACTION_BATTERY_OKAY); + } + public void testMethod(BroadcastReceiver receiver) { + mContext.registerReceiver(receiver, myIntentFilter); + } + public void testMethodTwo(BroadcastReceiver receiver) { + mContext.registerReceiver(receiver, myIntentFilter); + } + } + """ + ) + ) + .run() + .expectClean() + } + + fun testIntentFilterIsFieldWithProtectedActions_nonPrivate() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + import android.content.IntentFilter; + public class TestClass1 { + private Context mContext; + IntentFilter myIntentFilter; + private TestClass1(Context context) { + mContext = context; + myIntentFilter = new IntentFilter(); + myIntentFilter.addAction(Intent.ACTION_BATTERY_LOW); + myIntentFilter.addAction(Intent.ACTION_BATTERY_OKAY); + } + public void testMethod(BroadcastReceiver receiver) { + mContext.registerReceiver(receiver, myIntentFilter); + } + } + """ + ), + ) + .run() + .expect( + """ + src/test/pkg/TestClass1.java:17: Warning: receiver is missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag for unprotected broadcasts registered for an IntentFilter that cannot be inspected by lint [UnspecifiedRegisterReceiverFlag] + mContext.registerReceiver(receiver, myIntentFilter); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """ + ) + } + + fun testIntentFilterIsFieldWithProtectedActions_escapesScope() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + import android.content.IntentFilter; + public class TestClass1 { + private Context mContext; + private IntentFilter myIntentFilter; + private TestClass1(Context context) { + mContext = context; + myIntentFilter = new IntentFilter(); + myIntentFilter.addAction(Intent.ACTION_BATTERY_LOW); + myIntentFilter.addAction(Intent.ACTION_BATTERY_OKAY); + } + public void testMethod(BroadcastReceiver receiver) { + mContext.registerReceiver(receiver, myIntentFilter); + } + public void escape() { + UtilClass.utilMethod(myIntentFilter); + } + } + """ + ), + java( + """ + package test.pkg; + import android.content.IntentFilter; + public class UtilClass { + public void utilMethod(IntentFilter filter) {} + } + """ + ) + ) + .run() + .expect( + """ + src/test/pkg/TestClass1.java:17: Warning: receiver is missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag for unprotected broadcasts registered for an IntentFilter that cannot be inspected by lint [UnspecifiedRegisterReceiverFlag] + mContext.registerReceiver(receiver, myIntentFilter); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """ + ) + } + + fun testIntentFilterIsFieldWithProtectedActions_escapesScopeViaPublicGetter() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + import android.content.IntentFilter; + public class TestClass1 { + private Context mContext; + private IntentFilter myIntentFilter; + private TestClass1(Context context) { + mContext = context; + myIntentFilter = new IntentFilter(); + myIntentFilter.addAction(Intent.ACTION_BATTERY_LOW); + myIntentFilter.addAction(Intent.ACTION_BATTERY_OKAY); + } + public void testMethod(BroadcastReceiver receiver) { + mContext.registerReceiver(receiver, myIntentFilter); + } + public IntentFilter getIntentFilter() { + return myIntentFilter; + } + } + """ + ), + ) + .run() + .expect( + """ + src/test/pkg/TestClass1.java:17: Warning: receiver is missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag for unprotected broadcasts registered for an IntentFilter that cannot be inspected by lint [UnspecifiedRegisterReceiverFlag] + mContext.registerReceiver(receiver, myIntentFilter); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """ + ) + } + + fun testIntentFilterIsFieldWithProtectedActions_escapesScopeViaPublicSetter() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + import android.content.IntentFilter; + public class TestClass1 { + private Context mContext; + private IntentFilter myIntentFilter; + private TestClass1(Context context) { + mContext = context; + myIntentFilter = new IntentFilter(); + myIntentFilter.addAction(Intent.ACTION_BATTERY_LOW); + myIntentFilter.addAction(Intent.ACTION_BATTERY_OKAY); + } + public void testMethod(BroadcastReceiver receiver) { + mContext.registerReceiver(receiver, myIntentFilter); + } + public void setMyIntentFilter(IntentFilter intentFilter) { + myIntentFilter = intentFilter; + } + } + """ + ), + ) + .run() + .expect( + """ + src/test/pkg/TestClass1.java:17: Warning: receiver is missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag for unprotected broadcasts registered for an IntentFilter that cannot be inspected by lint [UnspecifiedRegisterReceiverFlag] + mContext.registerReceiver(receiver, myIntentFilter); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """ + ) + } + + fun testIntentFilterIsFieldWithUnprotectedActions() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + import android.content.IntentFilter; + public class TestClass1 { + private Context mContext; + private IntentFilter myIntentFilter; + private TestClass1(Context context) { + mContext = context; + myIntentFilter = new IntentFilter("foo"); + myIntentFilter.addAction("bar"); + } + public void testMethod(BroadcastReceiver receiver) { + mContext.registerReceiver(receiver, myIntentFilter); + } + public void randomMethod() { + myIntentFilter.addAction("baz"); + } + } + """ + ) + ) + .run() + .expect( + """ + src/test/pkg/TestClass1.java:16: Warning: receiver is missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag for unprotected broadcasts registered for foo, bar, baz [UnspecifiedRegisterReceiverFlag] + mContext.registerReceiver(receiver, myIntentFilter); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """ + ) + } + + fun testIntentFilterIsFieldWithUnprotectedActions_constructedInline() { + lint() + .files( + java( + """ + package test.pkg; + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + import android.content.IntentFilter; + public class TestClass1 { + private Context mContext; + private IntentFilter myIntentFilter = new IntentFilter("foo"); + private TestClass1(Context context) { + mContext = context; + myIntentFilter.addAction("bar"); + } + public void testMethod(BroadcastReceiver receiver) { + mContext.registerReceiver(receiver, myIntentFilter); + } + } + """ + ), + ) + .run() + .expect( + """ + src/test/pkg/TestClass1.java:15: Warning: receiver is missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag for unprotected broadcasts registered for foo, bar [UnspecifiedRegisterReceiverFlag] + mContext.registerReceiver(receiver, myIntentFilter); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """ + ) + } + fun testSubsequentFilterModification() { lint() .files( java( - """ - package test.pkg; - import android.content.BroadcastReceiver; - import android.content.Context; - import android.content.Intent; - import android.content.IntentFilter; - public class TestClass1 { - public void testMethod(Context context, BroadcastReceiver receiver) { - IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); - filter.addAction(Intent.ACTION_BATTERY_LOW); - filter.addAction(Intent.ACTION_BATTERY_OKAY); - context.registerReceiver(receiver, filter); - filter.addAction("querty"); - context.registerReceiver(receiver, filter); - } - } - """ - ) - .indented(), + """ + package test.pkg; + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + import android.content.IntentFilter; + public class TestClass1 { + public void testMethod(Context context, BroadcastReceiver receiver) { + IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); + filter.addAction(Intent.ACTION_BATTERY_LOW); + filter.addAction(Intent.ACTION_BATTERY_OKAY); + context.registerReceiver(receiver, filter); + filter.addAction("querty"); + context.registerReceiver(receiver, filter); + } + } + """ + ) ) .run() .expect( """ - src/test/pkg/TestClass1.java:13: Warning: receiver is missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag for unprotected broadcasts registered for querty [UnspecifiedRegisterReceiverFlag] - context.registerReceiver(receiver, filter); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 0 errors, 1 warnings - """ + src/test/pkg/TestClass1.java:14: Warning: receiver is missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag for unprotected broadcasts registered for querty [UnspecifiedRegisterReceiverFlag] + context.registerReceiver(receiver, filter); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """ ) } diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/UnsafeIntentLaunchDetectorTest.kt b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/UnsafeIntentLaunchDetectorTest.kt index 7542071f46..1154d81a04 100644 --- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/UnsafeIntentLaunchDetectorTest.kt +++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/UnsafeIntentLaunchDetectorTest.kt @@ -16,6 +16,7 @@ package com.android.tools.lint.checks import com.android.tools.lint.checks.infrastructure.TestFile +import com.android.tools.lint.checks.infrastructure.TestMode import com.android.tools.lint.detector.api.Detector class UnsafeIntentLaunchDetectorTest : AbstractCheckTest() { @@ -832,7 +833,7 @@ class UnsafeIntentLaunchDetectorTest : AbstractCheckTest() { .indented(), *stubs ) - .issues(UnsafeIntentLaunchDetector.ISSUE) /*.testModes(TestMode.DEFAULT)*/ + .issues(UnsafeIntentLaunchDetector.ISSUE) .run() .expect( """ @@ -908,6 +909,7 @@ class UnsafeIntentLaunchDetectorTest : AbstractCheckTest() { *stubs ) .issues(UnsafeIntentLaunchDetector.ISSUE) + .testModes(TestMode.PARTIAL) .run() .expect( """ @@ -1024,6 +1026,7 @@ class UnsafeIntentLaunchDetectorTest : AbstractCheckTest() { *stubs ) .issues(UnsafeIntentLaunchDetector.ISSUE) + .testModes(TestMode.PARTIAL) .run() .expect( """ @@ -1050,9 +1053,7 @@ class UnsafeIntentLaunchDetectorTest : AbstractCheckTest() { import android.content.Intent; import android.app.Activity; - public class AnonymousBroadcastReceiverTest { - private Activity activity; - + public class AnonymousBroadcastReceiverTest extends Activity { public void onCreate(@NonNull LifecycleOwner lifecycleOwner) { BroadcastReceiver receiver = new BroadcastReceiver() { @Override @@ -1066,7 +1067,7 @@ class UnsafeIntentLaunchDetectorTest : AbstractCheckTest() { } }; - activity.registerReceiver(receiver, new IntentFilter("INTENT_ACTION_INSTALL_COMMIT")); + registerReceiver(receiver, new IntentFilter("INTENT_ACTION_INSTALL_COMMIT")); } public static <T> T checkNotNull(T reference) { @@ -1085,10 +1086,10 @@ class UnsafeIntentLaunchDetectorTest : AbstractCheckTest() { .run() .expect( """ - src/test/pkg/AnonymousBroadcastReceiverTest.java:17: Warning: This intent could be coming from an untrusted source. It is later launched by an unprotected component. You could either make the component protected; or sanitize this intent using androidx.core.content.IntentSanitizer. [UnsafeIntentLaunch] + src/test/pkg/AnonymousBroadcastReceiverTest.java:15: Warning: This intent could be coming from an untrusted source. It is later launched by an unprotected component. You could either make the component protected; or sanitize this intent using androidx.core.content.IntentSanitizer. [UnsafeIntentLaunch] context.startActivity(checkNotNull(intent.getParcelableExtra(Intent.EXTRA_INTENT))); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - src/test/pkg/AnonymousBroadcastReceiverTest.java:17: The unsafe intent is launched here. + src/test/pkg/AnonymousBroadcastReceiverTest.java:15: The unsafe intent is launched here. context.startActivity(checkNotNull(intent.getParcelableExtra(Intent.EXTRA_INTENT))); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0 errors, 1 warnings @@ -1430,6 +1431,308 @@ class UnsafeIntentLaunchDetectorTest : AbstractCheckTest() { ) } + fun testRuntimeExportedBroadcastReceiverLaunchWithProtectedBroadcast() { + lint() + .files( + java( + """ + package test.pkg; + + import android.app.Activity; + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + import android.content.IntentFilter; + + public class TestActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + // actual IntentFilter action is not looked at. + IntentFilter filter = new IntentFilter("qwerty"); + TestReceiver receiver = new TestReceiver(); + registerReceiver(receiver, filter, Context.RECEIVER_EXPORTED); + registerReceiver(new TestReceiver2(), filter, Context.RECEIVER_EXPORTED); + registerReceiver(new TestReceiver3(), filter, Context.RECEIVER_EXPORTED); + registerReceiver(new TestReceiver4(), filter, Context.RECEIVER_EXPORTED); + } + } + """ + ) + .indented(), + java( + """ + package test.pkg; + + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + + public class TestReceiver extends BroadcastReceiver { + private static final String testProtectedBroadcast = "android.accounts.action.ACCOUNT_REMOVED"; + private static final String testUnProtectedBroadcast = "com.example.UNPROTECTED_ACTION"; + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action != null) { + if (action.equals(testProtectedBroadcast)) { + peekService(context, intent); // OK + // only the broadcast intent is protected. This extra intent is not. + context.startActivity(intent.getParcelableExtra(Intent.EXTRA_INTENT)); // ERROR 2 + } else { + context.startService(intent); // ERROR 1 + } + } + } + } + """ + ) + .indented(), + java( + """ + package test.pkg; + + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + + public class TestReceiver2 extends BroadcastReceiver { + private static final String testProtectedBroadcast = "android.accounts.action.ACCOUNT_REMOVED"; + private static final String testUnProtectedBroadcast = "com.example.UNPROTECTED_ACTION"; + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action != null) { + if (action.equals(testProtectedBroadcast)) { + peekService(context, intent); // OK + } else if (testUnProtectedBroadcast.equals(action)) { + context.startService(intent); // ERROR 3 + } + } + } + } + """ + ) + .indented(), + java( + """ + package test.pkg; + + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + + public class TestReceiver3 extends BroadcastReceiver { + private static final String testProtectedBroadcast = "android.accounts.action.ACCOUNT_REMOVED"; + private static final String testUnProtectedBroadcast = "com.example.UNPROTECTED_ACTION"; + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action != null) { + switch (action) { + case testProtectedBroadcast -> context.startService(intent); // OK + case testUnProtectedBroadcast -> context.startService(intent); // ERROR 4 + default -> context.startActivity(intent.getParcelableExtra(Intent.EXTRA_INTENT)); // ERROR 5 + } + } + } + } + """ + ) + .indented(), + java( + """ + package test.pkg; + + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + + public class TestReceiver4 extends BroadcastReceiver { + private static final String testProtectedBroadcast = "android.accounts.action.ACCOUNT_REMOVED"; + private static final String testUnProtectedBroadcast = "com.example.UNPROTECTED_ACTION"; + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action != null) { + switch (action) { + case testProtectedBroadcast -> context.startService(intent); // OK + default -> peekService(context, intent); // ERROR 6 + } + } + } + } + """ + ) + .indented(), + *stubs + ) + .issues(UnsafeIntentLaunchDetector.ISSUE) + .testModes(TestMode.PARTIAL) + .run() + .expect( + """ + src/test/pkg/TestReceiver.java:12: Warning: This intent could be coming from an untrusted source. It is later launched by an unprotected component test.pkg.TestReceiver. You could either make the component test.pkg.TestReceiver protected; or sanitize this intent using androidx.core.content.IntentSanitizer. [UnsafeIntentLaunch] + public void onReceive(Context context, Intent intent) { + ~~~~~~~~~~~~~ + src/test/pkg/TestReceiver.java:20: The unsafe intent is launched here. + context.startService(intent); // ERROR 1 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + src/test/pkg/TestReceiver.java:18: Warning: This intent could be coming from an untrusted source. It is later launched by an unprotected component test.pkg.TestReceiver. You could either make the component test.pkg.TestReceiver protected; or sanitize this intent using androidx.core.content.IntentSanitizer. [UnsafeIntentLaunch] + context.startActivity(intent.getParcelableExtra(Intent.EXTRA_INTENT)); // ERROR 2 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + src/test/pkg/TestReceiver.java:18: The unsafe intent is launched here. + context.startActivity(intent.getParcelableExtra(Intent.EXTRA_INTENT)); // ERROR 2 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + src/test/pkg/TestReceiver2.java:12: Warning: This intent could be coming from an untrusted source. It is later launched by an unprotected component test.pkg.TestReceiver2. You could either make the component test.pkg.TestReceiver2 protected; or sanitize this intent using androidx.core.content.IntentSanitizer. [UnsafeIntentLaunch] + public void onReceive(Context context, Intent intent) { + ~~~~~~~~~~~~~ + src/test/pkg/TestReceiver2.java:18: The unsafe intent is launched here. + context.startService(intent); // ERROR 3 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + src/test/pkg/TestReceiver3.java:12: Warning: This intent could be coming from an untrusted source. It is later launched by an unprotected component test.pkg.TestReceiver3. You could either make the component test.pkg.TestReceiver3 protected; or sanitize this intent using androidx.core.content.IntentSanitizer. [UnsafeIntentLaunch] + public void onReceive(Context context, Intent intent) { + ~~~~~~~~~~~~~ + src/test/pkg/TestReceiver3.java:17: The unsafe intent is launched here. + case testUnProtectedBroadcast -> context.startService(intent); // ERROR 4 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + src/test/pkg/TestReceiver3.java:18: Warning: This intent could be coming from an untrusted source. It is later launched by an unprotected component test.pkg.TestReceiver3. You could either make the component test.pkg.TestReceiver3 protected; or sanitize this intent using androidx.core.content.IntentSanitizer. [UnsafeIntentLaunch] + default -> context.startActivity(intent.getParcelableExtra(Intent.EXTRA_INTENT)); // ERROR 5 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + src/test/pkg/TestReceiver3.java:18: The unsafe intent is launched here. + default -> context.startActivity(intent.getParcelableExtra(Intent.EXTRA_INTENT)); // ERROR 5 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + src/test/pkg/TestReceiver4.java:12: Warning: This intent could be coming from an untrusted source. It is later launched by an unprotected component test.pkg.TestReceiver4. You could either make the component test.pkg.TestReceiver4 protected; or sanitize this intent using androidx.core.content.IntentSanitizer. [UnsafeIntentLaunch] + public void onReceive(Context context, Intent intent) { + ~~~~~~~~~~~~~ + src/test/pkg/TestReceiver4.java:17: The unsafe intent is launched here. + default -> peekService(context, intent); // ERROR 6 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 6 warnings + """ + ) + } + + fun testRuntimeExportedBroadcastReceiverLaunchWithProtectedBroadcastKotlin() { + lint() + .files( + kotlin( + """ + package test.pkg; + + import android.app.Activity; + import android.content.BroadcastReceiver; + import android.content.Context; + import android.content.Intent; + import android.content.IntentFilter; + + class TestActivity : Activity { + + override fun onCreate(savedInstanceState : Bundle) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + // actual IntentFilter action is not looked at. + val filter = IntentFilter("qwerty") + val receiver = TestReceiver() + registerReceiver(receiver, filter, Context.RECEIVER_EXPORTED) + registerReceiver(TestReceiver2(), filter, Context.RECEIVER_EXPORTED) + } + } + """ + ) + .indented(), + kotlin( + """ + package test.pkg + + import android.content.BroadcastReceiver + import android.content.Context + import android.content.Intent + + class TestReceiver : BroadcastReceiver { + private const val testProtectedBroadcast = "android.accounts.action.ACCOUNT_REMOVED" + private const val testUnProtectedBroadcast = "com.example.UNPROTECTED_ACTION" + + override fun onReceive(context : Context, intent : Intent) { + val action = intent.getAction() + if (action != null) { + if (action == testProtectedBroadcast) { + peekService(context, intent) // OK + // only the broadcast intent is protected. This extra intent is not. + context.startActivity(intent.getParcelableExtra(Intent.EXTRA_INTENT)) // ERROR 2 + } else { + context.startService(intent) // ERROR 1 + } + } + } + } + """ + ) + .indented(), + kotlin( + """ + package test.pkg + + import android.content.BroadcastReceiver + import android.content.Context + import android.content.Intent + + class TestReceiver2 : BroadcastReceiver { + private const val testProtectedBroadcast = "android.accounts.action.ACCOUNT_REMOVED" + private const val testUnProtectedBroadcast = "com.example.UNPROTECTED_ACTION" + + @Override + override fun onReceive(context : Context, intent : Intent) { + val action = intent.getAction() + if (action != null) { + if (action == testProtectedBroadcast) { + peekService(context, intent) // OK + } else if (testUnProtectedBroadcast == action) { + context.startService(intent) // ERROR 3 + } + } + } + } + """ + ) + .indented(), + *stubs + ) + .issues(UnsafeIntentLaunchDetector.ISSUE) + .skipTestModes(TestMode.SUPPRESSIBLE) + .testModes(TestMode.PARTIAL) + .run() + .expect( + """ + src/test/pkg/TestReceiver.kt:11: Warning: This intent could be coming from an untrusted source. It is later launched by an unprotected component test.pkg.TestReceiver. You could either make the component test.pkg.TestReceiver protected; or sanitize this intent using androidx.core.content.IntentSanitizer. [UnsafeIntentLaunch] + override fun onReceive(context : Context, intent : Intent) { + ~~~~~~~~~~~~~~~ + src/test/pkg/TestReceiver.kt:19: The unsafe intent is launched here. + context.startService(intent) // ERROR 1 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + src/test/pkg/TestReceiver.kt:17: Warning: This intent could be coming from an untrusted source. It is later launched by an unprotected component test.pkg.TestReceiver. You could either make the component test.pkg.TestReceiver protected; or sanitize this intent using androidx.core.content.IntentSanitizer. [UnsafeIntentLaunch] + context.startActivity(intent.getParcelableExtra(Intent.EXTRA_INTENT)) // ERROR 2 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + src/test/pkg/TestReceiver.kt:17: The unsafe intent is launched here. + context.startActivity(intent.getParcelableExtra(Intent.EXTRA_INTENT)) // ERROR 2 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + src/test/pkg/TestReceiver2.kt:12: Warning: This intent could be coming from an untrusted source. It is later launched by an unprotected component test.pkg.TestReceiver2. You could either make the component test.pkg.TestReceiver2 protected; or sanitize this intent using androidx.core.content.IntentSanitizer. [UnsafeIntentLaunch] + override fun onReceive(context : Context, intent : Intent) { + ~~~~~~~~~~~~~~~ + src/test/pkg/TestReceiver2.kt:18: The unsafe intent is launched here. + context.startService(intent) // ERROR 3 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 3 warnings + """ + ) + } + private val intentStub: TestFile = java( """ @@ -1446,6 +1749,7 @@ class UnsafeIntentLaunchDetectorTest : AbstractCheckTest() { public String getStringExtra(String key) { return null; } public Bundle getExtras() { return new Bundle(); } public Intent setAction(String action) { return this; } + public String getAction() { return null; } public static Intent parseUri(String uri, int flags) { return null; } } """ diff --git a/previewlib/cli/BUILD b/previewlib/cli/BUILD index 2097aed0bb..ad5deec076 100644 --- a/previewlib/cli/BUILD +++ b/previewlib/cli/BUILD @@ -7,5 +7,10 @@ iml_module( srcs = ["src/main/java"], iml_files = ["android.sdktools.screenshot.cli.iml"], visibility = ["//visibility:public"], - deps = ["//prebuilts/studio/intellij-sdk:studio-sdk"], + # do not sort: must match IML order + deps = [ + "//prebuilts/studio/intellij-sdk:studio-sdk", + "//tools/base/lint:studio.android.sdktools.lint-api[module]", + "//tools/base/lint/cli:studio.android.sdktools.lint.cli[module]", + ], ) diff --git a/previewlib/cli/android.sdktools.screenshot.cli.iml b/previewlib/cli/android.sdktools.screenshot.cli.iml index d541505dc5..9500e06fcc 100644 --- a/previewlib/cli/android.sdktools.screenshot.cli.iml +++ b/previewlib/cli/android.sdktools.screenshot.cli.iml @@ -8,5 +8,7 @@ <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="inheritedJdk" /> <orderEntry type="library" name="studio-sdk" level="project" /> + <orderEntry type="module" module-name="android.sdktools.lint-api" /> + <orderEntry type="module" module-name="android.sdktools.lint.cli" /> </component> -</module> +</module>
\ No newline at end of file diff --git a/previewlib/cli/src/main/java/com/android/screenshot/cli/Main.kt b/previewlib/cli/src/main/java/com/android/screenshot/cli/Main.kt index 4e653ffd9b..46ae8248db 100644 --- a/previewlib/cli/src/main/java/com/android/screenshot/cli/Main.kt +++ b/previewlib/cli/src/main/java/com/android/screenshot/cli/Main.kt @@ -15,11 +15,774 @@ */ package com.android.screenshot.cli +import com.android.SdkConstants +import com.android.annotations.NonNull +import com.android.annotations.Nullable +import com.android.tools.lint.CliConfiguration +import com.android.tools.lint.LintCliClient +import com.android.tools.lint.LintCliFlags +import com.android.tools.lint.LintCliFlags.ERRNO_ERRORS +import com.android.tools.lint.LintCliFlags.ERRNO_INVALID_ARGS +import com.android.tools.lint.ProjectMetadata +import com.android.tools.lint.UastEnvironment +import com.android.tools.lint.client.api.Configuration +import com.android.tools.lint.client.api.ConfigurationHierarchy +import com.android.tools.lint.client.api.IssueRegistry +import com.android.tools.lint.client.api.LintClient +import com.android.tools.lint.client.api.LintClient.Companion.clientName +import com.android.tools.lint.client.api.LintDriver +import com.android.tools.lint.client.api.LintRequest +import com.android.tools.lint.client.api.LintXmlConfiguration.Companion.create +import com.android.tools.lint.client.api.Vendor +import com.android.tools.lint.computeMetadata +import com.android.tools.lint.detector.api.Context +import com.android.tools.lint.detector.api.Incident +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.LintModelModuleProject +import com.android.tools.lint.detector.api.LintModelModuleProject.Companion.resolveDependencies +import com.android.tools.lint.detector.api.Location +import com.android.tools.lint.detector.api.Location.Companion.create +import com.android.tools.lint.detector.api.Project +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import com.android.tools.lint.detector.api.guessGradleLocation +import com.android.tools.lint.detector.api.isJreFolder +import com.android.tools.lint.detector.api.splitPath +import com.android.tools.lint.model.LintModelModule +import com.android.tools.lint.model.LintModelSerialization +import com.android.tools.lint.model.LintModelSourceProvider +import com.android.tools.lint.model.LintModelVariant +import com.android.tools.lint.model.PathVariables +import com.android.utils.XmlUtils +import com.google.common.collect.Sets +import com.google.common.io.ByteStreams +import com.intellij.pom.java.LanguageLevel +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys +import org.jetbrains.kotlin.config.JVMConfigurationKeys +import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.w3c.dom.Document +import org.xml.sax.SAXException +import java.io.File +import java.io.IOException +import java.util.EnumSet +import java.util.zip.ZipEntry +import java.util.zip.ZipException +import java.util.zip.ZipFile + class Main { + + private val ARG_CLIENT_ID = "--client-id" + private val ARG_CLIENT_NAME = "--client-name" + private val ARG_CLIENT_VERSION = "--client-version" + private val ARG_SDK_HOME = "--sdk-home" + private val ARG_JDK_HOME = "--jdk-home" + private val ARG_LINT_MODEL = "--lint-model" + private val ARG_LINT_RULE_JARS = "--lint-rule-jars" + private val ARG_CACHE_DIR = "--cache-dir" + + private var sdkHomePath: File? = null + private var jdkHomePath: File? = null + + private val flags = LintCliFlags() companion object { @JvmStatic fun main(args: Array<String>) { + Main().run(args) + } + } + + fun run(args: Array<String>) { + val argumentState = ArgumentState() + val client: LintCliClient = MainLintClient(flags, argumentState) + parseArguments(args, client, argumentState) + initializePathVariables(argumentState, client) + initializeConfigurations(client, argumentState) + val projects: List<Project> = configureProject(client, argumentState) + val driver: LintDriver = createDriver(projects, client as MainLintClient) + initializeUast(projects) + } + + /** + * Configure project with idea project and configure CoreAppEnv + */ + private fun initializeUast(projects: Collection<Project>) { + // Initialize the associated idea project to use + val includeTests = !flags.isIgnoreTestSources + // `projects` only lists root projects, not dependencies + val allProjects = Sets.newIdentityHashSet<Project>() + for (project in projects) { + allProjects.add(project) + allProjects.addAll(project.allLibraries) + } + val sourceRoots: MutableSet<File> = LinkedHashSet(10) + val classpathRoots: MutableSet<File> = LinkedHashSet(50) + for (project in allProjects) { + // Note that there could be duplicates here since we're including multiple library + // dependencies that could have the same dependencies (e.g. lib1 and lib2 both + // referencing guava.jar) + sourceRoots.addAll(project.javaSourceFolders) + if (includeTests) { + sourceRoots.addAll(project.testSourceFolders) + } + sourceRoots.addAll(project.generatedSourceFolders) + classpathRoots.addAll(project.getJavaLibraries(true)) + if (includeTests) { + classpathRoots.addAll(project.testLibraries) + } + if (!flags.isIgnoreTestFixturesSources) { + sourceRoots.addAll(project.testFixturesSourceFolders) + classpathRoots.addAll(project.testFixturesLibraries) + } + + // Don't include all class folders: + // files.addAll(project.getJavaClassFolders()); + // These are the outputs from the sources and generated sources, which we will + // parse directly with PSI/UAST anyway. Including them here leads lint to do + // a lot more work (e.g. when resolving symbols it looks at both .java and .class + // matches). + // However, we *do* need them for libraries; otherwise, type resolution into + // compiled libraries will not work; see + // https://issuetracker.google.com/72032121 + // (We also enable this for unit tests where there is no actual compilation; + // here, the presence of class files is simulating binary-only access + if (project.isLibrary) { + classpathRoots.addAll(project.javaClassFolders) + } else if (project.isGradleProject) { + // As of 3.4, R.java is in a special jar file + for (f in project.javaClassFolders) { + if (f.name == SdkConstants.FN_R_CLASS_JAR) { + classpathRoots.add(f) + } + } + } + } + var maxLevel = LanguageLevel.JDK_1_7 + for (project in projects) { + val level = project.javaLanguageLevel + if (maxLevel.isLessThan(level)) { + maxLevel = level + } + } + + for (file in sourceRoots + classpathRoots) { + // IntelliJ expects absolute file paths, otherwise resolution can fail in subtle ways. + require(file.isAbsolute) { "Relative Path found: $file. All paths should be absolute." } + } + + val config = UastEnvironment.Configuration.create() + config.javaLanguageLevel = maxLevel + config.addSourceRoots(sourceRoots.toList()) + config.addClasspathRoots(classpathRoots.toList()) + jdkHomePath?.let { + config.kotlinCompilerConfig.put(JVMConfigurationKeys.JDK_HOME, it) + config.kotlinCompilerConfig.put(JVMConfigurationKeys.NO_JDK, false) + } + + val env = UastEnvironment.create(config) + + for (project in allProjects) { + project.ideaProject = env.ideaProject + project.env = env.coreAppEnv + } + } + + @Suppress("UNCHECKED_CAST") + private fun createDriver(projects: List<Project>, client: MainLintClient): LintDriver { + val emptyIssueRegistry = + object : IssueRegistry() { + override val vendor: Vendor = AOSP_VENDOR + override val issues: List<Issue> + get() = listOf() + } + val roots = resolveDependencies(projects as List<LintModelModuleProject>, false) + + val lintRequest = LintRequest(client, emptyList()) + lintRequest.setProjects(roots) + + return client.createDriver(emptyIssueRegistry, lintRequest) + } + + private fun configureProject(client: LintCliClient, argumentState: ArgumentState): List<Project> { + val modules: List<LintModelModule> = argumentState.modules + val projects: MutableList<Project> = ArrayList() + if (modules.isNotEmpty()) { + for (module: LintModelModule in modules) { + val dir = module.dir + val variant: LintModelVariant? = module.defaultVariant() + assert(variant != null) + val project = LintModelModuleProject( + client, dir, dir, + (variant)!!, null + ) + client.registerProject(project.dir, project) + projects.add(project) + } + } + return projects + } + + private fun initializeConfigurations( + client: LintCliClient, + argumentState: ArgumentState + ) { + val configurations = client.configurations + val overrideConfig = flags.overrideLintConfig + if (overrideConfig != null) { + val config: Configuration = create(configurations, overrideConfig) + configurations.addGlobalConfigurations(null, config) + } + val override = CliConfiguration(configurations, flags, flags.isFatalOnly) + val defaultConfiguration = flags.lintConfig + configurations.addGlobalConfigurationFromFile(defaultConfiguration, override) + client.syncConfigOptions() + if (argumentState.modules.isNotEmpty()) { + val dir = argumentState.modules[0].dir + override.associatedLocation = create(dir) + } + } + + private fun initializePathVariables( + argumentState: ArgumentState, client: LintCliClient + ) { + val pathVariables = client.pathVariables + for (module in argumentState.modules) { + // Add project directory path variable + pathVariables.add( + "{" + module.modulePath + "*projectDir}", module.dir, false + ) + // Add build directory path variable + pathVariables.add( + "{" + module.modulePath + "*buildDir}", module.buildFolder, false + ) + for (variant in module.variants) { + for ((sourceProviderIndex, sourceProvider) in variant.sourceProviders.withIndex()) { + addSourceProviderPathVariables( + pathVariables, + sourceProvider, + "sourceProvider", + sourceProviderIndex, + module.modulePath, + variant.name + ) + } + for ((testSourceProviderIndex, testSourceProvider) in variant.testSourceProviders.withIndex()) { + addSourceProviderPathVariables( + pathVariables, + testSourceProvider, + "testSourceProvider", + testSourceProviderIndex, + module.modulePath, + variant.name + ) + } + for ((testFixturesSourceProviderIndex, testFixturesSourceProvider) in variant.testFixturesSourceProviders.withIndex()) { + addSourceProviderPathVariables( + pathVariables, + testFixturesSourceProvider, + "testFixturesSourceProvider", + testFixturesSourceProviderIndex, + module.modulePath, + variant.name + ) + } + } + } + pathVariables.sort() + } + + /** Adds necessary path variables to pathVariables. */ + private fun addSourceProviderPathVariables( + pathVariables: PathVariables, + sourceProvider: LintModelSourceProvider, + sourceProviderType: String, + sourceProviderIndex: Int, + modulePath: String, + variantName: String + ) { + addSourceProviderPathVariables( + pathVariables, + sourceProvider.manifestFiles, + modulePath, + variantName, + sourceProviderType, + sourceProviderIndex, + "manifest" + ) + addSourceProviderPathVariables( + pathVariables, + sourceProvider.javaDirectories, + modulePath, + variantName, + sourceProviderType, + sourceProviderIndex, + "javaDir" + ) + addSourceProviderPathVariables( + pathVariables, + sourceProvider.resDirectories, + modulePath, + variantName, + sourceProviderType, + sourceProviderIndex, + "resDir" + ) + addSourceProviderPathVariables( + pathVariables, + sourceProvider.assetsDirectories, + modulePath, + variantName, + sourceProviderType, + sourceProviderIndex, + "assetsDir" + ) + } + + /** Adds necessary path variables to pathVariables. */ + private fun addSourceProviderPathVariables( + pathVariables: PathVariables, + files: Collection<File>, + modulePath: String, + variantName: String, + sourceProviderType: String, + sourceProviderIndex: Int, + sourceType: String + ) { + for ((index, file) in files.withIndex()) { + val name = ("{" + + modulePath + + "*" + + variantName + + "*" + + sourceProviderType + + "*" + + sourceProviderIndex + + "*" + + sourceType + + "*" + + index + + "}") + pathVariables.add(name, file, false) + } + } + + private fun parseArguments( + args: Array<String>, + client: LintCliClient, + argumentState: ArgumentState + ): Int { + var index = 0 + while (index < args.size) { + val arg = args[index] + if (arg == ARG_CLIENT_ID) { + if (index == args.size - 1) { + System.err.println("Missing client id") + return ERRNO_INVALID_ARGS + } + clientName = args[++index] + } else if (arg == ARG_CLIENT_NAME) { + if (index == args.size - 1) { + System.err.println("Missing client name") + return ERRNO_INVALID_ARGS + } + argumentState.clientName = args[++index] + } else if (arg == ARG_CLIENT_VERSION) { + if (index == args.size - 1) { + System.err.println("Missing client version") + return ERRNO_INVALID_ARGS + } + argumentState.clientVersion = args[++index] + } else if (arg == ARG_SDK_HOME) { + if (index == args.size - 1) { + System.err.println("Missing SDK home directory") + return ERRNO_INVALID_ARGS + } + sdkHomePath = File(args[++index]) + if (!sdkHomePath!!.isDirectory) { + System.err.println(sdkHomePath.toString() + " is not a directory") + return ERRNO_INVALID_ARGS + } + } else if (arg == ARG_JDK_HOME) { + if (index == args.size - 1) { + System.err.println("Missing JDK home directory") + return ERRNO_INVALID_ARGS + } + jdkHomePath = File(args[++index]) + if (!jdkHomePath!!.isDirectory) { + System.err.println(jdkHomePath.toString() + " is not a directory") + return ERRNO_INVALID_ARGS + } + if (!isJreFolder(jdkHomePath!!)) { + System.err.println(jdkHomePath.toString() + " is not a JRE/JDK") + return ERRNO_INVALID_ARGS + } + } else if (arg == ARG_LINT_MODEL) { + if (index == args.size - 1) { + System.err.println("Missing lint model argument after $ARG_LINT_MODEL") + return ERRNO_INVALID_ARGS + } + val paths = args[++index] + for (path: String in splitPath(paths)) { + val input: File = getInArgumentPath(path) + if (!input.exists()) { + System.err.println("Lint model $input does not exist.") + return ERRNO_INVALID_ARGS + } + if (!input.isDirectory) { + System.err.println( + "Lint model " + + input + + " should be a folder containing the XML descriptor files" + + if (input.isDirectory) ", not a file" else "" + ) + return ERRNO_INVALID_ARGS + } + try { + val reader = LintModelSerialization + val module = reader.readModule(input, null, true, client.pathVariables) + argumentState.modules.add(module) + } catch (error: Throwable) { + System.err.println( + ("Could not deserialize " + + input + + " to a lint model: " + + error.toString()) + ) + return ERRNO_INVALID_ARGS + } + } + } else if ((arg == ARG_LINT_RULE_JARS)) { + if (index == args.size - 1) { + System.err.println("Missing lint rule jar") + return ERRNO_INVALID_ARGS + } + val lintRuleJarsOverride: MutableList<File> = ArrayList() + val currentOverrides = flags.lintRuleJarsOverride + if (currentOverrides != null) { + lintRuleJarsOverride.addAll(currentOverrides) + } + for (path: String in splitPath(args[++index])) { + lintRuleJarsOverride.add(getInArgumentPath(path)) + } + flags.lintRuleJarsOverride = lintRuleJarsOverride + } else if ((arg == ARG_CACHE_DIR)) { + if (index == args.size - 1) { + System.err.println("Missing cache directory") + return ERRNO_INVALID_ARGS + } + val path = args[++index] + val input: File = getInArgumentPath(path) + flags.setCacheDir(input) + } else { + return ERRNO_ERRORS + } + index++ + } + return 0 + } + + /** + * Converts a relative or absolute command-line argument into an input file. + * + * @param filename The filename given as a command-line argument. + * @return A File matching filename, either absolute or relative to lint.workdir if defined. + */ + private fun getInArgumentPath(filename: String): File { + var file = File(filename) + if (!file.isAbsolute) { + if (!file.isAbsolute) { + file = file.absoluteFile + } + } + return file + } + + inner class ArgumentState { + + @Nullable + var clientVersion: String? = null + + @Nullable + var clientName: String? = null + + @Nullable + var javaLanguageLevel: LanguageLevel? = null + + @Nullable + var kotlinLanguageLevel: LanguageVersionSettings? = null + + @NonNull + var modules: MutableList<LintModelModule> = mutableListOf() + + @NonNull + var files: List<File> = mutableListOf() + } + + inner class MainLintClient(flags: LintCliFlags, private val argumentState: ArgumentState) : + LintCliClient(flags, CLIENT_CLI) { + + private var unexpectedGradleProject: Project? = null + + public override fun createDriver( + registry: IssueRegistry, request: LintRequest + ): LintDriver { + val driver: LintDriver = super.createDriver(registry, request) + val project: Project? = unexpectedGradleProject + if (project != null) { + val message = java.lang.String.format( + "\"`%1\$s`\" is a Gradle project. To correctly " + + "analyze Gradle projects, you should run \"`gradlew lint`\" " + + "instead.", + project.name + ) + val location: Location = guessGradleLocation(this, project.dir, null) + report( + this, IssueRegistry.LINT_ERROR, message, driver, project, location, null + ) + } + return driver + } + + override fun createProject(dir: File, referenceDir: File): Project { + val project: Project = super.createProject(dir, referenceDir) + if (project.isGradleProject) { + // Can't report error yet; stash it here so we can report it after the + // driver has been created + unexpectedGradleProject = project + } + return project + } + + override fun getJavaLanguageLevel(project: Project): LanguageLevel { + return argumentState.javaLanguageLevel ?: super.getJavaLanguageLevel(project) + } + + override fun getKotlinLanguageLevel(project: Project): LanguageVersionSettings { + return argumentState.kotlinLanguageLevel ?: super.getKotlinLanguageLevel(project) + } + + override fun getConfiguration( + project: Project, driver: LintDriver? + ): Configuration { + if (project.isGradleProject && project !is LintModelModuleProject) { + // Don't report any issues when analyzing a Gradle project from the + // non-Gradle runner; they are likely to be false, and will hide the + // real problem reported above. We also need to turn off overrides + // and fallbacks such that we don't inherit any re-enabled issues etc. + val configurations: ConfigurationHierarchy = configurations + configurations.overrides = null + configurations.fallback = null + return object : CliConfiguration(configurations, flags, true) { + override fun getDefinedSeverity( + issue: Issue, + source: Configuration, + visibleDefault: Severity + ): Severity { + return if (issue === IssueRegistry.LINT_ERROR) Severity.FATAL else Severity.IGNORE + } + + override fun isIgnored(context: Context, incident: Incident): Boolean { + // If you've deliberately ignored IssueRegistry.LINT_ERROR + // don't flag that one either + val issue: Issue = incident.issue + if ((issue === IssueRegistry.LINT_ERROR + && LintCliClient(flags, clientName) + .isSuppressed(IssueRegistry.LINT_ERROR)) + ) { + return true + } else if ((issue === IssueRegistry.LINT_WARNING + && LintCliClient(flags, clientName) + .isSuppressed(IssueRegistry.LINT_WARNING)) + ) { + return true + } + return (issue !== IssueRegistry.LINT_ERROR + && issue !== IssueRegistry.LINT_WARNING) + } + } + } + return super.getConfiguration(project, driver) + } + + private fun readSrcJar(file: File): ByteArray? { + val path = file.path + val srcJarIndex = path.indexOf("srcjar!") + if (srcJarIndex != -1) { + val jarFile = File(path.substring(0, srcJarIndex + 6)) + if (jarFile.exists()) { + try { + ZipFile(jarFile).use { zipFile -> + val name: String = + path.substring(srcJarIndex + 8).replace(File.separatorChar, '/') + val entry: ZipEntry? = zipFile.getEntry(name) + if (entry != null) { + try { + zipFile.getInputStream(entry).use { `is` -> + return ByteStreams.toByteArray( + `is` + ) + } + } catch (e: Exception) { + log(e, null) + } + } + } + } catch (e: ZipException) { + // com.android.tools.lint.Main.this.log(e, "Could not unzip %1$s", jarFile); + } catch (e: IOException) { + // com.android.tools.lint.Main.this.log(e, "Could not read %1$s", jarFile); + } + } + } + return null + } + + override fun readFile(file: File): CharSequence { + // .srcjar file handle? + val srcJarBytes = readSrcJar(file) + return if (srcJarBytes != null) { + String(srcJarBytes, Charsets.UTF_8) + } else super.readFile(file) + } + + @Throws(IOException::class) + override fun readBytes(file: File): ByteArray { + // .srcjar file handle? + return (readSrcJar(file))!! + } + + private var metadata: ProjectMetadata? = null + override fun configureLintRequest(lintRequest: LintRequest) { + super.configureLintRequest(lintRequest) + val descriptor: File? = flags.projectDescriptorOverride + if (descriptor != null) { + metadata = computeMetadata(this, descriptor) + val clientName: String? = metadata!!.clientName + if (clientName != null) { + LintCliClient(clientName) // constructor has side effect + } + val projects: List<Project> = metadata!!.projects + if (projects.isNotEmpty()) { + lintRequest.setProjects(projects) + if (metadata!!.sdk != null) { + sdkHomePath = metadata!!.sdk + } + if (metadata!!.jdk!= null) { + jdkHomePath = metadata!!.jdk + } + if (metadata!!.baseline != null) { + flags.baselineFile = metadata!!.baseline + } + val scope: EnumSet<Scope> = EnumSet.copyOf(Scope.ALL) + if (metadata!!.incomplete) { + scope.remove(Scope.ALL_CLASS_FILES) + scope.remove(Scope.ALL_JAVA_FILES) + scope.remove(Scope.ALL_RESOURCE_FILES) + } + lintRequest.setScope(scope) + lintRequest.setPlatform(metadata!!.platforms) + } + } + } + + override fun findRuleJars(project: Project): Iterable<File> { + if (metadata != null) { + val jars: List<File>? = metadata!!.lintChecks[project] + if (jars != null) { + return jars + } + } + return super.findRuleJars(project) + } + + override fun findGlobalRuleJars(driver: LintDriver?, warnDeprecated: Boolean): List<File> { + if (metadata != null) { + val jars: List<File> = metadata!!.globalLintChecks + if (jars.isNotEmpty()) { + return jars + } + } + return super.findGlobalRuleJars(driver, warnDeprecated) + } + + override fun getCacheDir(name: String?, create: Boolean): File? { + if (metadata != null) { + var dir: File? = metadata!!.cache + if (dir != null) { + if (name != null) { + dir = File(dir, name) + } + if (create && !dir.exists()) { + if (!dir.mkdirs()) { + return null + } + } + return dir + } + } + return super.getCacheDir(name, create) + } + + override fun getMergedManifest(project: Project): Document? { + if (metadata != null) { + val manifest: File? = metadata!!.mergedManifests[project] + if (manifest != null && manifest.exists()) { + try { + // We can't call + // resolveMergeManifestSources(document, manifestReportFile) + // here since we don't have the merging log. + return XmlUtils.parseUtfXmlFile(manifest, true) + } catch (e: IOException) { + log(e, "Could not read/parse %1\$s", manifest) + } catch (e: SAXException) { + log(e, "Could not read/parse %1\$s", manifest) + } + } + } + return super.getMergedManifest(project) + } + + override fun getSdkHome(): File? { + return if (sdkHomePath != null) { + sdkHomePath + } else super.getSdkHome() + } + + override fun getJdkHome(project: Project?): File? { + return if (jdkHomePath != null) { + jdkHomePath + } else super.getJdkHome(project) + } + + override fun addBootClassPath( + knownProjects: Collection<Project>, files: MutableSet<File> + ): Boolean { + if (metadata != null && metadata!!.jdkBootClasspath.isNotEmpty()) { + var isAndroid = false + for (project in knownProjects) { + if (project.isAndroidProject) { + isAndroid = true + break + } + } + if (!isAndroid) { + files.addAll(metadata!!.jdkBootClasspath) + return true + } + val ok: Boolean = super.addBootClassPath(knownProjects, files) + if (!ok) { + files.addAll(metadata!!.jdkBootClasspath) + } + return ok + } + return super.addBootClassPath(knownProjects, files) + } + override fun getExternalAnnotations(projects: Collection<Project>): List<File> { + val externalAnnotations: MutableList<File> = super.getExternalAnnotations(projects).toMutableList() + if (metadata != null) { + externalAnnotations.addAll(metadata!!.externalAnnotations) + } + return externalAnnotations } } } diff --git a/process-monitor/src/test/com/android/processmonitor/agenttracker/AgentProcessTrackerTest.kt b/process-monitor/src/test/com/android/processmonitor/agenttracker/AgentProcessTrackerTest.kt index 1d2afd8754..c9987581a5 100644 --- a/process-monitor/src/test/com/android/processmonitor/agenttracker/AgentProcessTrackerTest.kt +++ b/process-monitor/src/test/com/android/processmonitor/agenttracker/AgentProcessTrackerTest.kt @@ -15,12 +15,9 @@ */ package com.android.processmonitor.agenttracker -import com.android.adblib.AdbSession import com.android.adblib.RemoteFileMode import com.android.adblib.testing.FakeAdbLoggerFactory -import com.android.adblib.testingutils.CloseablesRule -import com.android.adblib.testingutils.FakeAdbServerProvider -import com.android.adblib.testingutils.TestingAdbSessionHost +import com.android.adblib.testingutils.FakeAdbServerProviderRule import com.android.fakeadbserver.DeviceFileState import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.DeviceState.HostConnectionType.USB @@ -44,27 +41,17 @@ import java.nio.file.Path @OptIn(ExperimentalCoroutinesApi::class) // runTest is experimental (replaced runTestTest) internal class AgentProcessTrackerTest { - @get:Rule - val closeables = CloseablesRule() - private val makeAgentDirHandler = MakeAgentDirCommandHandler() private val agentHandler = ProcessTrackerAgentCommandHandler() - private val fakeAdb = closeables.register( - FakeAdbServerProvider() - .buildDefault() - .start() - .installDeviceHandler(agentHandler) - .installDeviceHandler(makeAgentDirHandler) - .installDeviceHandler(SyncCommandHandler()) - ) - private val adbHost = closeables.register(TestingAdbSessionHost()) - private val adbSession = closeables.register( - AdbSession.create(adbHost, fakeAdb.createChannelProvider(adbHost)) - ) - + @get:Rule + val fakeAdbRule = FakeAdbServerProviderRule { + installDefaultCommandHandlers() + installDeviceHandler(agentHandler) + installDeviceHandler(makeAgentDirHandler) + installDeviceHandler(SyncCommandHandler()) + } private val logger = FakeAdbLoggerFactory().logger - private val agentSourcePath = TestResources.getDirectory("/agent").toPath() @Test @@ -133,7 +120,7 @@ internal class AgentProcessTrackerTest { } private fun setupDevice(serialNumber: String): DeviceState = - fakeAdb.connectDevice(serialNumber, "", "", "13", "33", USB) + fakeAdbRule.fakeAdb.connectDevice(serialNumber, "", "", "13", "33", USB) private fun agentProcessTracker( serialNumber: String, @@ -142,7 +129,7 @@ internal class AgentProcessTrackerTest { intervalMillis: Int = 1000, ): AgentProcessTracker = AgentProcessTracker( - adbSession, + fakeAdbRule.adbSession, serialNumber, deviceAbi, agentSourcePath, diff --git a/process-monitor/src/test/com/android/processmonitor/agenttracker/MakeAgentDirCommandHandler.kt b/process-monitor/src/test/com/android/processmonitor/agenttracker/MakeAgentDirCommandHandler.kt index 8af66aeb20..2b4b7a0320 100644 --- a/process-monitor/src/test/com/android/processmonitor/agenttracker/MakeAgentDirCommandHandler.kt +++ b/process-monitor/src/test/com/android/processmonitor/agenttracker/MakeAgentDirCommandHandler.kt @@ -18,7 +18,7 @@ package com.android.processmonitor.agenttracker import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput import com.android.fakeadbserver.shellcommandhandlers.ShellHandler import com.android.fakeadbserver.shellcommandhandlers.StatusWriter import com.android.processmonitor.agenttracker.AgentProcessTracker.Companion.AGENT_DIR @@ -40,14 +40,14 @@ internal class MakeAgentDirCommandHandler : ShellHandler(ShellProtocolType.SHELL override fun execute( fakeAdbServer: FakeAdbServer, statusWriter: StatusWriter, - serviceOutput: ServiceOutput, + shellCommandOutput: ShellCommandOutput, device: DeviceState, shellCommand: String, shellCommandArgs: String? ) { statusWriter.writeOk() invocations.add(device.deviceId) - serviceOutput.writeStdout("") - serviceOutput.writeExitCode(0) + shellCommandOutput.writeStdout("") + shellCommandOutput.writeExitCode(0) } } diff --git a/process-monitor/src/test/com/android/processmonitor/agenttracker/ProcessTrackerAgentCommandHandler.kt b/process-monitor/src/test/com/android/processmonitor/agenttracker/ProcessTrackerAgentCommandHandler.kt index f221857599..3536b3d400 100644 --- a/process-monitor/src/test/com/android/processmonitor/agenttracker/ProcessTrackerAgentCommandHandler.kt +++ b/process-monitor/src/test/com/android/processmonitor/agenttracker/ProcessTrackerAgentCommandHandler.kt @@ -19,7 +19,7 @@ import ai.grazie.utils.dropPrefix import com.android.fakeadbserver.DeviceState import com.android.fakeadbserver.FakeAdbServer import com.android.fakeadbserver.ShellProtocolType -import com.android.fakeadbserver.services.ServiceOutput +import com.android.fakeadbserver.services.ShellCommandOutput import com.android.fakeadbserver.shellcommandhandlers.SimpleShellHandler import com.android.fakeadbserver.shellcommandhandlers.StatusWriter import com.android.processmonitor.agenttracker.AgentProcessTracker.Companion.AGENT_PATH @@ -55,7 +55,7 @@ internal class ProcessTrackerAgentCommandHandler : SimpleShellHandler( override fun execute( fakeAdbServer: FakeAdbServer, statusWriter: StatusWriter, - serviceOutput: ServiceOutput, + shellCommandOutput: ShellCommandOutput, device: DeviceState, shellCommand: String, shellCommandArgs: String? @@ -67,12 +67,12 @@ internal class ProcessTrackerAgentCommandHandler : SimpleShellHandler( it != EOF }.collect { when { - it.startsWith(STDOUT) -> serviceOutput.writeStdout(it.dropPrefix(STDOUT)) - it.startsWith(STDERR) -> serviceOutput.writeStderr(it.dropPrefix(STDERR)) + it.startsWith(STDOUT) -> shellCommandOutput.writeStdout(it.dropPrefix(STDOUT)) + it.startsWith(STDERR) -> shellCommandOutput.writeStderr(it.dropPrefix(STDERR)) else -> throw IllegalStateException("Unexpected data: $it") } } } - serviceOutput.writeExitCode(0) + shellCommandOutput.writeExitCode(0) } } diff --git a/process-monitor/src/test/com/android/processmonitor/monitor/adblib/DeviceTrackerAdblibTest.kt b/process-monitor/src/test/com/android/processmonitor/monitor/adblib/DeviceTrackerAdblibTest.kt index 0fe966a3ef..8fe546dcb7 100644 --- a/process-monitor/src/test/com/android/processmonitor/monitor/adblib/DeviceTrackerAdblibTest.kt +++ b/process-monitor/src/test/com/android/processmonitor/monitor/adblib/DeviceTrackerAdblibTest.kt @@ -15,13 +15,10 @@ */ package com.android.processmonitor.monitor.adblib -import com.android.adblib.AdbSession import com.android.adblib.DeviceSelector import com.android.adblib.testing.FakeAdbLoggerFactory -import com.android.adblib.testingutils.CloseablesRule import com.android.adblib.testingutils.CoroutineTestUtils.runBlockingWithTimeout import com.android.adblib.testingutils.FakeAdbServerProvider -import com.android.adblib.testingutils.TestingAdbSessionHost import com.android.ddmlib.TimeoutException import com.android.fakeadbserver.DeviceState.DeviceStatus import com.android.fakeadbserver.DeviceState.DeviceStatus.ONLINE @@ -31,7 +28,7 @@ import com.android.processmonitor.common.DeviceEvent.DeviceOnline import com.android.processmonitor.testutils.toChannel import com.android.sdklib.deviceprovisioner.DeviceProvisioner import com.android.sdklib.deviceprovisioner.DeviceState -import com.android.sdklib.deviceprovisioner.testing.FakeAdbDeviceProvisionerPlugin +import com.android.sdklib.deviceprovisioner.testing.DeviceProvisionerRule import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.take @@ -47,23 +44,10 @@ import java.time.Duration class DeviceTrackerAdblibTest { @get:Rule - val closeables = CloseablesRule() - - private val fakeAdb = closeables.register( - FakeAdbServerProvider() - .buildDefault() - .start() - ) - private val adbHost = closeables.register(TestingAdbSessionHost()) - - private val adbSession = closeables.register( - AdbSession.create(adbHost, fakeAdb.createChannelProvider(adbHost)) - ) - - private val deviceProvisioner = DeviceProvisioner.create( - adbSession, - listOf(FakeAdbDeviceProvisionerPlugin(adbSession.scope, fakeAdb)), - ) + val deviceProvisionerRule = DeviceProvisionerRule() + + private val fakeAdb get() = deviceProvisionerRule.fakeAdb + private val deviceProvisioner get() = deviceProvisionerRule.deviceProvisioner private val logger = FakeAdbLoggerFactory().logger diff --git a/process-monitor/src/test/com/android/processmonitor/monitor/adblib/JdwpProcessTrackerTest.kt b/process-monitor/src/test/com/android/processmonitor/monitor/adblib/JdwpProcessTrackerTest.kt index 7dd3c152aa..ede810c916 100644 --- a/process-monitor/src/test/com/android/processmonitor/monitor/adblib/JdwpProcessTrackerTest.kt +++ b/process-monitor/src/test/com/android/processmonitor/monitor/adblib/JdwpProcessTrackerTest.kt @@ -21,9 +21,7 @@ import com.android.adblib.connectedDevicesTracker import com.android.adblib.device import com.android.adblib.serialNumber import com.android.adblib.testing.FakeAdbLoggerFactory -import com.android.adblib.testingutils.CloseablesRule -import com.android.adblib.testingutils.FakeAdbServerProvider -import com.android.adblib.testingutils.TestingAdbSessionHost +import com.android.adblib.testingutils.FakeAdbServerProviderRule import com.android.fakeadbserver.DeviceState.DeviceStatus.ONLINE import com.android.fakeadbserver.DeviceState.HostConnectionType.USB import com.android.processmonitor.common.ProcessEvent.ProcessAdded @@ -47,17 +45,9 @@ import org.junit.Test class JdwpProcessTrackerTest { @get:Rule - val closeables = CloseablesRule() - - private val fakeAdb = closeables.register( - FakeAdbServerProvider() - .buildDefault() - .start() - ) - private val adbHost = closeables.register(TestingAdbSessionHost()) - private val adbSession = closeables.register( - AdbSession.create(adbHost, fakeAdb.createChannelProvider(adbHost)) - ) + val fakeAdbRule = FakeAdbServerProviderRule() + + private val adbSession get() = fakeAdbRule.adbSession private val logger = FakeAdbLoggerFactory().logger @Test @@ -147,7 +137,7 @@ class JdwpProcessTrackerTest { } private fun setupDevice(serialNumber: String, sdk: Int) = - fakeAdb.connectDevice(serialNumber, "", "", "13", sdk.toString(), USB).apply { + fakeAdbRule.fakeAdb.connectDevice(serialNumber, "", "", "13", sdk.toString(), USB).apply { deviceStatus = ONLINE } diff --git a/profgen/OWNERS b/profgen/OWNERS index 4a9f0fcbbe..c8ba4bfde8 100644 --- a/profgen/OWNERS +++ b/profgen/OWNERS @@ -1,4 +1,5 @@ gijosh@google.com lelandr@google.com rahulrav@google.com +ccraik@google.com shukang@google.com diff --git a/profgen/profgen-cli/src/main/kotlin/com/android/tools/profgen/cli/BinCommand.kt b/profgen/profgen-cli/src/main/kotlin/com/android/tools/profgen/cli/BinCommand.kt index cadf41f048..e746317f83 100644 --- a/profgen/profgen-cli/src/main/kotlin/com/android/tools/profgen/cli/BinCommand.kt +++ b/profgen/profgen-cli/src/main/kotlin/com/android/tools/profgen/cli/BinCommand.kt @@ -23,21 +23,24 @@ import com.android.tools.profgen.Diagnostics import com.android.tools.profgen.HumanReadableProfile import com.android.tools.profgen.ObfuscationMap import com.android.tools.profgen.dumpProfile +import com.android.tools.profgen.extractProfileAsDm import kotlinx.cli.ArgType import kotlinx.cli.ExperimentalCli import kotlinx.cli.Subcommand import kotlinx.cli.default import kotlinx.cli.required import java.io.File +import kotlin.io.path.Path import kotlin.system.exitProcess +@Suppress("unused") // Values are referenced by name as shell args @ExperimentalCli -enum class ArtProfileFormat { - V0_1_5_S, // targets S+ - V0_1_0_P, // targets P -> R - V0_0_9_OMR1, // targets Android O MR1 - V0_0_5_O, // targets O - V0_0_1_N // targets N +enum class ArtProfileFormat(internal val serializer: ArtProfileSerializer) { + V0_1_5_S(ArtProfileSerializer.V0_1_5_S), // targets S+ + V0_1_0_P(ArtProfileSerializer.V0_1_0_P), // targets P -> R + V0_0_9_OMR1(ArtProfileSerializer.V0_0_9_OMR1), // targets Android O MR1 + V0_0_5_O(ArtProfileSerializer.V0_0_5_O), // targets O + V0_0_1_N(ArtProfileSerializer.V0_0_1_N) // targets N } @ExperimentalCli @@ -50,37 +53,30 @@ class BinCommand : Subcommand("bin", "Generate Binary Profile") { val artProfileFormat by option(ArgType.Choice<ArtProfileFormat>(), "profile-format", "pf", "The ART profile format version").default(ArtProfileFormat.V0_1_0_P) override fun execute() { - val hrpFile = File(hrpPath) + val hrpFile = Path(hrpPath).toFile() require(hrpFile.exists()) { "File not found: $hrpPath" } - val apkFile = File(apkPath) + val apkFile = Path(apkPath).toFile() require(apkFile.exists()) { "File not found: $apkPath" } - val obfFile = obfPath?.let { File(it) } + val obfFile = obfPath?.let { Path(it).toFile() } require(obfFile?.exists() != false) { "File not found: $obfPath" } - val metaFile = metaPath?.let { File(it) } + val metaFile = metaPath?.let { Path(it).toFile() } if (metaFile != null) { require(metaFile.parentFile.exists()) { "Directory does not exist: ${metaFile.parent}" } } - val outFile = File(outPath) + val outFile = Path(outPath).toFile() require(outFile.parentFile.exists()) { "Directory does not exist: ${outFile.parent}" } val hrp = readHumanReadableProfileOrExit(hrpFile) val apk = Apk(apkFile) val obf = if (obfFile != null) ObfuscationMap(obfFile) else ObfuscationMap.Empty val profile = ArtProfile(hrp, obf, apk) - val version = when(artProfileFormat) { - ArtProfileFormat.V0_1_0_P -> ArtProfileSerializer.V0_1_0_P - ArtProfileFormat.V0_1_5_S -> ArtProfileSerializer.V0_1_5_S - ArtProfileFormat.V0_0_9_OMR1 -> ArtProfileSerializer.V0_0_9_OMR1 - ArtProfileFormat.V0_0_5_O -> ArtProfileSerializer.V0_0_5_O - ArtProfileFormat.V0_0_1_N -> ArtProfileSerializer.V0_0_1_N - } - profile.save(outFile.outputStream(), version) + profile.save(outFile.outputStream(), artProfileFormat.serializer) if (metaFile != null) { profile.save(metaFile.outputStream(), ArtProfileSerializer.METADATA_0_0_2) } @@ -88,10 +84,32 @@ class BinCommand : Subcommand("bin", "Generate Binary Profile") { } @ExperimentalCli +class ExtractProfileCommand : Subcommand("extractProfile", "Extract Binary Profile as versioned dex metadata") { + private val apkPath by option(ArgType.String, "apk", "a", "File path to apk").required() + private val outPath by option(ArgType.String, "output-dex-metadata", "odm", "File path to generated dex metadata output").required() + private val artProfileFormat by option(ArgType.Choice<ArtProfileFormat>(), "profile-format", "pf", "The ART profile format version").default(ArtProfileFormat.V0_1_0_P) + + override fun execute() { + val apkFile = Path(apkPath).toFile() + require(apkFile.exists()) { "File not found: $apkPath" } + + val outFile = Path(outPath).toFile() + require(outFile.parentFile.exists()) { "Directory does not exist: ${outFile.parent}" } + + extractProfileAsDm( + apkFile = apkFile, + profileSerializer = artProfileFormat.serializer, + metadataSerializer = ArtProfileSerializer.METADATA_0_0_2, + outputStream = outFile.outputStream() + ) + } +} + +@ExperimentalCli class ValidateCommand : Subcommand("validate", "Validate Profile") { val hrpPath by argument(ArgType.String, "profile", "File path to Human Readable profile") override fun execute() { - val hrpFile = File(hrpPath) + val hrpFile = Path(hrpPath).toFile() require(hrpFile.exists()) { "File not found: $hrpPath" } HumanReadableProfile(hrpFile, StdErrorDiagnostics) } @@ -104,16 +122,16 @@ class PrintCommand : Subcommand("print", "Print methods matching profile") { val outPath by option(ArgType.String, "output", "o", "File path to generated binary profile").required() val obfPath by option(ArgType.String, "map", "m", "File path to name obfuscation map") override fun execute() { - val hrpFile = File(hrpPath) + val hrpFile = Path(hrpPath).toFile() require(hrpFile.exists()) { "File not found: $hrpPath" } - val apkFile = File(apkPath) + val apkFile = Path(apkPath).toFile() require(apkFile.exists()) { "File not found: $apkPath" } - val obfFile = obfPath?.let { File(it) } + val obfFile = obfPath?.let { Path(it).toFile() } require(obfFile?.exists() != false) { "File not found: $obfPath" } - val outFile = File(outPath) + val outFile = Path(outPath).toFile() require(outFile.parentFile.exists()) { "Directory does not exist: ${outFile.parent}" } val hrp = readHumanReadableProfileOrExit(hrpFile) @@ -131,16 +149,16 @@ class ProfileDumpCommand: Subcommand("dumpProfile", "Dump a binary profile to a val strictMode by option(ArgType.Boolean, "strict", "s", "Strict mode").default(value = true) val outPath by option(ArgType.String, "output", "o", "File path for the HRF").required() override fun execute() { - val binFile = File(binPath) + val binFile = Path(binPath).toFile() require(binFile.exists()) { "File not found: $binPath" } - val apkFile = File(apkPath) + val apkFile = Path(apkPath).toFile() require(apkFile.exists()) { "File not found: $apkPath" } - val obfFile = obfPath?.let { File(it) } + val obfFile = obfPath?.let { Path(it).toFile() } require(obfFile?.exists() != false) { "File not found: $obfPath" } - val outFile = File(outPath) + val outFile = Path(outPath).toFile() require(outFile.parentFile.exists()) { "Directory does not exist: ${outFile.parent}" } val profile = ArtProfile(binFile)!! diff --git a/profgen/profgen-cli/src/main/kotlin/com/android/tools/profgen/cli/ExpandWildcardsCommand.kt b/profgen/profgen-cli/src/main/kotlin/com/android/tools/profgen/cli/ExpandWildcardsCommand.kt index e42a7e9756..9557dafd2b 100644 --- a/profgen/profgen-cli/src/main/kotlin/com/android/tools/profgen/cli/ExpandWildcardsCommand.kt +++ b/profgen/profgen-cli/src/main/kotlin/com/android/tools/profgen/cli/ExpandWildcardsCommand.kt @@ -17,53 +17,69 @@ package com.android.tools.profgen.cli import com.android.tools.profgen.ArchiveClassFileResourceProvider -import com.android.tools.profgen.ClassFileResource import com.android.tools.profgen.CLASS_EXTENSION +import com.android.tools.profgen.ClassFileResource +import com.android.tools.profgen.getClassDescriptorFromBinaryName import com.android.tools.profgen.JAR_EXTENSION +import kotlin.io.path.Path import kotlinx.cli.ArgType import kotlinx.cli.ExperimentalCli import kotlinx.cli.Subcommand import kotlinx.cli.required import kotlinx.cli.vararg -import java.io.File +import kotlin.io.path.Path @ExperimentalCli class ExpandWildcardsCommand: Subcommand("expandWildcards", "Dump a binary profile to a HRF") { val hrpPath by option(ArgType.String, "profile", "p", "File path to the human readable profile") - .required() + .required() val outPath by option( - ArgType.String, "output", "o", - "File path for the resulting human readable profile without wildcards" - ) - .required() - val programPaths by argument(ArgType.String, "program", "File paths to program sources") - .vararg() + ArgType.String, "output", "o", + "File path for the resulting human readable profile without wildcards" + ) + .required() + val programPaths by argument( + ArgType.String, + "program", + "File paths to program sources (.class or .jar). " + + "Class files must be on the form <src dir>:<path to file>.class, e.g., " + + "src:pkg/Main.class.") + .vararg() override fun execute() { - val hrpFile = File(hrpPath) + val hrpFile = Path(hrpPath).toFile() require(hrpFile.exists()) { "File not found: $hrpPath" } - val outFile = File(outPath) + val outFile = Path(outPath).toFile() require(outFile.parentFile.exists()) { "Directory does not exist: ${outFile.parent}" } - require(!programPaths.isEmpty()) { "Must pass at least one program source" } - val programFiles = programPaths.map { File(it) } - for (programFile in programFiles) { - require(programFile.exists()) { "File not found: $programFile" } - } + require(programPaths.isNotEmpty()) { "Must pass at least one program source" } val hrp = readHumanReadableProfileOrExit(hrpFile) val archiveClassFileResourceProviders = mutableListOf<ArchiveClassFileResourceProvider>() val classFileResources = mutableListOf<ClassFileResource>() - for (programFile in programFiles) { - if (programFile.toString().endsWith(CLASS_EXTENSION)) { - classFileResources += ClassFileResource(programFile.toPath()) - } else if (programFile.toString().endsWith(JAR_EXTENSION)) { + for (programPath in programPaths) { + if (programPath.endsWith(CLASS_EXTENSION)) { + val separatorIndex = programPath.lastIndexOf(':') + require(separatorIndex >= 0) { + "Missing ':' separator for class file: $programPath" + } + val classBinaryName = + programPath.substring(separatorIndex + 1).dropLast(CLASS_EXTENSION.length) + val classDescriptor = getClassDescriptorFromBinaryName(classBinaryName) + val programFile = + Path(programPath.substring(0, separatorIndex), "$classBinaryName.class") + .toFile() + require(programFile.exists()) { "File not found: $programFile" } + classFileResources += ClassFileResource(classDescriptor, programFile.toPath()) + } else if (programPath.endsWith(JAR_EXTENSION)) { + val programFile = Path(programPath).toFile() + require(programFile.exists()) { "File not found: $programPath" } val archiveClassFileResourceProvider = - ArchiveClassFileResourceProvider(programFile.toPath()) + ArchiveClassFileResourceProvider(programFile.toPath()) archiveClassFileResourceProviders += archiveClassFileResourceProvider classFileResources += archiveClassFileResourceProvider.getClassFileResources() } else { - throw IllegalArgumentException("Unexpected program file: $programFile") + throw IllegalArgumentException("Unexpected program file: $programPath") } } val result = hrp.expandWildcards(classFileResources) diff --git a/profgen/profgen-cli/src/main/kotlin/com/android/tools/profgen/cli/main.kt b/profgen/profgen-cli/src/main/kotlin/com/android/tools/profgen/cli/main.kt index f9e402b357..16a5f607a1 100644 --- a/profgen/profgen-cli/src/main/kotlin/com/android/tools/profgen/cli/main.kt +++ b/profgen/profgen-cli/src/main/kotlin/com/android/tools/profgen/cli/main.kt @@ -26,7 +26,8 @@ fun main(args: Array<String>) { BinCommand(), ValidateCommand(), ProfileDumpCommand(), - ExpandWildcardsCommand() + ExpandWildcardsCommand(), + ExtractProfileCommand(), ) parser.parse(args) } diff --git a/profgen/profgen-cli/src/test/kotlin/TestUtils.kt b/profgen/profgen-cli/src/test/kotlin/TestUtils.kt new file mode 100644 index 0000000000..46349cc2c6 --- /dev/null +++ b/profgen/profgen-cli/src/test/kotlin/TestUtils.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 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.tools.profgen.cli + +import com.android.testutils.TestUtils +import java.io.File +import java.nio.file.Path + +fun testData(relativePath: String): File { + return testDataPath(relativePath).toFile() +} +fun testDataPath(): Path { + return workspacePath("tools/base/profgen/profgen-cli/testData") +} + +fun testDataPath(relativePath: String): Path { + return testDataPath().resolve(relativePath) +} +fun workspacePath(relativePath: String): Path { + return TestUtils.resolveWorkspacePath(relativePath) +} diff --git a/profgen/profgen-cli/src/test/kotlin/ExpandWildcardsCommandTest.kt b/profgen/profgen-cli/src/test/kotlin/WildCardsCommandTest.kt index cae096a946..1f28caea2f 100644 --- a/profgen/profgen-cli/src/test/kotlin/ExpandWildcardsCommandTest.kt +++ b/profgen/profgen-cli/src/test/kotlin/WildCardsCommandTest.kt @@ -16,38 +16,42 @@ package com.android.tools.profgen.cli -import com.android.testutils.TestUtils import com.google.common.truth.Truth.assertThat -import kotlin.io.path.createTempFile import kotlinx.cli.ExperimentalCli import org.junit.Test +import kotlin.io.path.createTempFile @ExperimentalCli -class ExpandWildcardsCommandTest { +class WildCardsCommandTest { @Test - fun test() { + fun expandWildCardsTest() { val command = ExpandWildcardsCommand() - val profile = createTempFile(suffix=".txt").toFile() + val profile = createTempFile(suffix = ".txt").toFile() profile.writeText("L*;") - val output = createTempFile(suffix=".txt").toFile() + val output = createTempFile(suffix = ".txt").toFile() command.parse( arrayOf( "--profile", profile.toString(), "--output", output.toString(), - TestUtils.resolveWorkspacePath(ClassFilePath).toString(), - TestUtils.resolveWorkspacePath(JarArchivePath).toString())) + getClassFileArgument(), + testData(JarArchivePath).toString())) command.execute() assertThat(output.readText()).isEqualTo( - """ + """ LHello; LWorld; """.trimIndent().plus('\n') ) } + internal fun getClassFileArgument(): String { + val sourceDir = testDataPath() + return "$sourceDir:$ClassFilePath" + } companion object { - private const val ClassFilePath = "tools/base/profgen/profgen-cli/testData/Hello.class" - private const val JarArchivePath = "tools/base/profgen/profgen-cli/testData/world.jar" + + private const val ClassFilePath = "Hello.class" + private const val JarArchivePath = "world.jar" } } diff --git a/profgen/profgen/src/main/kotlin/com/android/tools/profgen/ArtProfileSerializer.kt b/profgen/profgen/src/main/kotlin/com/android/tools/profgen/ArtProfileSerializer.kt index 92a58ea0c9..18bf29961d 100644 --- a/profgen/profgen/src/main/kotlin/com/android/tools/profgen/ArtProfileSerializer.kt +++ b/profgen/profgen/src/main/kotlin/com/android/tools/profgen/ArtProfileSerializer.kt @@ -46,7 +46,8 @@ enum class MetadataVersion(internal val versionBytes: ByteArray) { enum class ArtProfileSerializer( internal val versionBytes: ByteArray, - internal val magicBytes: ByteArray = MAGIC + internal val magicBytes: ByteArray = MAGIC, + internal val metadataVersion: MetadataVersion? = null ) { /** @@ -516,7 +517,8 @@ enum class ArtProfileSerializer( */ METADATA_FOR_N( MetadataVersion.V_001.versionBytes, - byteArrayOf('p', 'r', 'm', '\u0000') + byteArrayOf('p', 'r', 'm', '\u0000'), + MetadataVersion.V_001 ) { override fun write( os: OutputStream, @@ -665,7 +667,8 @@ enum class ArtProfileSerializer( */ METADATA_0_0_2( MetadataVersion.V_002.versionBytes, - byteArrayOf('p', 'r', 'm', '\u0000') + byteArrayOf('p', 'r', 'm', '\u0000'), + MetadataVersion.V_002 ) { override fun write( @@ -1372,6 +1375,7 @@ enum class ArtProfileSerializer( internal abstract fun write(os: OutputStream, profileData: Map<DexFile, DexFileData>, apkName: String) internal abstract fun read(src: InputStream): Map<DexFile, DexFileData> internal abstract fun skipInlineCaches(src: InputStream) + internal fun InputStream.skipInlineCacheV015S() { /* val dexPc = */readUInt16() var dexPcMapSize = readUInt8() diff --git a/profgen/profgen/src/main/kotlin/com/android/tools/profgen/ClassFileResource.kt b/profgen/profgen/src/main/kotlin/com/android/tools/profgen/ClassFileResource.kt index ab81c7fd5c..d2e762840f 100644 --- a/profgen/profgen/src/main/kotlin/com/android/tools/profgen/ClassFileResource.kt +++ b/profgen/profgen/src/main/kotlin/com/android/tools/profgen/ClassFileResource.kt @@ -36,13 +36,19 @@ interface ClassFileResource { return it.readBytes() } } + + fun getClassDescriptor(): String } -fun ClassFileResource(classFile: Path): ClassFileResource { +fun ClassFileResource(classDescriptor: String, classFile: Path): ClassFileResource { return object : ClassFileResource { override fun getByteStream(): InputStream { return classFile.toFile().inputStream() } + + override fun getClassDescriptor(): String { + return classDescriptor + } } } @@ -60,10 +66,16 @@ class ArchiveClassFileResourceProvider ( while (zipEntries.hasMoreElements()) { val zipEntry = zipEntries.nextElement() if (isClassFile(zipEntry)) { + val classBinaryName = zipEntry.name.dropLast(CLASS_EXTENSION.length) + val classDescriptor = getClassDescriptorFromBinaryName(classBinaryName) val classFileResource = object : ClassFileResource { override fun getByteStream(): InputStream { return zipFile.getInputStream(zipEntry) } + + override fun getClassDescriptor(): String { + return classDescriptor + } } classFileResources.add(classFileResource) } @@ -76,8 +88,12 @@ class ArchiveClassFileResourceProvider ( } } +public fun getClassDescriptorFromBinaryName(classBinaryName: String): String { + return "L$classBinaryName;" +} + private fun isClassFile(zipEntry: ZipEntry): Boolean { - val name = zipEntry.getName().toLowerCase(Locale.getDefault()) + val name = zipEntry.name.toLowerCase(Locale.getDefault()) return name.endsWith(CLASS_EXTENSION) && !name.endsWith(MODULE_INFO_CLASS) && !name.startsWith("meta-inf") diff --git a/profgen/profgen/src/main/kotlin/com/android/tools/profgen/HumanReadableProfile.kt b/profgen/profgen/src/main/kotlin/com/android/tools/profgen/HumanReadableProfile.kt index d7fdcf19d1..fa6e743936 100644 --- a/profgen/profgen/src/main/kotlin/com/android/tools/profgen/HumanReadableProfile.kt +++ b/profgen/profgen/src/main/kotlin/com/android/tools/profgen/HumanReadableProfile.kt @@ -72,6 +72,10 @@ class HumanReadableProfile internal constructor( return flags } + private fun hasFuzzyMethods(classDescriptor: String): Boolean { + return fuzzyMethods.prefixIterator(classDescriptor).hasNext() + } + internal fun match(type: String): Int { if (type in exactTypes) { return MethodFlags.STARTUP @@ -93,48 +97,9 @@ class HumanReadableProfile internal constructor( val newExactTypes = mutableSetOf<String>() newExactTypes += exactTypes - val classVisitor = object : ClassVisitor(Opcodes.ASM9) { - private lateinit var classDescriptor: String - - override fun visit( - version: Int, - access: Int, - name: String, - signature: String?, - superName: String?, - interfaces: Array<String>?): Unit { - classDescriptor = "L$name;" - if (classDescriptor !in newExactTypes - && fuzzyMatch(classDescriptor) == MethodFlags.STARTUP) { - newExactTypes += classDescriptor - } - } - - override fun visitMethod( - access: Int, - name: String, - desc: String, - signature: String?, - exceptions: Array<String>?): MethodVisitor? { - val closeParenIndex = desc.indexOf(CLOSE_PAREN) - val parameters = desc.substring(1, closeParenIndex) - val returnTypeDescriptor = desc.substring(closeParenIndex + 1) - val method = DexMethod( - classDescriptor, - name, - DexPrototype(returnTypeDescriptor, splitParameters(parameters)) - ) - val flags = match(method) - if (flags != 0) { - newExactMethods[method] = flags - } - return null - } - } - val parsingOptions: Int = - ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES for (classFileResource in classFileResources) { - ClassReader(classFileResource.getBytes()).accept(classVisitor, parsingOptions) + expandWildcards( + classFileResource, classFileResource.getBytes(), newExactMethods, newExactTypes) } return HumanReadableProfile( @@ -145,6 +110,47 @@ class HumanReadableProfile internal constructor( ) } + private fun expandWildcards( + classFileResource: ClassFileResource, + classFileResourceData: ByteArray, + methods: MutableMap<DexMethod, Int>, + classes: MutableSet<String> + ) { + val classDescriptor = classFileResource.getClassDescriptor() + if (match(classDescriptor) == MethodFlags.STARTUP) { + classes.add(classDescriptor) + } + + if (hasFuzzyMethods(classDescriptor)) { + val classVisitor = object : ClassVisitor(Opcodes.ASM9) { + override fun visitMethod( + access: Int, + name: String, + desc: String, + signature: String?, + exceptions: Array<String>?, + ): MethodVisitor? { + val closeParenIndex = desc.indexOf(CLOSE_PAREN) + val parameters = desc.substring(1, closeParenIndex) + val returnTypeDescriptor = desc.substring(closeParenIndex + 1) + val method = DexMethod( + classDescriptor, + name, + DexPrototype(returnTypeDescriptor, splitParameters(parameters)) + ) + val flags = match(method) + if (flags != 0) { + methods[method] = flags + } + return null + } + } + val parsingOptions: Int = + ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES + ClassReader(classFileResourceData).accept(classVisitor, parsingOptions) + } + } + fun printExact(os: Appendable): Unit { val app = mutableMapOf<String, MutableList<DexMethod>>() for (classDescriptor in exactTypes) { diff --git a/profgen/profgen/src/main/kotlin/com/android/tools/profgen/ProfileExtractor.kt b/profgen/profgen/src/main/kotlin/com/android/tools/profgen/ProfileExtractor.kt new file mode 100644 index 0000000000..30d13e7987 --- /dev/null +++ b/profgen/profgen/src/main/kotlin/com/android/tools/profgen/ProfileExtractor.kt @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2022 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.tools.profgen + +import java.io.ByteArrayOutputStream +import java.io.File +import java.io.OutputStream +import java.util.zip.Deflater +import java.util.zip.ZipEntry +import java.util.zip.ZipFile +import java.util.zip.ZipOutputStream + +fun extractProfileAsDm( + apkFile: File, + profileSerializer: ArtProfileSerializer, + metadataSerializer: ArtProfileSerializer, + outputStream: OutputStream +) { + ZipFile(apkFile).use { zipFile -> + val profEntry = zipFile.entries() + .asSequence() + .firstOrNull { it.name == "assets/dexopt/baseline.prof" } + val profmEntry = zipFile.entries() + .asSequence() + .firstOrNull { it.name == "assets/dexopt/baseline.profm" } + + // Theoretically we could support if the output version matches current version, + // but this would complicate user experience, so we don't bother for now. + check(profEntry != null && profmEntry != null) { + "Apk must contain profile at assets/dexopt/baseline.prof " + + "and assets/dexopt/baseline.profm" + } + val profInputStream = zipFile.getInputStream(profEntry) + val profmInputStream = zipFile.getInputStream(profmEntry) + val prof = ArtProfile(profInputStream) + check(prof != null) { + "Unable to read profile from apk ${apkFile.absolutePath}" + } + + val profmVersion = profmInputStream.readProfileVersion() + check(profmVersion != null) { + "Unable to read profile metadata from apk ${apkFile.absolutePath}" + } + val metadata = ArtProfile(profmVersion.read(profmInputStream)).also { + prof.addMetadata(it, profmVersion.metadataVersion!!) + } + outputStream.writeDm(prof, metadata, profileSerializer, metadataSerializer) + } +} + +private fun ZipOutputStream.put(name: String, block: (OutputStream) -> Unit) { + putNextEntry(ZipEntry(name)) + val stream = ByteArrayOutputStream() + block(stream) + write(stream.toByteArray()) + closeEntry() +} + +private fun OutputStream.writeDm( + prof: ArtProfile, + profm: ArtProfile?, + profileVersion: ArtProfileSerializer, + metadataVersion: ArtProfileSerializer +) { + ZipOutputStream(this).use { + it.setLevel(Deflater.NO_COMPRESSION) + it.put("primary.prof") { zipFileOutStream -> + prof.save(zipFileOutStream, profileVersion) + } + profm?.apply { + it.put("primary.profm") { zipFileOutStream -> + save(zipFileOutStream, metadataVersion) + } + } + } +} diff --git a/profgen/profgen/src/test/kotlin/com/android/tools/profgen/ArtProfileTests.kt b/profgen/profgen/src/test/kotlin/com/android/tools/profgen/ArtProfileTests.kt index 1578c379af..d423d4c123 100644 --- a/profgen/profgen/src/test/kotlin/com/android/tools/profgen/ArtProfileTests.kt +++ b/profgen/profgen/src/test/kotlin/com/android/tools/profgen/ArtProfileTests.kt @@ -7,10 +7,18 @@ import java.io.File import java.io.InputStream import java.util.zip.CRC32 import java.util.zip.ZipFile +import java.util.zip.ZipInputStream +import kotlin.io.path.Path +import kotlin.io.path.copyTo +import kotlin.io.path.createTempFile +import kotlin.io.path.outputStream +import kotlin.test.assertContentEquals import kotlin.test.assertEquals +import kotlin.test.assertFailsWith import kotlin.test.assertFalse import kotlin.test.assertNotNull import kotlin.test.assertTrue +import kotlin.test.expect import kotlin.test.fail class ArtProfileTests { @@ -176,6 +184,59 @@ class ArtProfileTests { } } + /** + * Validates that two zip files are *content* equivalent, ignoring metadata like timestamps + */ + private fun validateZipContentEquals(expected: ZipFile, observed: ZipFile) { + fun ZipFile.getContents(): Map<String, ByteArray> = entries().asSequence().associate { + it.name to getInputStream(it).readBytes() + } + val exp = expected.getContents() + val obs = observed.getContents() + assertEquals(exp.keys.toSet(), obs.keys.toSet()) + exp.entries.sortedBy { it.key }.zip(obs.entries.sortedBy { it.key }).forEach { + assertEquals(it.first.key, it.second.key) + assertContentEquals(it.first.value, it.second.value) + } + } + + @Test + fun testExtractProfileAsDm() { + val golden = testData("now-in-android/b-227394536/app-release.dm") + val apkFile = testData("now-in-android/b-227394536/app-release.apk") + val output = createTempFile(suffix = ".dm") + + output.outputStream().use { + extractProfileAsDm( + apkFile = apkFile, + profileSerializer = ArtProfileSerializer.V0_1_5_S, + metadataSerializer = ArtProfileSerializer.METADATA_0_0_2, + outputStream = it + ) + } + validateZipContentEquals( + expected = ZipFile(golden), + observed = ZipFile(output.toFile()) + ) + } + + @Test + fun testExtractProfileAsDm_missing() { + // APK doesn't contain a profile, so will fail + val apkFile = testData("jetnews/app-release.apk") + val outS = ByteArrayOutputStream() + + val exception = assertFailsWith<IllegalStateException> { + extractProfileAsDm( + apkFile = apkFile, + profileSerializer = ArtProfileSerializer.V0_1_5_S, + metadataSerializer = ArtProfileSerializer.METADATA_0_0_2, + outputStream = outS + ) + } + assertTrue(exception.message!!.contains("Apk must contain profile")) + } + @Test fun testTranscodeFromPtoO() { val obf = ObfuscationMap(testData("mapping.txt")) diff --git a/profgen/profgen/src/test/kotlin/com/android/tools/profgen/WildcardExpansionTest.kt b/profgen/profgen/src/test/kotlin/com/android/tools/profgen/WildcardExpansionTest.kt index ac8165ba8b..abf16c2a53 100644 --- a/profgen/profgen/src/test/kotlin/com/android/tools/profgen/WildcardExpansionTest.kt +++ b/profgen/profgen/src/test/kotlin/com/android/tools/profgen/WildcardExpansionTest.kt @@ -16,7 +16,6 @@ package com.android.tools.profgen -import com.android.testutils.TestUtils import com.google.common.truth.Truth.assertThat import org.junit.Test import java.io.ByteArrayInputStream @@ -29,15 +28,15 @@ class WildcardExpansionTest { @Test fun testClassFile() { val classFileResource = object : ClassFileResource { - override fun getByteStream(): InputStream = - TestUtils.resolveWorkspacePath(ClassFilePath).toFile().inputStream() + override fun getByteStream(): InputStream = testData(ClassFilePath).inputStream() + override fun getClassDescriptor(): String = "LHello;" } runTests(listOf(classFileResource)) } @Test fun testJarArchive() { - val archive = TestUtils.resolveWorkspacePath(JarArchivePath) + val archive = testData(JarArchivePath).toPath() ArchiveClassFileResourceProvider(archive).use { runTests(it.getClassFileResources()) } @@ -88,7 +87,7 @@ class WildcardExpansionTest { } companion object { - private const val ClassFilePath = "tools/base/profgen/profgen/testData/Hello.class" - private const val JarArchivePath = "tools/base/profgen/profgen/testData/hello.jar" + private const val ClassFilePath = "Hello.class" + private const val JarArchivePath = "hello.jar" } } diff --git a/profgen/profgen/testData/now-in-android/b-227394536/app-release.dm b/profgen/profgen/testData/now-in-android/b-227394536/app-release.dm Binary files differnew file mode 100644 index 0000000000..01f50305b9 --- /dev/null +++ b/profgen/profgen/testData/now-in-android/b-227394536/app-release.dm diff --git a/sdk-common/src/main/java/com/android/ide/common/gradle/Component.kt b/sdk-common/src/main/java/com/android/ide/common/gradle/Component.kt new file mode 100644 index 0000000000..0c328efa39 --- /dev/null +++ b/sdk-common/src/main/java/com/android/ide/common/gradle/Component.kt @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2023 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.ide.common.gradle + +data class Component( + val module: Module, + val version: Version, +) { + constructor(group: String, name: String, version: Version): this(Module(group, name), version) + val group get() = module.group + val name get() = module.name + + override fun toString() = when(val id = toIdentifier()) { + is String -> id + else -> "Component(module=$module, version=$version)" + } + /** + * Return a string that will produce the same [Component] when parsed, or `null` + * if no such identifier exists. + */ + fun toIdentifier() = module.toIdentifier()?.let { moduleIdentifier -> + when { + !version.isPrefixInfimum -> "$moduleIdentifier:$version" + else -> null + } + } + + companion object { + /** + * Parse a string with two or more colon (':') characters as a [Component], where the + * first colon terminates the group of a [Module]; the second colon terminates the name + * of the [Module]; and the remainder of the string is parsed as a [Version]. If the + * string has fewer than two colons, return `null`. + */ + fun tryParse(string: String): Component? = string + .takeIf { s -> s.count { it == ':' } > 1 } + ?.run { + val firstColonIndex = indexOf(':') + val secondColonIndex = indexOf(':', startIndex = 1 + firstColonIndex) + Component( + Module.parse(substring(0, secondColonIndex)), + Version.parse(substring(1 + secondColonIndex)) + ) + } + + /** + * Attempt to parse a string as a [Component] using [tryParse]; if parsing fails, throw + * an [IllegalArgumentException]. + * + * @throws IllegalArgumentException + */ + fun parse(string: String): Component = + tryParse(string) ?: throw IllegalArgumentException("Invalid component: `$string`") + } +} diff --git a/sdk-common/src/main/java/com/android/ide/common/gradle/Module.kt b/sdk-common/src/main/java/com/android/ide/common/gradle/Module.kt new file mode 100644 index 0000000000..bda669343d --- /dev/null +++ b/sdk-common/src/main/java/com/android/ide/common/gradle/Module.kt @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2023 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.ide.common.gradle + +data class Module( + val group: String, + val name: String, +) { + override fun toString() = when(val id = toIdentifier()) { + is String -> id + else -> "Module(group=$group, name=$name)" + } + /** + * Return a string that will produce the same [Module] when parsed, or `null` + * if no such identifier exists. + */ + fun toIdentifier() = when { + !group.contains(':') && !name.contains(':') -> "${group}:${name}" + else -> null + } + + companion object { + /** + * Parse a string with exactly 1 colon (':') character as a [Module], where the colon + * separates the group from the name. If the string has zero, or more than one, colon, + * return `null`. + */ + fun tryParse(string: String) = string + .takeIf { s -> s.count { it == ':' } == 1 } + ?.run { Module(substring(0, indexOf(':')), substring(indexOf(':') + 1)) } + + /** + * Attempt to parse a string as a [Module] using [tryParse]. If parsing fails, throw + * an [IllegalArgumentException]. + * + * @throws IllegalArgumentException + */ + fun parse(string: String): Module = + tryParse(string) ?: throw IllegalArgumentException("Invalid module: `$string`") + } +} + diff --git a/sdk-common/src/main/java/com/android/ide/common/gradle/Version.kt b/sdk-common/src/main/java/com/android/ide/common/gradle/Version.kt index 512adfcba7..99b865514c 100644 --- a/sdk-common/src/main/java/com/android/ide/common/gradle/Version.kt +++ b/sdk-common/src/main/java/com/android/ide/common/gradle/Version.kt @@ -65,7 +65,7 @@ class Version: Comparable<Version> { // This is a reasonably well-defined concept. val isPreview - get() = parts.any { it !is Numeric } || isPrefixInfimum + get() = parts.any { it !is Numeric } // This is not very well-defined: // - why is SNAPSHOT special, compared with all the other Special components? // - we check only check the last part because this is what the GradleVersion class did diff --git a/sdk-common/src/main/java/com/android/ide/common/rendering/HardwareConfigHelper.java b/sdk-common/src/main/java/com/android/ide/common/rendering/HardwareConfigHelper.java index 9e430b48cb..bcc2f39108 100644 --- a/sdk-common/src/main/java/com/android/ide/common/rendering/HardwareConfigHelper.java +++ b/sdk-common/src/main/java/com/android/ide/common/rendering/HardwareConfigHelper.java @@ -204,8 +204,8 @@ public class HardwareConfigHelper { String name = device.getDisplayName(); if (isTv(device)) { // Example: 1080p, 1920x1080, xhdpi (TV) - if (name.startsWith("Android TV (")) { - name = name.substring("Android TV (".length()); + if (name.startsWith("Television (")) { + name = name.substring("Television (".length()); if (name.endsWith(")")) { name = name.substring(0, name.length() - 1); } @@ -317,7 +317,9 @@ public class HardwareConfigHelper { * Whether the given device is a TV device */ public static boolean isTv(@Nullable Device device) { - return device != null && "android-tv".equals(device.getTagId()); + return device != null + && ("android-tv".equals(device.getTagId()) + || "google-tv".equals(device.getTagId())); } /** Whether the given device is an Automotive device */ diff --git a/sdk-common/src/main/java/com/android/ide/common/repository/GradleCoordinate.java b/sdk-common/src/main/java/com/android/ide/common/repository/GradleCoordinate.java index 5863036d04..f17f2c0cff 100644 --- a/sdk-common/src/main/java/com/android/ide/common/repository/GradleCoordinate.java +++ b/sdk-common/src/main/java/com/android/ide/common/repository/GradleCoordinate.java @@ -15,10 +15,11 @@ */ package com.android.ide.common.repository; -import static com.android.ide.common.repository.KnownVersionStabilityKt.stabilityOf; +import static com.android.ide.common.repository.KnownVersionStabilityKt.getStability; import com.android.annotations.NonNull; import com.android.annotations.Nullable; +import com.android.ide.common.gradle.Component; import com.android.ide.common.gradle.Version; import com.android.ide.common.gradle.VersionRange; import com.google.common.base.Joiner; @@ -581,14 +582,15 @@ public final class GradleCoordinate { } /** Returns the dependency version range of this coordinate */ - @Nullable + @NonNull public VersionRange getVersionRange() { String revision = getRevision(); if (acceptsGreaterRevisions()) { return VersionRange.Companion.parse(revision); } else { - KnownVersionStability stability = stabilityOf(mGroupId, mArtifactId, revision); Version version = Version.Companion.parse(getRevision()); + Component component = new Component(mGroupId, mArtifactId, version); + KnownVersionStability stability = getStability(component); // this is [version,expiration), where stability.expiration(...) has computed the // appropriate prefixInfimum for the maven-style upper bound. return new VersionRange(Range.closedOpen(version, stability.expiration(version))); diff --git a/sdk-common/src/main/java/com/android/ide/common/repository/KnownVersionStability.kt b/sdk-common/src/main/java/com/android/ide/common/repository/KnownVersionStability.kt index fa45e52813..b1f9e555aa 100644 --- a/sdk-common/src/main/java/com/android/ide/common/repository/KnownVersionStability.kt +++ b/sdk-common/src/main/java/com/android/ide/common/repository/KnownVersionStability.kt @@ -18,6 +18,7 @@ package com.android.ide.common.repository import com.android.SdkConstants.ANNOTATIONS_LIB_ARTIFACT_ID import com.android.SdkConstants.MATERIAL2_PKG import com.android.SdkConstants.SUPPORT_LIB_GROUP_ID +import com.android.ide.common.gradle.Component import com.android.ide.common.gradle.Version import com.android.ide.common.gradle.VersionRange @@ -80,20 +81,25 @@ enum class KnownVersionStability { } } +val Component.stability get() = when { + group == KOTLIN_GROUP_ID -> kotlinStabilityOf(name) + group == GOOGLE_MOBILE_SERVICES_GROUP_ID -> gmsAndFirebaseStability(version) + group == FIREBASE_GROUP_ID -> gmsAndFirebaseStability(version) + group == MATERIAL2_PKG -> KnownVersionStability.SEMANTIC + group == SUPPORT_LIB_GROUP_ID -> supportLibStability(name) + MavenRepositories.isAndroidX(group) -> KnownVersionStability.SEMANTIC + else -> KnownVersionStability.INCOMPATIBLE +} + +@Deprecated( + "replace with Component.stability", + ReplaceWith("Component(groupId, artifactId, Version.parse(revision)).stability") +) fun stabilityOf( groupId: String, artifactId: String, revision: String = "1.0.0" -): KnownVersionStability = - when { - groupId == KOTLIN_GROUP_ID -> kotlinStabilityOf(artifactId) - groupId == GOOGLE_MOBILE_SERVICES_GROUP_ID -> gmsAndFirebaseStability(revision) - groupId == FIREBASE_GROUP_ID -> gmsAndFirebaseStability(revision) - groupId == MATERIAL2_PKG -> KnownVersionStability.SEMANTIC - groupId == SUPPORT_LIB_GROUP_ID -> supportLibStability(artifactId) - MavenRepositories.isAndroidX(groupId) -> KnownVersionStability.SEMANTIC - else -> KnownVersionStability.INCOMPATIBLE - } +): KnownVersionStability = Component(groupId, artifactId, Version.parse(revision)).stability private fun kotlinStabilityOf(artifactId: String): KnownVersionStability = when (artifactId) { @@ -108,14 +114,16 @@ private fun kotlinStabilityOf(artifactId: String): KnownVersionStability = else -> KnownVersionStability.INCOMPATIBLE } -private fun gmsAndFirebaseStability(revision: String): KnownVersionStability { - val version = GradleVersion.tryParse(revision) - return if (version != null && version.major >= GMS_AND_FIREBASE_SEMANTIC_START) - KnownVersionStability.SEMANTIC - else - KnownVersionStability.INCOMPATIBLE +private fun gmsAndFirebaseStability(version: Version): KnownVersionStability { + val major = version.major + return when { + major == null -> KnownVersionStability.INCOMPATIBLE + major >= GMS_AND_FIREBASE_SEMANTIC_START -> KnownVersionStability.SEMANTIC + else -> KnownVersionStability.INCOMPATIBLE + } } + /** * Stability of legacy support libraries. * diff --git a/sdk-common/src/main/java/com/android/ide/common/repository/SdkMavenRepository.java b/sdk-common/src/main/java/com/android/ide/common/repository/SdkMavenRepository.java index 236b803e36..4e3e042b30 100644 --- a/sdk-common/src/main/java/com/android/ide/common/repository/SdkMavenRepository.java +++ b/sdk-common/src/main/java/com/android/ide/common/repository/SdkMavenRepository.java @@ -35,6 +35,7 @@ import com.android.sdklib.repository.meta.DetailsTypes; import com.google.common.collect.Lists; import java.nio.file.Path; import java.util.Collection; +import java.util.Comparator; import java.util.List; import java.util.function.Predicate; @@ -214,8 +215,11 @@ public enum SdkMavenRepository { Predicate<Revision> revisionFilter = filter == null ? null : (revision) -> filter.test(revisionToVersion(revision)); return sdkHandler.getLatestLocalPackageForPrefix( - prefix, revisionFilter, coordinate.isPreview(), GradleCoordinate::parseVersionOnly, - GradleCoordinate.COMPARE_PLUS_LOWER, progress); + prefix, + revisionFilter, + coordinate.isPreview(), + Version.Companion::parse, + progress); } @NonNull @@ -236,8 +240,11 @@ public enum SdkMavenRepository { Predicate<Revision> revisionFilter = filter == null ? null : (revision) -> filter.test(revisionToVersion(revision)); return sdkHandler.getLatestRemotePackageForPrefix( - prefix, revisionFilter, coordinate.isPreview(), - GradleCoordinate::parseVersionOnly, GradleCoordinate.COMPARE_PLUS_LOWER, progress); + prefix, + revisionFilter, + coordinate.isPreview(), + Version.Companion::parse, + progress); } /** diff --git a/sdk-common/src/main/java/com/android/ide/common/resources/ResourceResolver.java b/sdk-common/src/main/java/com/android/ide/common/resources/ResourceResolver.java index da7c632942..17cf5f2fc8 100644 --- a/sdk-common/src/main/java/com/android/ide/common/resources/ResourceResolver.java +++ b/sdk-common/src/main/java/com/android/ide/common/resources/ResourceResolver.java @@ -38,7 +38,9 @@ import com.android.resources.ResourceUrl; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; import com.google.common.base.Strings; +import com.google.common.collect.ForwardingList; import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; import java.util.Arrays; @@ -158,7 +160,10 @@ public class ResourceResolver extends RenderResources { resolver.mLogger = original.mLogger; resolver.mStyleInheritanceMap.putAll(original.mStyleInheritanceMap); resolver.mReverseStyleInheritanceMap.putAll(original.mReverseStyleInheritanceMap); - resolver.mThemes.addAll(original.mThemes); + List<StyleResourceValue> originalThemes = original.getAllThemes(); + synchronized (resolver.mThemes) { + resolver.mThemes.addAll(originalThemes); + } return resolver; } @@ -301,25 +306,52 @@ public class ResourceResolver extends RenderResources { if (theme == null) { return; } - if (useAsPrimary) { - mThemes.add(0, theme); - } else { - mThemes.add(theme); + synchronized (mThemes) { + if (useAsPrimary) { + mThemes.add(0, theme); + } else { + mThemes.add(theme); + } + } + } + + @Override + public void clearAllThemes() { + synchronized (mThemes) { + mThemes.clear(); } } @Override public void clearStyles() { - mThemes.clear(); - if (mDefaultTheme != null) { - mThemes.add(mDefaultTheme); + synchronized (mThemes) { + mThemes.clear(); + if (mDefaultTheme != null) { + mThemes.add(mDefaultTheme); + } } } @Override @NonNull public List<StyleResourceValue> getAllThemes() { - return mThemes; + synchronized (mThemes) { + // Layoutlib calls getAllThemes().clear() to ensure all the themes + // all cleared. The new method clearAllThemes will replace this ForwardingList + // that is currently a workaround to allow for that use case. + return new ForwardingList<StyleResourceValue>() { + + @Override + protected List<StyleResourceValue> delegate() { + return ImmutableList.copyOf(mThemes); + } + + @Override + public void clear() { + clearAllThemes(); + } + }; + } } /** @@ -751,7 +783,10 @@ public class ResourceResolver extends RenderResources { new RecordingResourceResolver(lookupChain, mResources, mDefaultTheme); resolver.mLogger = mLogger; resolver.mStyleInheritanceMap.putAll(mStyleInheritanceMap); - resolver.mThemes.addAll(mThemes); + List<StyleResourceValue> originalThemes = getAllThemes(); + synchronized (resolver.mThemes) { + resolver.mThemes.addAll(originalThemes); + } return resolver; } diff --git a/sdk-common/src/main/resources/versions-offline/androidx/activity/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/activity/group-index.xml index a4fb5db218..c048d2b7d8 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/activity/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/activity/group-index.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.activity> - <activity versions="1.4.0,1.6.0-alpha01"/> - <activity-compose versions="1.4.0,1.6.0-alpha01"/> - <activity-ktx versions="1.4.0,1.6.0-alpha01"/> + <activity versions="1.7.0,1.8.0-alpha02"/> + <activity-compose versions="1.7.0,1.8.0-alpha02"/> + <activity-ktx versions="1.7.0,1.8.0-alpha02"/> </androidx.activity> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/ads/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/ads/group-index.xml index d85dbfb96b..266dcd8492 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/ads/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/ads/group-index.xml @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="UTF-8"?> +<?xml version='1.0' encoding='UTF-8'?> <androidx.ads> - <ads-identifier versions="1.0.0-alpha04"/> - <ads-identifier-common versions="1.0.0-alpha04"/> - <ads-identifier-provider versions="1.0.0-alpha04"/> + <ads-identifier versions="1.0.0-alpha05"/> + <ads-identifier-common versions="1.0.0-alpha05"/> + <ads-identifier-provider versions="1.0.0-alpha05"/> </androidx.ads> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/annotation/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/annotation/group-index.xml index daaa592c3f..b5cbd5385e 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/annotation/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/annotation/group-index.xml @@ -1,7 +1,14 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.annotation> - <annotation versions="1.3.0,1.4.0-alpha02"/> - <annotation-experimental versions="1.2.0"/> + <annotation versions="1.6.0,1.7.0-alpha02"/> + <annotation-experimental versions="1.3.0,1.4.0-dev01"/> <annotation-experimental-lint versions="1.0.0"/> + <annotation-iosarm64 versions="1.7.0-alpha02"/> + <annotation-iossimulatorarm64 versions="1.7.0-alpha02"/> + <annotation-iosx64 versions="1.7.0-alpha02"/> + <annotation-jvm versions="1.6.0,1.7.0-alpha02"/> + <annotation-linuxx64 versions="1.7.0-alpha02"/> + <annotation-macosarm64 versions="1.7.0-alpha02"/> + <annotation-macosx64 versions="1.7.0-alpha02"/> </androidx.annotation> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/appcompat/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/appcompat/group-index.xml index 5902badf6e..93e8c9fa3d 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/appcompat/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/appcompat/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.appcompat> - <appcompat versions="1.4.1,1.6.0-alpha01"/> - <appcompat-resources versions="1.4.1,1.6.0-alpha01"/> + <appcompat versions="1.6.1,1.7.0-alpha02"/> + <appcompat-resources versions="1.6.1,1.7.0-alpha02"/> </androidx.appcompat> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/appsearch/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/appsearch/group-index.xml index 39f92f4cee..0092b61ee1 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/appsearch/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/appsearch/group-index.xml @@ -1,8 +1,9 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.appsearch> - <appsearch versions="1.0.0-alpha04"/> - <appsearch-compiler versions="1.0.0-alpha04"/> - <appsearch-local-storage versions="1.0.0-alpha04"/> - <appsearch-platform-storage versions="1.0.0-alpha04"/> + <appsearch versions="1.1.0-alpha02"/> + <appsearch-builtin-types versions="1.1.0-alpha02"/> + <appsearch-compiler versions="1.1.0-alpha02"/> + <appsearch-local-storage versions="1.1.0-alpha02"/> + <appsearch-platform-storage versions="1.1.0-alpha02"/> </androidx.appsearch> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/arch/core/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/arch/core/group-index.xml index ad7797fdac..538a59a264 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/arch/core/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/arch/core/group-index.xml @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="UTF-8"?> +<?xml version='1.0' encoding='UTF-8'?> <androidx.arch.core> - <core-common versions="2.1.0"/> - <core-runtime versions="2.1.0"/> - <core-testing versions="2.1.0"/> + <core-common versions="2.2.0"/> + <core-runtime versions="2.2.0"/> + <core-testing versions="2.2.0"/> </androidx.arch.core> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/asynclayoutinflater/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/asynclayoutinflater/group-index.xml index 87ee5febb1..2845d37136 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/asynclayoutinflater/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/asynclayoutinflater/group-index.xml @@ -1,5 +1,6 @@ -<?xml version="1.0" encoding="UTF-8"?> +<?xml version='1.0' encoding='UTF-8'?> <androidx.asynclayoutinflater> - <asynclayoutinflater versions="1.0.0"/> + <asynclayoutinflater versions="1.0.0,1.1.0-alpha01"/> + <asynclayoutinflater-appcompat versions="1.1.0-alpha01"/> </androidx.asynclayoutinflater> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/baselineprofile/apptarget/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/baselineprofile/apptarget/group-index.xml new file mode 100644 index 0000000000..fb44facd53 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/baselineprofile/apptarget/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.baselineprofile.apptarget> + <androidx.baselineprofile.apptarget.gradle.plugin versions="1.2.0-alpha12"/> +</androidx.baselineprofile.apptarget> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/baselineprofile/consumer/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/baselineprofile/consumer/group-index.xml new file mode 100644 index 0000000000..314fe53c77 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/baselineprofile/consumer/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.baselineprofile.consumer> + <androidx.baselineprofile.consumer.gradle.plugin versions="1.2.0-alpha12"/> +</androidx.baselineprofile.consumer> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/baselineprofile/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/baselineprofile/group-index.xml new file mode 100644 index 0000000000..fd727a2eaa --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/baselineprofile/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.baselineprofile> + <androidx.baselineprofile.gradle.plugin versions="1.2.0-alpha12"/> +</androidx.baselineprofile> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/baselineprofile/producer/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/baselineprofile/producer/group-index.xml new file mode 100644 index 0000000000..b4d871e293 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/baselineprofile/producer/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.baselineprofile.producer> + <androidx.baselineprofile.producer.gradle.plugin versions="1.2.0-alpha12"/> +</androidx.baselineprofile.producer> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/benchmark/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/benchmark/group-index.xml index 9174bbf889..d1c5785f99 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/benchmark/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/benchmark/group-index.xml @@ -1,11 +1,12 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.benchmark> - <androidx.benchmark.gradle.plugin versions="1.1.0-beta05"/> + <androidx.benchmark.gradle.plugin versions="1.1.1,1.2.0-alpha12"/> <benchmark versions="1.0.0-alpha03"/> - <benchmark-common versions="1.0.0,1.1.0-beta05"/> - <benchmark-gradle-plugin versions="1.0.0,1.1.0-beta05"/> - <benchmark-junit4 versions="1.0.0,1.1.0-beta05"/> - <benchmark-macro versions="1.1.0-beta05"/> - <benchmark-macro-junit4 versions="1.1.0-beta05"/> + <benchmark-baseline-profile-gradle-plugin versions="1.2.0-alpha12"/> + <benchmark-common versions="1.1.1,1.2.0-alpha12"/> + <benchmark-gradle-plugin versions="1.1.1,1.2.0-alpha12"/> + <benchmark-junit4 versions="1.1.1,1.2.0-alpha12"/> + <benchmark-macro versions="1.1.1,1.2.0-alpha12"/> + <benchmark-macro-junit4 versions="1.1.1,1.2.0-alpha12"/> </androidx.benchmark> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/biometric/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/biometric/group-index.xml index 0508f1aed1..e82ccd66ea 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/biometric/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/biometric/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.biometric> - <biometric versions="1.1.0,1.2.0-alpha04"/> - <biometric-ktx versions="1.2.0-alpha04"/> + <biometric versions="1.1.0,1.2.0-alpha05"/> + <biometric-ktx versions="1.2.0-alpha05"/> </androidx.biometric> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/browser/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/browser/group-index.xml index 1de2c3bde0..15470f146d 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/browser/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/browser/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.browser> - <browser versions="1.4.0"/> + <browser versions="1.5.0"/> </androidx.browser> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/camera/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/camera/group-index.xml index 61e5bd4e35..4581441b8c 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/camera/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/camera/group-index.xml @@ -1,10 +1,12 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.camera> - <camera-camera2 versions="1.0.2,1.1.0-beta02"/> - <camera-core versions="1.0.2,1.1.0-beta02"/> - <camera-extensions versions="1.1.0-beta02"/> - <camera-lifecycle versions="1.0.2,1.1.0-beta02"/> - <camera-video versions="1.1.0-beta02"/> - <camera-view versions="1.1.0-beta02"/> + <camera-camera2 versions="1.2.2,1.3.0-alpha05"/> + <camera-core versions="1.2.2,1.3.0-alpha05"/> + <camera-extensions versions="1.2.2,1.3.0-alpha05"/> + <camera-lifecycle versions="1.2.2,1.3.0-alpha05"/> + <camera-mlkit-vision versions="1.3.0-alpha05"/> + <camera-video versions="1.2.2,1.3.0-alpha05"/> + <camera-view versions="1.2.2,1.3.0-alpha05"/> + <camera-viewfinder versions="1.3.0-alpha05"/> </androidx.camera> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/car/app/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/car/app/group-index.xml index 58d575b270..408c765cf5 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/car/app/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/car/app/group-index.xml @@ -1,8 +1,8 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.car.app> - <app versions="1.1.0,1.2.0-rc01"/> - <app-automotive versions="1.1.0,1.2.0-rc01"/> - <app-projected versions="1.1.0,1.2.0-rc01"/> - <app-testing versions="1.1.0,1.2.0-rc01"/> + <app versions="1.2.0,1.4.0-alpha01"/> + <app-automotive versions="1.2.0,1.4.0-alpha01"/> + <app-projected versions="1.2.0,1.4.0-alpha01"/> + <app-testing versions="1.2.0,1.4.0-alpha01"/> </androidx.car.app> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/collection/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/collection/group-index.xml index 127c334c1a..3ea8f252ba 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/collection/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/collection/group-index.xml @@ -1,6 +1,13 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.collection> - <collection versions="1.2.0"/> - <collection-ktx versions="1.2.0"/> + <collection versions="1.2.0,1.3.0-alpha04"/> + <collection-iosarm64 versions="1.3.0-alpha04"/> + <collection-iossimulatorarm64 versions="1.3.0-alpha04"/> + <collection-iosx64 versions="1.3.0-alpha04"/> + <collection-jvm versions="1.3.0-alpha04"/> + <collection-ktx versions="1.2.0,1.3.0-alpha04"/> + <collection-linuxx64 versions="1.3.0-alpha04"/> + <collection-macosarm64 versions="1.3.0-alpha04"/> + <collection-macosx64 versions="1.3.0-alpha04"/> </androidx.collection> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/compose/animation/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/compose/animation/group-index.xml index 4706650110..1dcc1070a3 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/compose/animation/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/compose/animation/group-index.xml @@ -1,7 +1,8 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.compose.animation> - <animation versions="1.1.1,1.2.0-alpha06"/> - <animation-core versions="1.1.1,1.2.0-alpha06"/> - <animation-graphics versions="1.1.1,1.2.0-alpha06"/> + <animation versions="1.4.0,1.5.0-alpha01"/> + <animation-core versions="1.4.0,1.5.0-alpha01"/> + <animation-graphics versions="1.4.0,1.5.0-alpha01"/> + <animation-tooling-internal versions="1.5.0-alpha01"/> </androidx.compose.animation> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/compose/compiler/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/compose/compiler/group-index.xml index 40c1b80304..077621f2c6 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/compose/compiler/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/compose/compiler/group-index.xml @@ -1,5 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.compose.compiler> - <compiler versions="1.1.1,1.2.0-alpha06"/> + <compiler versions="1.4.4"/> + <compiler-daemon versions="1.4.4"/> + <compiler-hosted versions="1.4.4"/> </androidx.compose.compiler> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/compose/foundation/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/compose/foundation/group-index.xml index ed286a7fe5..60733ea778 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/compose/foundation/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/compose/foundation/group-index.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.compose.foundation> - <foundation versions="1.1.1,1.2.0-alpha06"/> - <foundation-layout versions="1.1.1,1.2.0-alpha06"/> + <foundation versions="1.4.0,1.5.0-alpha01"/> + <foundation-layout versions="1.4.0,1.5.0-alpha01"/> <foundation-text versions="1.0.0-alpha07"/> </androidx.compose.foundation> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/compose/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/compose/group-index.xml index 2df6b88f62..9c114c3b80 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/compose/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/compose/group-index.xml @@ -1,5 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.compose> + <compose-bom versions="2022.12.00,2023.03.00"/> <compose-compiler versions="1.0.0-alpha03"/> <compose-runtime versions="0.1.0-dev14"/> </androidx.compose> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/compose/material/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/compose/material/group-index.xml index 300139dbd6..c07f1b1040 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/compose/material/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/compose/material/group-index.xml @@ -1,8 +1,8 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.compose.material> - <material versions="1.1.1,1.2.0-alpha06"/> - <material-icons-core versions="1.1.1,1.2.0-alpha06"/> - <material-icons-extended versions="1.1.1,1.2.0-alpha06"/> - <material-ripple versions="1.1.1,1.2.0-alpha06"/> + <material versions="1.4.0,1.5.0-alpha01"/> + <material-icons-core versions="1.4.0,1.5.0-alpha01"/> + <material-icons-extended versions="1.4.0,1.5.0-alpha01"/> + <material-ripple versions="1.4.0,1.5.0-alpha01"/> </androidx.compose.material> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/compose/material3/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/compose/material3/group-index.xml index f58768fc4a..f158ad9e49 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/compose/material3/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/compose/material3/group-index.xml @@ -1,5 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.compose.material3> - <material3 versions="1.0.0-alpha08"/> + <material3 versions="1.0.1,1.1.0-beta01"/> + <material3-window-size-class versions="1.0.1,1.1.0-beta01"/> </androidx.compose.material3> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/compose/runtime/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/compose/runtime/group-index.xml index 0f76c288fa..dc3a65c78e 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/compose/runtime/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/compose/runtime/group-index.xml @@ -1,11 +1,12 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.compose.runtime> - <runtime versions="1.1.1,1.2.0-alpha06"/> + <runtime versions="1.4.0,1.5.0-alpha01"/> <runtime-dispatch versions="1.0.0-alpha12"/> - <runtime-livedata versions="1.1.1,1.2.0-alpha06"/> - <runtime-rxjava2 versions="1.1.1,1.2.0-alpha06"/> - <runtime-rxjava3 versions="1.1.1,1.2.0-alpha06"/> - <runtime-saveable versions="1.1.1,1.2.0-alpha06"/> + <runtime-livedata versions="1.4.0,1.5.0-alpha01"/> + <runtime-rxjava2 versions="1.4.0,1.5.0-alpha01"/> + <runtime-rxjava3 versions="1.4.0,1.5.0-alpha01"/> + <runtime-saveable versions="1.4.0,1.5.0-alpha01"/> <runtime-saved-instance-state versions="1.0.0-alpha11"/> + <runtime-tracing versions="1.0.0-alpha03"/> </androidx.compose.runtime> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/compose/ui/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/compose/ui/group-index.xml index ad65089adf..0eb5232063 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/compose/ui/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/compose/ui/group-index.xml @@ -1,19 +1,20 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.compose.ui> - <ui versions="1.1.1,1.2.0-alpha06"/> - <ui-geometry versions="1.1.1,1.2.0-alpha06"/> - <ui-graphics versions="1.1.1,1.2.0-alpha06"/> - <ui-test versions="1.1.1,1.2.0-alpha06"/> - <ui-test-junit4 versions="1.1.1,1.2.0-alpha06"/> - <ui-test-manifest versions="1.1.1,1.2.0-alpha06"/> - <ui-text versions="1.1.1,1.2.0-alpha06"/> + <ui versions="1.4.0,1.5.0-alpha01"/> + <ui-android-stubs versions="1.5.0-alpha01"/> + <ui-geometry versions="1.4.0,1.5.0-alpha01"/> + <ui-graphics versions="1.4.0,1.5.0-alpha01"/> + <ui-test versions="1.4.0,1.5.0-alpha01"/> + <ui-test-junit4 versions="1.4.0,1.5.0-alpha01"/> + <ui-test-manifest versions="1.4.0,1.5.0-alpha01"/> + <ui-text versions="1.4.0,1.5.0-alpha01"/> <ui-text-android versions="1.0.0-alpha06"/> - <ui-text-google-fonts versions="1.2.0-alpha06"/> - <ui-tooling versions="1.1.1,1.2.0-alpha06"/> - <ui-tooling-data versions="1.1.1,1.2.0-alpha06"/> - <ui-tooling-preview versions="1.1.1,1.2.0-alpha06"/> - <ui-unit versions="1.1.1,1.2.0-alpha06"/> - <ui-util versions="1.1.1,1.2.0-alpha06"/> - <ui-viewbinding versions="1.1.1,1.2.0-alpha06"/> + <ui-text-google-fonts versions="1.4.0,1.5.0-alpha01"/> + <ui-tooling versions="1.4.0,1.5.0-alpha01"/> + <ui-tooling-data versions="1.4.0,1.5.0-alpha01"/> + <ui-tooling-preview versions="1.4.0,1.5.0-alpha01"/> + <ui-unit versions="1.4.0,1.5.0-alpha01"/> + <ui-util versions="1.4.0,1.5.0-alpha01"/> + <ui-viewbinding versions="1.4.0,1.5.0-alpha01"/> </androidx.compose.ui> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/concurrent/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/concurrent/group-index.xml index a0c718aaec..509990aac8 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/concurrent/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/concurrent/group-index.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.concurrent> - <concurrent-futures versions="1.1.0"/> - <concurrent-futures-ktx versions="1.1.0"/> + <concurrent-futures versions="1.1.0,1.2.0-alpha01"/> + <concurrent-futures-ktx versions="1.1.0,1.2.0-alpha01"/> <concurrent-listenablefuture versions="1.0.0-beta01"/> <concurrent-listenablefuture-callback versions="1.0.0-beta01"/> <futures versions="1.0.0-alpha01"/> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/constraintlayout/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/constraintlayout/group-index.xml index 5fff7bff87..da7a99fa6d 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/constraintlayout/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/constraintlayout/group-index.xml @@ -1,8 +1,8 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.constraintlayout> - <constraintlayout versions="1.1.3,2.1.3"/> - <constraintlayout-compose versions="1.0.0"/> - <constraintlayout-core versions="1.0.3"/> + <constraintlayout versions="1.1.3,2.1.4,2.2.0-alpha09"/> + <constraintlayout-compose versions="1.0.1,1.1.0-alpha09"/> + <constraintlayout-core versions="1.0.4,1.1.0-alpha09"/> <constraintlayout-solver versions="1.1.3,2.0.4"/> </androidx.constraintlayout> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/core/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/core/group-index.xml index 0e76aa2680..2cb632c1f0 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/core/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/core/group-index.xml @@ -1,13 +1,13 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.core> - <core versions="1.7.0,1.9.0-alpha02"/> - <core-animation versions="1.0.0-alpha02"/> + <core versions="1.9.0,1.12.0-alpha01"/> + <core-animation versions="1.0.0-beta01"/> <core-animation-testing versions="1.0.0-alpha02"/> - <core-google-shortcuts versions="1.0.0,1.1.0-alpha01"/> - <core-ktx versions="0.3,1.7.0,1.9.0-alpha02"/> + <core-google-shortcuts versions="1.1.0"/> + <core-ktx versions="0.3,1.9.0,1.12.0-alpha01"/> <core-performance versions="1.0.0-alpha02"/> - <core-remoteviews versions="1.0.0-alpha03"/> + <core-remoteviews versions="1.0.0-beta03"/> <core-role versions="1.0.0,1.1.0-rc01"/> - <core-splashscreen versions="1.0.0-beta02"/> + <core-splashscreen versions="1.0.0,1.1.0-alpha01"/> </androidx.core> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/core/uwb/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/core/uwb/group-index.xml new file mode 100644 index 0000000000..ae3fc0e84d --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/core/uwb/group-index.xml @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.core.uwb> + <uwb versions="1.0.0-alpha04"/> + <uwb-rxjava3 versions="1.0.0-alpha04"/> +</androidx.core.uwb> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/credentials/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/credentials/group-index.xml new file mode 100644 index 0000000000..f9d988248f --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/credentials/group-index.xml @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.credentials> + <credentials versions="1.2.0-alpha02"/> + <credentials-play-services-auth versions="1.2.0-alpha02"/> +</androidx.credentials> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/customview/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/customview/group-index.xml index e640f37099..eb94412376 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/customview/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/customview/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.customview> - <customview versions="1.1.0,1.2.0-alpha01"/> - <customview-poolingcontainer versions="1.0.0-alpha01"/> + <customview versions="1.1.0,1.2.0-alpha02"/> + <customview-poolingcontainer versions="1.0.0"/> </androidx.customview> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/databinding/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/databinding/group-index.xml index caaf866580..85f00357d6 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/databinding/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/databinding/group-index.xml @@ -4,13 +4,13 @@ <baseLibrary versions="3.2.0-alpha11"/> <compiler versions="3.2.0-alpha11"/> <compilerCommon versions="3.2.0-alpha11"/> - <databinding-adapters versions="4.2.2,7.1.2,7.3.0-alpha07"/> - <databinding-common versions="4.2.2,7.1.2,7.3.0-alpha07"/> - <databinding-compiler versions="4.2.2,7.1.2,7.3.0-alpha07"/> - <databinding-compiler-common versions="4.2.2,7.1.2,7.3.0-alpha07"/> - <databinding-ktx versions="7.1.2,7.3.0-alpha07"/> - <databinding-runtime versions="4.2.2,7.1.2,7.3.0-alpha07"/> + <databinding-adapters versions="4.2.2,7.4.2,8.1.0-alpha10"/> + <databinding-common versions="4.2.2,7.4.2,8.1.0-alpha10"/> + <databinding-compiler versions="4.2.2,7.4.2,8.1.0-alpha10"/> + <databinding-compiler-common versions="4.2.2,7.4.2,8.1.0-alpha10"/> + <databinding-ktx versions="7.4.2,8.1.0-alpha10"/> + <databinding-runtime versions="4.2.2,7.4.2,8.1.0-alpha10"/> <library versions="3.2.0-alpha11"/> - <viewbinding versions="4.2.2,7.1.2,7.3.0-alpha07"/> + <viewbinding versions="4.2.2,7.4.2,8.1.0-alpha10"/> </androidx.databinding> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/datastore/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/datastore/group-index.xml index 317535de82..3c8c7ed719 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/datastore/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/datastore/group-index.xml @@ -1,12 +1,51 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.datastore> - <datastore versions="1.0.0"/> - <datastore-core versions="1.0.0"/> - <datastore-preferences versions="1.0.0"/> - <datastore-preferences-core versions="1.0.0"/> - <datastore-preferences-rxjava2 versions="1.0.0"/> - <datastore-preferences-rxjava3 versions="1.0.0"/> - <datastore-rxjava2 versions="1.0.0"/> - <datastore-rxjava3 versions="1.0.0"/> + <datastore versions="1.0.0,1.1.0-alpha03"/> + <datastore-android versions="1.1.0-alpha03"/> + <datastore-core versions="1.0.0,1.1.0-alpha03"/> + <datastore-core-android versions="1.1.0-alpha03"/> + <datastore-core-iosarm64 versions="1.1.0-alpha03"/> + <datastore-core-iossimulatorarm64 versions="1.1.0-alpha03"/> + <datastore-core-iosx64 versions="1.1.0-alpha03"/> + <datastore-core-jvm versions="1.1.0-alpha03"/> + <datastore-core-linuxx64 versions="1.1.0-alpha03"/> + <datastore-core-macosarm64 versions="1.1.0-alpha03"/> + <datastore-core-macosx64 versions="1.1.0-alpha03"/> + <datastore-core-okio versions="1.1.0-alpha03"/> + <datastore-core-okio-iosarm64 versions="1.1.0-alpha03"/> + <datastore-core-okio-iossimulatorarm64 versions="1.1.0-alpha03"/> + <datastore-core-okio-iosx64 versions="1.1.0-alpha03"/> + <datastore-core-okio-jvm versions="1.1.0-alpha03"/> + <datastore-core-okio-linuxx64 versions="1.1.0-alpha03"/> + <datastore-core-okio-macosarm64 versions="1.1.0-alpha03"/> + <datastore-core-okio-macosx64 versions="1.1.0-alpha03"/> + <datastore-iosarm64 versions="1.1.0-alpha03"/> + <datastore-iossimulatorarm64 versions="1.1.0-alpha03"/> + <datastore-iosx64 versions="1.1.0-alpha03"/> + <datastore-jvm versions="1.1.0-alpha03"/> + <datastore-linuxx64 versions="1.1.0-alpha03"/> + <datastore-macosarm64 versions="1.1.0-alpha03"/> + <datastore-macosx64 versions="1.1.0-alpha03"/> + <datastore-preferences versions="1.0.0,1.1.0-alpha03"/> + <datastore-preferences-android versions="1.1.0-alpha03"/> + <datastore-preferences-core versions="1.0.0,1.1.0-alpha03"/> + <datastore-preferences-core-iosarm64 versions="1.1.0-alpha03"/> + <datastore-preferences-core-iossimulatorarm64 versions="1.1.0-alpha03"/> + <datastore-preferences-core-iosx64 versions="1.1.0-alpha03"/> + <datastore-preferences-core-jvm versions="1.1.0-alpha03"/> + <datastore-preferences-core-linuxx64 versions="1.1.0-alpha03"/> + <datastore-preferences-core-macosarm64 versions="1.1.0-alpha03"/> + <datastore-preferences-core-macosx64 versions="1.1.0-alpha03"/> + <datastore-preferences-iosarm64 versions="1.1.0-alpha03"/> + <datastore-preferences-iossimulatorarm64 versions="1.1.0-alpha03"/> + <datastore-preferences-iosx64 versions="1.1.0-alpha03"/> + <datastore-preferences-jvm versions="1.1.0-alpha03"/> + <datastore-preferences-linuxx64 versions="1.1.0-alpha03"/> + <datastore-preferences-macosarm64 versions="1.1.0-alpha03"/> + <datastore-preferences-macosx64 versions="1.1.0-alpha03"/> + <datastore-preferences-rxjava2 versions="1.0.0,1.1.0-alpha03"/> + <datastore-preferences-rxjava3 versions="1.0.0,1.1.0-alpha03"/> + <datastore-rxjava2 versions="1.0.0,1.1.0-alpha03"/> + <datastore-rxjava3 versions="1.0.0,1.1.0-alpha03"/> </androidx.datastore> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/draganddrop/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/draganddrop/group-index.xml index f7dbda9ebc..b60ef98303 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/draganddrop/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/draganddrop/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.draganddrop> - <draganddrop versions="1.0.0-beta01"/> + <draganddrop versions="1.0.0"/> </androidx.draganddrop> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/drawerlayout/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/drawerlayout/group-index.xml index ae0776f775..13b54d7b38 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/drawerlayout/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/drawerlayout/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.drawerlayout> - <drawerlayout versions="1.1.1"/> + <drawerlayout versions="1.2.0"/> </androidx.drawerlayout> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/emoji2/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/emoji2/group-index.xml index 494a6c73b1..3612d081ed 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/emoji2/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/emoji2/group-index.xml @@ -1,8 +1,9 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.emoji2> - <emoji2 versions="1.1.0,1.2.0-alpha02"/> - <emoji2-bundled versions="1.1.0,1.2.0-alpha02"/> - <emoji2-views versions="1.1.0,1.2.0-alpha02"/> - <emoji2-views-helper versions="1.1.0,1.2.0-alpha02"/> + <emoji2 versions="1.3.0,1.4.0-alpha01"/> + <emoji2-bundled versions="1.3.0,1.4.0-alpha01"/> + <emoji2-emojipicker versions="1.0.0-alpha03"/> + <emoji2-views versions="1.3.0,1.4.0-alpha01"/> + <emoji2-views-helper versions="1.3.0,1.4.0-alpha01"/> </androidx.emoji2> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/exifinterface/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/exifinterface/group-index.xml index 352dfcb4b0..0d9df89df0 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/exifinterface/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/exifinterface/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.exifinterface> - <exifinterface versions="1.3.3"/> + <exifinterface versions="1.3.6"/> </androidx.exifinterface> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/fragment/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/fragment/group-index.xml index 7cf52dc711..99cd8b0a9d 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/fragment/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/fragment/group-index.xml @@ -1,7 +1,8 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.fragment> - <fragment versions="1.4.1,1.5.0-alpha04"/> - <fragment-ktx versions="1.4.1,1.5.0-alpha04"/> - <fragment-testing versions="1.4.1,1.5.0-alpha04"/> + <fragment versions="1.5.6,1.6.0-alpha08"/> + <fragment-ktx versions="1.5.6,1.6.0-alpha08"/> + <fragment-testing versions="1.5.6,1.6.0-alpha08"/> + <fragment-testing-manifest versions="1.6.0-alpha08"/> </androidx.fragment> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/games/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/games/group-index.xml index b3461d11dc..ef4527e1de 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/games/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/games/group-index.xml @@ -1,10 +1,10 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.games> - <games-activity versions="1.1.0"/> - <games-controller versions="1.1.0"/> - <games-frame-pacing versions="1.10.0"/> - <games-memory-advice versions="1.0.0-beta01"/> - <games-performance-tuner versions="1.5.0"/> - <games-text-input versions="1.1.0"/> + <games-activity versions="1.2.2,2.0.0"/> + <games-controller versions="1.1.0,2.0.0"/> + <games-frame-pacing versions="1.10.1,2.0.0"/> + <games-memory-advice versions="2.0.0-beta02"/> + <games-performance-tuner versions="1.6.0,2.0.0-alpha03"/> + <games-text-input versions="1.1.1,2.0.0"/> </androidx.games> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/glance/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/glance/group-index.xml index 3de7394f6b..1a2396dd55 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/glance/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/glance/group-index.xml @@ -1,8 +1,8 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.glance> - <glance versions="1.0.0-alpha03"/> - <glance-appwidget versions="1.0.0-alpha03"/> + <glance versions="1.0.0-alpha05"/> + <glance-appwidget versions="1.0.0-alpha05"/> <glance-appwidget-proto versions="1.0.0-alpha03"/> - <glance-wear-tiles versions="1.0.0-alpha03"/> + <glance-wear-tiles versions="1.0.0-alpha05"/> </androidx.glance> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/graphics/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/graphics/group-index.xml new file mode 100644 index 0000000000..9837e9973d --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/graphics/group-index.xml @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.graphics> + <graphics-core versions="1.0.0-alpha03"/> + <graphics-path versions="1.0.0-alpha01"/> +</androidx.graphics> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/gridlayout/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/gridlayout/group-index.xml index 44ef6f2d8d..8bf16c7a4c 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/gridlayout/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/gridlayout/group-index.xml @@ -1,5 +1,5 @@ -<?xml version="1.0" encoding="UTF-8"?> +<?xml version='1.0' encoding='UTF-8'?> <androidx.gridlayout> - <gridlayout versions="1.0.0"/> + <gridlayout versions="1.0.0,1.1.0-alpha01"/> </androidx.gridlayout> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/health/connect/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/health/connect/group-index.xml new file mode 100644 index 0000000000..94af912136 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/health/connect/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.health.connect> + <connect-client versions="1.0.0-alpha11"/> +</androidx.health.connect> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/health/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/health/group-index.xml index e8e718bab8..a5f96e7941 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/health/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/health/group-index.xml @@ -1,5 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.health> - <health-services-client versions="1.0.0-alpha03"/> + <health-connect-client versions="1.0.0-alpha03"/> + <health-services-client versions="1.0.0-beta02"/> </androidx.health> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/hilt/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/hilt/group-index.xml index 441de5000f..e6d99ca99a 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/hilt/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/hilt/group-index.xml @@ -3,8 +3,8 @@ <hilt-common versions="1.0.0"/> <hilt-compiler versions="1.0.0"/> <hilt-lifecycle-viewmodel versions="1.0.0-alpha03"/> - <hilt-navigation versions="1.0.0"/> - <hilt-navigation-compose versions="1.0.0"/> + <hilt-navigation versions="1.0.0,1.1.0-alpha01"/> + <hilt-navigation-compose versions="1.0.0,1.1.0-alpha01"/> <hilt-navigation-fragment versions="1.0.0"/> <hilt-work versions="1.0.0"/> </androidx.hilt> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/input/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/input/group-index.xml new file mode 100644 index 0000000000..1cac1560f0 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/input/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.input> + <input-motionprediction versions="1.0.0-beta01"/> +</androidx.input> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/javascriptengine/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/javascriptengine/group-index.xml new file mode 100644 index 0000000000..8ad6490a5f --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/javascriptengine/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.javascriptengine> + <javascriptengine versions="1.0.0-alpha04"/> +</androidx.javascriptengine> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/lifecycle/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/lifecycle/group-index.xml index 2838b3c41a..8728529781 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/lifecycle/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/lifecycle/group-index.xml @@ -1,23 +1,24 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.lifecycle> - <lifecycle-common versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-common-java8 versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-compiler versions="2.4.1,2.5.0-alpha05"/> + <lifecycle-common versions="2.6.1"/> + <lifecycle-common-java8 versions="2.6.1"/> + <lifecycle-compiler versions="2.6.1"/> <lifecycle-extensions versions="2.2.0"/> - <lifecycle-livedata versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-livedata-core versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-livedata-core-ktx versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-livedata-ktx versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-process versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-reactivestreams versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-reactivestreams-ktx versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-runtime versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-runtime-ktx versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-runtime-testing versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-service versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-viewmodel versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-viewmodel-compose versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-viewmodel-ktx versions="2.4.1,2.5.0-alpha05"/> - <lifecycle-viewmodel-savedstate versions="1.0.0,2.4.1,2.5.0-alpha05"/> + <lifecycle-livedata versions="2.6.1"/> + <lifecycle-livedata-core versions="2.6.1"/> + <lifecycle-livedata-core-ktx versions="2.6.1"/> + <lifecycle-livedata-ktx versions="2.6.1"/> + <lifecycle-process versions="2.6.1"/> + <lifecycle-reactivestreams versions="2.6.1"/> + <lifecycle-reactivestreams-ktx versions="2.6.1"/> + <lifecycle-runtime versions="2.6.1"/> + <lifecycle-runtime-compose versions="2.6.1"/> + <lifecycle-runtime-ktx versions="2.6.1"/> + <lifecycle-runtime-testing versions="2.6.1"/> + <lifecycle-service versions="2.6.1"/> + <lifecycle-viewmodel versions="2.6.1"/> + <lifecycle-viewmodel-compose versions="2.6.1"/> + <lifecycle-viewmodel-ktx versions="2.6.1"/> + <lifecycle-viewmodel-savedstate versions="1.0.0,2.6.1"/> </androidx.lifecycle> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/media/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/media/group-index.xml index 4b75c7d8b9..1dc3ce08c5 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/media/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/media/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.media> - <media versions="1.5.0,1.6.0-beta01"/> - <media-widget versions="1.0.0-alpha5"/> + <media versions="1.6.0,1.7.0-alpha01"/> + <media-widget versions="1.0.0-alpha06"/> </androidx.media> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/media3/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/media3/group-index.xml index 2ce6038c01..42558f75b4 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/media3/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/media3/group-index.xml @@ -1,26 +1,27 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.media3> - <media3-cast versions="1.0.0-alpha03"/> - <media3-common versions="1.0.0-alpha03"/> - <media3-database versions="1.0.0-alpha03"/> - <media3-datasource versions="1.0.0-alpha03"/> - <media3-datasource-cronet versions="1.0.0-alpha03"/> - <media3-datasource-okhttp versions="1.0.0-alpha03"/> - <media3-datasource-rtmp versions="1.0.0-alpha03"/> - <media3-decoder versions="1.0.0-alpha03"/> - <media3-exoplayer versions="1.0.0-alpha03"/> - <media3-exoplayer-dash versions="1.0.0-alpha03"/> - <media3-exoplayer-hls versions="1.0.0-alpha03"/> - <media3-exoplayer-ima versions="1.0.0-alpha03"/> - <media3-exoplayer-rtsp versions="1.0.0-alpha03"/> - <media3-exoplayer-smoothstreaming versions="1.0.0-alpha03"/> - <media3-exoplayer-workmanager versions="1.0.0-alpha03"/> - <media3-extractor versions="1.0.0-alpha03"/> - <media3-session versions="1.0.0-alpha03"/> - <media3-test-utils versions="1.0.0-alpha03"/> - <media3-test-utils-robolectric versions="1.0.0-alpha03"/> - <media3-transformer versions="1.0.0-alpha03"/> - <media3-ui versions="1.0.0-alpha03"/> - <media3-ui-leanback versions="1.0.0-alpha03"/> + <media3-cast versions="1.0.0"/> + <media3-common versions="1.0.0"/> + <media3-database versions="1.0.0"/> + <media3-datasource versions="1.0.0"/> + <media3-datasource-cronet versions="1.0.0"/> + <media3-datasource-okhttp versions="1.0.0"/> + <media3-datasource-rtmp versions="1.0.0"/> + <media3-decoder versions="1.0.0"/> + <media3-effect versions="1.0.0"/> + <media3-exoplayer versions="1.0.0"/> + <media3-exoplayer-dash versions="1.0.0"/> + <media3-exoplayer-hls versions="1.0.0"/> + <media3-exoplayer-ima versions="1.0.0"/> + <media3-exoplayer-rtsp versions="1.0.0"/> + <media3-exoplayer-smoothstreaming versions="1.0.0"/> + <media3-exoplayer-workmanager versions="1.0.0"/> + <media3-extractor versions="1.0.0"/> + <media3-session versions="1.0.0"/> + <media3-test-utils versions="1.0.0"/> + <media3-test-utils-robolectric versions="1.0.0"/> + <media3-transformer versions="1.0.0"/> + <media3-ui versions="1.0.0"/> + <media3-ui-leanback versions="1.0.0"/> </androidx.media3> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/mediarouter/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/mediarouter/group-index.xml index 0e8e72c633..bf7ceeebb7 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/mediarouter/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/mediarouter/group-index.xml @@ -1,5 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.mediarouter> - <mediarouter versions="1.2.6,1.3.0-rc01"/> + <mediarouter versions="1.3.1,1.6.0-alpha02"/> + <mediarouter-testing versions="1.6.0-alpha02"/> </androidx.mediarouter> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/metrics/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/metrics/group-index.xml index 193b6e7bd5..a2e0b0d5f5 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/metrics/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/metrics/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.metrics> - <metrics-performance versions="1.0.0-alpha01"/> + <metrics-performance versions="1.0.0-alpha03"/> </androidx.metrics> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/navigation/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/navigation/group-index.xml index c246e8d11d..1167fede5f 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/navigation/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/navigation/group-index.xml @@ -1,18 +1,18 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.navigation> - <navigation-common versions="2.5.2,2.5.0-alpha03"/> - <navigation-common-ktx versions="2.5.2,2.5.0-alpha03"/> - <navigation-compose versions="2.4.1,2.5.0-alpha03"/> - <navigation-dynamic-features-fragment versions="2.4.1,2.5.0-alpha03"/> - <navigation-dynamic-features-runtime versions="2.4.1,2.5.0-alpha03"/> - <navigation-fragment versions="2.5.2,2.5.0-alpha03"/> - <navigation-fragment-ktx versions="2.5.2,2.5.0-alpha03"/> - <navigation-runtime versions="2.5.2,2.5.0-alpha03"/> - <navigation-runtime-ktx versions="2.5.2,2.5.0-alpha03"/> - <navigation-safe-args-generator versions="2.5.2,2.5.0-alpha03"/> - <navigation-safe-args-gradle-plugin versions="2.5.2,2.5.0-alpha03"/> - <navigation-testing versions="2.4.1,2.5.0-alpha03"/> - <navigation-ui versions="2.5.2,2.5.0-alpha03"/> - <navigation-ui-ktx versions="2.5.2,2.5.0-alpha03"/> + <navigation-common versions="2.5.3,2.6.0-alpha08"/> + <navigation-common-ktx versions="2.5.3,2.6.0-alpha08"/> + <navigation-compose versions="2.5.3,2.6.0-alpha08"/> + <navigation-dynamic-features-fragment versions="2.5.3,2.6.0-alpha08"/> + <navigation-dynamic-features-runtime versions="2.5.3,2.6.0-alpha08"/> + <navigation-fragment versions="2.5.3,2.6.0-alpha08"/> + <navigation-fragment-ktx versions="2.5.3,2.6.0-alpha08"/> + <navigation-runtime versions="2.5.3,2.6.0-alpha08"/> + <navigation-runtime-ktx versions="2.5.3,2.6.0-alpha08"/> + <navigation-safe-args-generator versions="2.5.3,2.6.0-alpha08"/> + <navigation-safe-args-gradle-plugin versions="2.5.3,2.6.0-alpha08"/> + <navigation-testing versions="2.5.3,2.6.0-alpha08"/> + <navigation-ui versions="2.5.3,2.6.0-alpha08"/> + <navigation-ui-ktx versions="2.5.3,2.6.0-alpha08"/> </androidx.navigation> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/navigation/safeargs/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/navigation/safeargs/group-index.xml index fdd64d436a..aa052f68c5 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/navigation/safeargs/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/navigation/safeargs/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.navigation.safeargs> - <androidx.navigation.safeargs.gradle.plugin versions="2.4.1,2.5.0-alpha03"/> + <androidx.navigation.safeargs.gradle.plugin versions="2.5.3,2.6.0-alpha08"/> </androidx.navigation.safeargs> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/navigation/safeargs/kotlin/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/navigation/safeargs/kotlin/group-index.xml index 3040022433..b8c95e385a 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/navigation/safeargs/kotlin/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/navigation/safeargs/kotlin/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.navigation.safeargs.kotlin> - <androidx.navigation.safeargs.kotlin.gradle.plugin versions="2.4.1,2.5.0-alpha03"/> + <androidx.navigation.safeargs.kotlin.gradle.plugin versions="2.5.3,2.6.0-alpha08"/> </androidx.navigation.safeargs.kotlin> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/paging/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/paging/group-index.xml index f8dc5aba4c..b66eb92ee3 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/paging/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/paging/group-index.xml @@ -1,13 +1,14 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.paging> - <paging-common versions="2.1.2,3.1.1"/> - <paging-common-ktx versions="2.1.2,3.1.1"/> - <paging-compose versions="1.0.0-alpha14"/> - <paging-guava versions="3.1.1"/> - <paging-runtime versions="2.1.2,3.1.1"/> - <paging-runtime-ktx versions="2.1.2,3.1.1"/> - <paging-rxjava2 versions="2.1.2,3.1.1"/> - <paging-rxjava2-ktx versions="2.1.2,3.1.1"/> - <paging-rxjava3 versions="3.1.1"/> + <paging-common versions="2.1.2,3.1.1,3.2.0-alpha04"/> + <paging-common-ktx versions="2.1.2,3.1.1,3.2.0-alpha04"/> + <paging-compose versions="1.0.0-alpha18"/> + <paging-guava versions="3.1.1,3.2.0-alpha04"/> + <paging-runtime versions="2.1.2,3.1.1,3.2.0-alpha04"/> + <paging-runtime-ktx versions="2.1.2,3.1.1,3.2.0-alpha04"/> + <paging-rxjava2 versions="2.1.2,3.1.1,3.2.0-alpha04"/> + <paging-rxjava2-ktx versions="2.1.2,3.1.1,3.2.0-alpha04"/> + <paging-rxjava3 versions="3.1.1,3.2.0-alpha04"/> + <paging-testing versions="3.2.0-alpha04"/> </androidx.paging> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/privacysandbox/ads/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/privacysandbox/ads/group-index.xml new file mode 100644 index 0000000000..84e5056a21 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/privacysandbox/ads/group-index.xml @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.privacysandbox.ads> + <ads-adservices versions="1.0.0-beta02"/> + <ads-adservices-java versions="1.0.0-beta02"/> +</androidx.privacysandbox.ads> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/privacysandbox/sdkruntime/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/privacysandbox/sdkruntime/group-index.xml new file mode 100644 index 0000000000..163ffd5f74 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/privacysandbox/sdkruntime/group-index.xml @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.privacysandbox.sdkruntime> + <sdkruntime-client versions="1.0.0-alpha02"/> + <sdkruntime-core versions="1.0.0-alpha02"/> +</androidx.privacysandbox.sdkruntime> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/privacysandbox/tools/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/privacysandbox/tools/group-index.xml new file mode 100644 index 0000000000..c10c7d4381 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/privacysandbox/tools/group-index.xml @@ -0,0 +1,9 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.privacysandbox.tools> + <tools versions="1.0.0-alpha03"/> + <tools-apicompiler versions="1.0.0-alpha03"/> + <tools-apigenerator versions="1.0.0-alpha03"/> + <tools-apipackager versions="1.0.0-alpha03"/> + <tools-core versions="1.0.0-alpha03"/> +</androidx.privacysandbox.tools> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/privacysandbox/ui/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/privacysandbox/ui/group-index.xml new file mode 100644 index 0000000000..cc4366cceb --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/privacysandbox/ui/group-index.xml @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.privacysandbox.ui> + <ui-client versions="1.0.0-alpha01"/> + <ui-core versions="1.0.0-alpha01"/> + <ui-provider versions="1.0.0-alpha01"/> +</androidx.privacysandbox.ui> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/profileinstaller/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/profileinstaller/group-index.xml index f4a5cf7ae7..2032bedfee 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/profileinstaller/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/profileinstaller/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.profileinstaller> - <profileinstaller versions="1.1.0,1.2.0-alpha02"/> + <profileinstaller versions="1.3.0"/> </androidx.profileinstaller> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/recyclerview/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/recyclerview/group-index.xml index 564981f13c..bdb6a8e87a 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/recyclerview/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/recyclerview/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.recyclerview> - <recyclerview versions="1.2.1,1.3.0-alpha01"/> + <recyclerview versions="1.3.0"/> <recyclerview-selection versions="1.1.0,1.2.0-alpha01"/> </androidx.recyclerview> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/room/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/room/group-index.xml index ec6ec77d17..1479d95c6e 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/room/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/room/group-index.xml @@ -1,17 +1,20 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.room> - <room-common versions="2.4.2,2.5.0-alpha01"/> - <room-compiler versions="2.4.2,2.5.0-alpha01"/> - <room-compiler-processing versions="2.4.2,2.5.0-alpha01"/> - <room-compiler-processing-testing versions="2.4.2,2.5.0-alpha01"/> + <room-common versions="2.5.1,2.6.0-alpha01"/> + <room-compiler versions="2.5.1,2.6.0-alpha01"/> + <room-compiler-processing versions="2.5.1,2.6.0-alpha01"/> + <room-compiler-processing-testing versions="2.5.1,2.6.0-alpha01"/> <room-coroutines versions="2.1.0-alpha04"/> - <room-guava versions="2.4.2,2.5.0-alpha01"/> - <room-ktx versions="2.4.2,2.5.0-alpha01"/> - <room-migration versions="2.4.2,2.5.0-alpha01"/> - <room-paging versions="2.4.2,2.5.0-alpha01"/> - <room-runtime versions="2.4.2,2.5.0-alpha01"/> - <room-rxjava2 versions="2.4.2,2.5.0-alpha01"/> - <room-rxjava3 versions="2.4.2,2.5.0-alpha01"/> - <room-testing versions="2.4.2,2.5.0-alpha01"/> + <room-guava versions="2.5.1,2.6.0-alpha01"/> + <room-ktx versions="2.5.1,2.6.0-alpha01"/> + <room-migration versions="2.5.1,2.6.0-alpha01"/> + <room-paging versions="2.5.1,2.6.0-alpha01"/> + <room-paging-guava versions="2.5.1,2.6.0-alpha01"/> + <room-paging-rxjava2 versions="2.5.1,2.6.0-alpha01"/> + <room-paging-rxjava3 versions="2.5.1,2.6.0-alpha01"/> + <room-runtime versions="2.5.1,2.6.0-alpha01"/> + <room-rxjava2 versions="2.5.1,2.6.0-alpha01"/> + <room-rxjava3 versions="2.5.1,2.6.0-alpha01"/> + <room-testing versions="2.5.1,2.6.0-alpha01"/> </androidx.room> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/savedstate/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/savedstate/group-index.xml index 3149da6950..aa3ede0735 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/savedstate/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/savedstate/group-index.xml @@ -1,8 +1,8 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.savedstate> - <savedstate versions="1.1.0,1.2.0-alpha01"/> + <savedstate versions="1.2.1"/> <savedstate-bundle versions="1.0.0-alpha01"/> <savedstate-common versions="1.0.0-alpha01"/> - <savedstate-ktx versions="1.1.0,1.2.0-alpha01"/> + <savedstate-ktx versions="1.2.1"/> </androidx.savedstate> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/security/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/security/group-index.xml index a32db32972..09b551337b 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/security/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/security/group-index.xml @@ -2,8 +2,8 @@ <androidx.security> <security-app-authenticator versions="1.0.0-alpha02"/> <security-app-authenticator-testing versions="1.0.0-alpha01"/> - <security-crypto versions="1.0.0,1.1.0-alpha03"/> - <security-crypto-ktx versions="1.1.0-alpha03"/> + <security-crypto versions="1.0.0,1.1.0-alpha05"/> + <security-crypto-ktx versions="1.1.0-alpha05"/> <security-identity-credential versions="1.0.0-alpha03"/> </androidx.security> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/sharetarget/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/sharetarget/group-index.xml index 36eed9c250..c6b73d1301 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/sharetarget/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/sharetarget/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.sharetarget> - <sharetarget versions="1.1.0,1.2.0-rc01"/> + <sharetarget versions="1.2.0"/> </androidx.sharetarget> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/slice/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/slice/group-index.xml index 8bc309f0db..1f624f2fb3 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/slice/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/slice/group-index.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.slice> <slice-builders versions="1.0.0,1.1.0-alpha02"/> - <slice-builders-ktx versions="1.0.0-alpha6"/> + <slice-builders-ktx versions="1.0.0-alpha08"/> <slice-core versions="1.0.0,1.1.0-alpha02"/> <slice-view versions="1.0.0,1.1.0-alpha02"/> </androidx.slice> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/sqlite/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/sqlite/group-index.xml index e939533834..f6b1fa61f4 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/sqlite/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/sqlite/group-index.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.sqlite> - <sqlite versions="2.2.0,2.3.0-alpha01"/> - <sqlite-framework versions="2.2.0,2.3.0-alpha01"/> - <sqlite-ktx versions="2.2.0,2.3.0-alpha01"/> + <sqlite versions="2.3.1,2.4.0-alpha01"/> + <sqlite-framework versions="2.3.1,2.4.0-alpha01"/> + <sqlite-ktx versions="2.3.1,2.4.0-alpha01"/> </androidx.sqlite> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/startup/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/startup/group-index.xml index 5376424d54..0065175d4a 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/startup/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/startup/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.startup> - <startup-runtime versions="1.1.1,1.2.0-alpha01"/> + <startup-runtime versions="1.1.1,1.2.0-alpha02"/> </androidx.startup> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/test/espresso/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/test/espresso/group-index.xml index 8a68ebab47..fc74f688b7 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/test/espresso/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/test/espresso/group-index.xml @@ -1,11 +1,12 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.test.espresso> - <espresso-accessibility versions="3.4.0,3.5.0-alpha05"/> - <espresso-contrib versions="3.4.0,3.5.0-alpha05"/> - <espresso-core versions="3.4.0,3.5.0-alpha05"/> - <espresso-idling-resource versions="3.4.0,3.5.0-alpha05"/> - <espresso-intents versions="3.4.0,3.5.0-alpha05"/> - <espresso-remote versions="3.4.0,3.5.0-alpha05"/> - <espresso-web versions="3.4.0,3.5.0-alpha05"/> + <espresso-accessibility versions="3.5.1,3.6.0-alpha01"/> + <espresso-contrib versions="3.5.1,3.6.0-alpha01"/> + <espresso-core versions="3.5.1,3.6.0-alpha01"/> + <espresso-device versions="1.0.0-alpha04"/> + <espresso-idling-resource versions="3.5.1,3.6.0-alpha01"/> + <espresso-intents versions="3.5.1,3.6.0-alpha01"/> + <espresso-remote versions="3.5.1,3.6.0-alpha01"/> + <espresso-web versions="3.5.1,3.6.0-alpha01"/> </androidx.test.espresso> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/test/espresso/idling/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/test/espresso/idling/group-index.xml index 48568e2c85..dd11420a72 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/test/espresso/idling/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/test/espresso/idling/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.test.espresso.idling> - <idling-concurrent versions="3.4.0,3.5.0-alpha05"/> - <idling-net versions="3.4.0,3.5.0-alpha05"/> + <idling-concurrent versions="3.5.1,3.6.0-alpha01"/> + <idling-net versions="3.5.1,3.6.0-alpha01"/> </androidx.test.espresso.idling> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/test/ext/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/test/ext/group-index.xml index b1b8ccb03f..6ff562efaf 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/test/ext/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/test/ext/group-index.xml @@ -1,8 +1,8 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.test.ext> - <junit versions="1.1.3,1.1.4-alpha05"/> + <junit versions="1.1.5,1.2.0-alpha01"/> <junit-gtest versions="1.0.0-alpha01"/> - <junit-ktx versions="1.1.3,1.1.4-alpha05"/> - <truth versions="1.4.0,1.5.0-alpha05"/> + <junit-ktx versions="1.1.5,1.2.0-alpha01"/> + <truth versions="1.5.0,1.6.0-alpha01"/> </androidx.test.ext> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/test/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/test/group-index.xml index 8d1166bace..4aa33a7957 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/test/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/test/group-index.xml @@ -1,11 +1,11 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.test> - <annotation versions="1.0.0"/> - <core versions="1.4.0,1.4.1-alpha05"/> - <core-ktx versions="1.4.0,1.4.1-alpha05"/> - <monitor versions="1.5.0,1.6.0-alpha02"/> - <orchestrator versions="1.4.1,1.4.2-alpha02"/> - <rules versions="1.4.0,1.4.1-alpha05"/> - <runner versions="1.4.0,1.5.0-alpha02"/> + <annotation versions="1.0.1,1.1.0-alpha01"/> + <core versions="1.5.0,1.6.0-alpha01"/> + <core-ktx versions="1.5.0,1.6.0-alpha01"/> + <monitor versions="1.6.1,1.7.0-alpha01"/> + <orchestrator versions="1.4.2,1.5.0-alpha01"/> + <rules versions="1.5.0,1.6.0-alpha01"/> + <runner versions="1.5.2,1.6.0-alpha01"/> </androidx.test> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/test/services/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/test/services/group-index.xml index 2c96df1c45..97c0f6b4ce 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/test/services/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/test/services/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.test.services> - <storage versions="1.4.1,1.4.2-alpha02"/> - <test-services versions="1.4.1,1.4.2-alpha02"/> + <storage versions="1.4.2,1.5.0-alpha01"/> + <test-services versions="1.4.2,1.5.0-alpha01"/> </androidx.test.services> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/test/uiautomator/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/test/uiautomator/group-index.xml index a5a58f8d63..0159a837fb 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/test/uiautomator/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/test/uiautomator/group-index.xml @@ -1,6 +1,6 @@ -<?xml version="1.0" encoding="UTF-8"?> +<?xml version='1.0' encoding='UTF-8'?> <androidx.test.uiautomator> + <uiautomator versions="2.2.0,2.3.0-alpha02"/> <uiautomator-v18 versions="2.2.0-alpha1"/> - <uiautomator versions="2.2.0"/> </androidx.test.uiautomator> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/tracing/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/tracing/group-index.xml index cfa3849aec..1487d00e73 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/tracing/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/tracing/group-index.xml @@ -1,6 +1,9 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.tracing> - <tracing versions="1.0.0,1.1.0-beta01"/> - <tracing-ktx versions="1.0.0,1.1.0-beta01"/> + <tracing versions="1.1.0,1.2.0-beta02"/> + <tracing-ktx versions="1.1.0,1.2.0-beta02"/> + <tracing-perfetto versions="1.0.0-alpha13"/> + <tracing-perfetto-binary versions="1.0.0-alpha13"/> + <tracing-perfetto-common versions="1.0.0-alpha13"/> </androidx.tracing> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/tv/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/tv/group-index.xml new file mode 100644 index 0000000000..77c276e9c1 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/tv/group-index.xml @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.tv> + <tv-foundation versions="1.0.0-alpha05"/> + <tv-material versions="1.0.0-alpha05"/> +</androidx.tv> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/vectordrawable/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/vectordrawable/group-index.xml index 64c1207f19..0bfe16d8a0 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/vectordrawable/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/vectordrawable/group-index.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.vectordrawable> - <vectordrawable versions="1.1.0,1.2.0-alpha02"/> + <vectordrawable versions="1.1.0,1.2.0-beta01"/> <vectordrawable-animated versions="1.1.0"/> - <vectordrawable-seekable versions="1.0.0-alpha02"/> + <vectordrawable-seekable versions="1.0.0-beta01"/> </androidx.vectordrawable> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/wear/compose/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/wear/compose/group-index.xml index 0e144d6cd4..82f259412e 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/wear/compose/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/wear/compose/group-index.xml @@ -1,7 +1,10 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.wear.compose> - <compose-foundation versions="1.0.0-alpha19"/> - <compose-material versions="1.0.0-alpha19"/> - <compose-navigation versions="1.0.0-alpha19"/> + <compose-foundation versions="1.1.2,1.2.0-alpha07"/> + <compose-material versions="1.1.2,1.2.0-alpha07"/> + <compose-material-core versions="1.2.0-alpha07"/> + <compose-material3 versions="1.0.0-alpha01"/> + <compose-navigation versions="1.1.2,1.2.0-alpha07"/> + <compose-ui-tooling versions="1.2.0-alpha07"/> </androidx.wear.compose> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/wear/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/wear/group-index.xml index 2ef0f0144e..afa475f806 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/wear/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/wear/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.wear> - <wear versions="1.2.0,1.3.0-alpha02"/> + <wear versions="1.2.0,1.3.0-alpha04"/> <wear-complications-data versions="1.0.0-alpha22"/> <wear-complications-data-source versions="1.0.0-alpha22"/> <wear-complications-data-source-ktx versions="1.0.0-alpha22"/> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/wear/protolayout/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/wear/protolayout/group-index.xml new file mode 100644 index 0000000000..dbe1cce91c --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/wear/protolayout/group-index.xml @@ -0,0 +1,10 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.wear.protolayout> + <protolayout versions="1.0.0-alpha06"/> + <protolayout-expression versions="1.0.0-alpha06"/> + <protolayout-expression-pipeline versions="1.0.0-alpha06"/> + <protolayout-material versions="1.0.0-alpha06"/> + <protolayout-proto versions="1.0.0-alpha06"/> + <protolayout-renderer versions="1.0.0-alpha06"/> +</androidx.wear.protolayout> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/wear/tiles/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/wear/tiles/group-index.xml index 1e339d83a2..c2d718bdc4 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/wear/tiles/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/wear/tiles/group-index.xml @@ -1,9 +1,10 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.wear.tiles> - <tiles versions="1.0.1,1.1.0-alpha04"/> - <tiles-material versions="1.1.0-alpha04"/> - <tiles-proto versions="1.0.1,1.1.0-alpha04"/> - <tiles-renderer versions="1.0.1,1.1.0-alpha04"/> - <tiles-testing versions="1.0.1,1.1.0-alpha04"/> + <tiles versions="1.1.0,1.2.0-alpha02"/> + <tiles-material versions="1.1.0,1.2.0-alpha02"/> + <tiles-proto versions="1.1.0,1.2.0-alpha02"/> + <tiles-renderer versions="1.1.0,1.2.0-alpha02"/> + <tiles-testing versions="1.1.0,1.2.0-alpha02"/> + <tiles-tooling versions="1.2.0-alpha02"/> </androidx.wear.tiles> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/wear/watchface/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/wear/watchface/group-index.xml index bafe311086..2af6073a71 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/wear/watchface/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/wear/watchface/group-index.xml @@ -1,17 +1,17 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.wear.watchface> - <watchface versions="1.0.1,1.1.0-alpha04"/> - <watchface-client versions="1.0.1,1.1.0-alpha04"/> - <watchface-client-guava versions="1.0.1,1.1.0-alpha04"/> - <watchface-complications versions="1.0.1,1.1.0-alpha04"/> - <watchface-complications-data versions="1.0.1,1.1.0-alpha04"/> - <watchface-complications-data-source versions="1.0.1,1.1.0-alpha04"/> - <watchface-complications-data-source-ktx versions="1.0.1,1.1.0-alpha04"/> - <watchface-complications-rendering versions="1.0.1,1.1.0-alpha04"/> - <watchface-data versions="1.0.1,1.1.0-alpha04"/> - <watchface-editor versions="1.0.1,1.1.0-alpha04"/> - <watchface-editor-guava versions="1.0.1,1.1.0-alpha04"/> - <watchface-guava versions="1.0.1,1.1.0-alpha04"/> - <watchface-style versions="1.0.1,1.1.0-alpha04"/> + <watchface versions="1.1.1,1.2.0-alpha07"/> + <watchface-client versions="1.1.1,1.2.0-alpha07"/> + <watchface-client-guava versions="1.1.1,1.2.0-alpha07"/> + <watchface-complications versions="1.1.1,1.2.0-alpha07"/> + <watchface-complications-data versions="1.1.1,1.2.0-alpha07"/> + <watchface-complications-data-source versions="1.1.1,1.2.0-alpha07"/> + <watchface-complications-data-source-ktx versions="1.1.1,1.2.0-alpha07"/> + <watchface-complications-rendering versions="1.1.1,1.2.0-alpha07"/> + <watchface-data versions="1.1.1,1.2.0-alpha07"/> + <watchface-editor versions="1.1.1,1.2.0-alpha07"/> + <watchface-editor-guava versions="1.1.1,1.2.0-alpha07"/> + <watchface-guava versions="1.1.1,1.2.0-alpha07"/> + <watchface-style versions="1.1.1,1.2.0-alpha07"/> </androidx.wear.watchface> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/webkit/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/webkit/group-index.xml index 68a4e7606f..26530e5697 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/webkit/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/webkit/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.webkit> - <webkit versions="1.4.0"/> + <webkit versions="1.6.1,1.7.0-alpha03"/> </androidx.webkit> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/window/extensions/core/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/window/extensions/core/group-index.xml new file mode 100644 index 0000000000..260f0157c3 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/androidx/window/extensions/core/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<androidx.window.extensions.core> + <core versions="1.0.0-beta01"/> +</androidx.window.extensions.core> + diff --git a/sdk-common/src/main/resources/versions-offline/androidx/window/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/window/group-index.xml index 5ceca43aff..9a2a280caf 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/window/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/window/group-index.xml @@ -1,10 +1,11 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.window> - <window versions="1.0.0"/> + <window versions="1.0.0,1.1.0-beta01"/> + <window-core versions="1.1.0-beta01"/> <window-extensions versions="1.0.0-alpha01"/> - <window-java versions="1.0.0"/> - <window-rxjava2 versions="1.0.0"/> - <window-rxjava3 versions="1.0.0"/> - <window-testing versions="1.0.0"/> + <window-java versions="1.0.0,1.1.0-beta01"/> + <window-rxjava2 versions="1.0.0,1.1.0-beta01"/> + <window-rxjava3 versions="1.0.0,1.1.0-beta01"/> + <window-testing versions="1.0.0,1.1.0-beta01"/> </androidx.window> diff --git a/sdk-common/src/main/resources/versions-offline/androidx/work/group-index.xml b/sdk-common/src/main/resources/versions-offline/androidx/work/group-index.xml index 32f702d6d2..e3c94349cf 100644 --- a/sdk-common/src/main/resources/versions-offline/androidx/work/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/androidx/work/group-index.xml @@ -1,11 +1,11 @@ <?xml version='1.0' encoding='UTF-8'?> <androidx.work> - <work-gcm versions="2.7.1,2.8.0-alpha01"/> - <work-multiprocess versions="2.7.1,2.8.0-alpha01"/> - <work-runtime versions="2.7.1,2.8.0-alpha01"/> - <work-runtime-ktx versions="2.7.1,2.8.0-alpha01"/> - <work-rxjava2 versions="2.7.1,2.8.0-alpha01"/> - <work-rxjava3 versions="2.7.1,2.8.0-alpha01"/> - <work-testing versions="2.7.1,2.8.0-alpha01"/> + <work-gcm versions="2.8.1"/> + <work-multiprocess versions="2.8.1"/> + <work-runtime versions="2.8.1"/> + <work-runtime-ktx versions="2.8.1"/> + <work-rxjava2 versions="2.8.1"/> + <work-rxjava3 versions="2.8.1"/> + <work-testing versions="2.8.1"/> </androidx.work> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/application/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/application/group-index.xml index 52898aaaaf..f6caaf1c4f 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/application/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/application/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.application> - <com.android.application.gradle.plugin versions="4.2.2,7.1.2,7.3.0-alpha07"/> + <com.android.application.gradle.plugin versions="4.2.2,7.4.2,8.1.0-alpha10"/> </com.android.application> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/asset-pack-bundle/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/asset-pack-bundle/group-index.xml index fb23ee86a7..8365789e82 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/asset-pack-bundle/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/asset-pack-bundle/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.asset-pack-bundle> - <com.android.asset-pack-bundle.gradle.plugin versions="7.1.2,7.3.0-alpha07"/> + <com.android.asset-pack-bundle.gradle.plugin versions="7.4.2,8.1.0-alpha10"/> </com.android.asset-pack-bundle> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/asset-pack/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/asset-pack/group-index.xml index e10d05ae60..d591e6404a 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/asset-pack/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/asset-pack/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.asset-pack> - <com.android.asset-pack.gradle.plugin versions="4.2.2,7.1.2,7.3.0-alpha07"/> + <com.android.asset-pack.gradle.plugin versions="4.2.2,7.4.2,8.1.0-alpha10"/> </com.android.asset-pack> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/billingclient/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/billingclient/group-index.xml index 2cc81d343e..0785417804 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/billingclient/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/billingclient/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.billingclient> - <billing versions="3.0.3,4.1.0"/> - <billing-ktx versions="3.0.3,4.1.0"/> + <billing versions="4.1.0,5.1.0"/> + <billing-ktx versions="4.1.0,5.1.0"/> </com.android.billingclient> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/car/setupwizardlib/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/car/setupwizardlib/group-index.xml index fce5e7e031..746edcd884 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/car/setupwizardlib/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/car/setupwizardlib/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.car.setupwizardlib> - <car-setup-wizard-lib versions="1.3.0"/> + <car-setup-wizard-lib versions="1.4.0"/> </com.android.car.setupwizardlib> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/car/ui/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/car/ui/group-index.xml index cafabb33c8..5ce50f8ad6 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/car/ui/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/car/ui/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.car.ui> - <car-ui-lib versions="2.0.0"/> - <car-ui-lib-plugin-apis versions="1.0.1"/> + <car-ui-lib versions="2.3.0"/> + <car-ui-lib-plugin-apis versions="1.2.0"/> </com.android.car.ui> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/databinding/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/databinding/group-index.xml index b0d110442f..c35090c233 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/databinding/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/databinding/group-index.xml @@ -1,11 +1,11 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.databinding> - <adapters versions="4.2.2,7.1.2,7.3.0-alpha07"/> - <baseLibrary versions="4.2.2,7.1.2,7.3.0-alpha07"/> + <adapters versions="4.2.2,7.4.2,8.1.0-alpha10"/> + <baseLibrary versions="4.2.2,7.4.2,8.1.0-alpha10"/> <compiler versions="3.1.4,3.2.0-alpha10"/> <compilerCommon versions="3.1.4,3.2.0-alpha10"/> - <library versions="4.2.2,7.1.2,7.3.0-alpha07"/> - <viewbinding versions="4.2.2,7.1.2,7.3.0-alpha07"/> + <library versions="4.2.2,7.4.2,8.1.0-alpha10"/> + <viewbinding versions="4.2.2,7.4.2,8.1.0-alpha10"/> <viewbinding-support versions="3.6.0-alpha02"/> </com.android.databinding> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/dynamic-feature/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/dynamic-feature/group-index.xml index ea5b450f8e..9048bf5a23 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/dynamic-feature/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/dynamic-feature/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.dynamic-feature> - <com.android.dynamic-feature.gradle.plugin versions="4.2.2,7.1.2,7.3.0-alpha07"/> + <com.android.dynamic-feature.gradle.plugin versions="4.2.2,7.4.2,8.1.0-alpha10"/> </com.android.dynamic-feature> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/fused-library/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/fused-library/group-index.xml new file mode 100644 index 0000000000..7cd09ec45c --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/android/fused-library/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.android.fused-library> + <com.android.fused-library.gradle.plugin versions="7.4.2,8.1.0-alpha10"/> +</com.android.fused-library> + diff --git a/sdk-common/src/main/resources/versions-offline/com/android/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/group-index.xml index 433335e776..3b6a042a98 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android> - <signflinger versions="4.2.2,7.1.2,7.3.0-alpha07"/> - <zipflinger versions="4.2.2,7.1.2,7.3.0-alpha07"/> + <signflinger versions="4.2.2,7.4.2,8.1.0-alpha10"/> + <zipflinger versions="4.2.2,7.4.2,8.1.0-alpha10"/> </com.android> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/internal/settings/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/internal/settings/group-index.xml new file mode 100644 index 0000000000..ded4ac17f4 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/android/internal/settings/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.android.internal.settings> + <com.android.internal.settings.gradle.plugin versions="7.4.2,8.1.0-alpha10"/> +</com.android.internal.settings> + diff --git a/sdk-common/src/main/resources/versions-offline/com/android/library/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/library/group-index.xml index 767a5bc8fc..d18b739cb5 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/library/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/library/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.library> - <com.android.library.gradle.plugin versions="4.2.2,7.1.2,7.3.0-alpha07"/> + <com.android.library.gradle.plugin versions="4.2.2,7.4.2,8.1.0-alpha10"/> </com.android.library> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/lint/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/lint/group-index.xml index 5981c90539..e1d8023bcc 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/lint/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/lint/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.lint> - <com.android.lint.gradle.plugin versions="4.2.2,7.1.2,7.3.0-alpha07"/> + <com.android.lint.gradle.plugin versions="4.2.2,7.4.2,8.1.0-alpha10"/> </com.android.lint> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/ndk/thirdparty/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/ndk/thirdparty/group-index.xml index 85a135bf91..856c6ba846 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/ndk/thirdparty/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/ndk/thirdparty/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.ndk.thirdparty> - <curl versions="7.79.1-beta-1"/> + <curl versions="7.85.0-beta-1"/> <googletest versions="1.11.0-beta-1"/> <jsoncpp versions="1.9.5-beta-1"/> <libpng versions="1.6.37-alpha-1"/> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/privacy-sandbox-sdk/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/privacy-sandbox-sdk/group-index.xml new file mode 100644 index 0000000000..2668e6541d --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/android/privacy-sandbox-sdk/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.android.privacy-sandbox-sdk> + <com.android.privacy-sandbox-sdk.gradle.plugin versions="7.4.2,8.1.0-alpha10"/> +</com.android.privacy-sandbox-sdk> + diff --git a/sdk-common/src/main/resources/versions-offline/com/android/settings/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/settings/group-index.xml new file mode 100644 index 0000000000..26d21ff09d --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/android/settings/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.android.settings> + <com.android.settings.gradle.plugin versions="7.4.2,8.1.0-alpha10"/> +</com.android.settings> + diff --git a/sdk-common/src/main/resources/versions-offline/com/android/test/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/test/group-index.xml index f837ec64b7..b79a77e08b 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/test/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/test/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.test> - <com.android.test.gradle.plugin versions="4.2.2,7.1.2,7.3.0-alpha07"/> + <com.android.test.gradle.plugin versions="4.2.2,7.4.2,8.1.0-alpha10"/> </com.android.test> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/analytics-library/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/analytics-library/group-index.xml index a1a74e631f..d6763d1456 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/analytics-library/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/analytics-library/group-index.xml @@ -1,11 +1,11 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools.analytics-library> - <crash versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <inspector versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <protos versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <publisher versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <shared versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <testing versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <tracker versions="27.2.2,30.1.2,30.3.0-alpha07"/> + <crash versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <inspector versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <protos versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <publisher versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <shared versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <testing versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <tracker versions="27.2.2,30.4.2,31.1.0-alpha10"/> </com.android.tools.analytics-library> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/apkparser/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/apkparser/group-index.xml index 1852904a8b..1cea9e67e8 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/apkparser/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/apkparser/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools.apkparser> - <apkanalyzer versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <binary-resources versions="27.2.2,30.1.2,30.3.0-alpha07"/> + <apkanalyzer versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <binary-resources versions="27.2.2,30.4.2,31.1.0-alpha10"/> </com.android.tools.apkparser> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/build/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/build/group-index.xml index 9c7f86bf39..c0ff7a2cdc 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/build/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/build/group-index.xml @@ -1,19 +1,21 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools.build> - <aapt2 versions="4.2.2-7147631,7.1.2-7984345,7.3.0-alpha07-8248216"/> - <aapt2-proto versions="4.2.2-7147631,7.1.2-7984345,7.3.0-alpha07-8248216"/> - <aaptcompiler versions="4.2.2,7.1.2,7.3.0-alpha07"/> - <apksig versions="4.2.2,7.1.2,7.3.0-alpha07"/> - <apkzlib versions="4.2.2,7.1.2,7.3.0-alpha07"/> - <builder versions="4.2.2,7.1.2,7.3.0-alpha07"/> - <builder-model versions="4.2.2,7.1.2,7.3.0-alpha07"/> - <builder-test-api versions="4.2.2,7.1.2,7.3.0-alpha07"/> - <bundletool versions="0.15.0,1.9.0"/> - <gradle versions="4.2.2,7.1.2,7.3.0-alpha07"/> - <gradle-api versions="4.2.2,7.1.2,7.3.0-alpha07"/> + <aapt2 versions="4.2.2-7147631,7.4.2-8841542,8.1.0-alpha10-9603961"/> + <aapt2-proto versions="4.2.2-7147631,7.4.2-8841542,8.1.0-alpha10-9603961"/> + <aaptcompiler versions="4.2.2,7.4.2,8.1.0-alpha10"/> + <apksig versions="4.2.2,7.4.2,8.1.0-alpha10"/> + <apkzlib versions="4.2.2,7.4.2,8.1.0-alpha10"/> + <builder versions="4.2.2,7.4.2,8.1.0-alpha10"/> + <builder-model versions="4.2.2,7.4.2,8.1.0-alpha10"/> + <builder-test-api versions="4.2.2,7.4.2,8.1.0-alpha10"/> + <bundletool versions="0.15.0,1.14.0"/> + <gradle versions="4.2.2,7.4.2,8.1.0-alpha10"/> + <gradle-api versions="4.2.2,7.4.2,8.1.0-alpha10"/> <gradle-core versions="3.1.4,3.2.0-alpha10"/> <gradle-experimental versions="0.11.1"/> - <manifest-merger versions="27.2.2,30.1.2,30.3.0-alpha07"/> + <gradle-settings versions="7.4.2,8.1.0-alpha10"/> + <gradle-settings-api versions="7.4.2,8.1.0-alpha10"/> + <manifest-merger versions="27.2.2,30.4.2,31.1.0-alpha10"/> <transform-api versions="2.0.0-deprecated-use-gradle-api"/> </com.android.tools.build> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/chunkio/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/chunkio/group-index.xml index daac9c37d7..4fef22c8af 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/chunkio/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/chunkio/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools.chunkio> - <chunkio versions="27.2.2,30.1.2,30.3.0-alpha07"/> + <chunkio versions="27.2.2,30.4.2,31.1.0-alpha10"/> </com.android.tools.chunkio> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/ddms/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/ddms/group-index.xml index 15c59cfbf8..09b42ac066 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/ddms/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/ddms/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools.ddms> - <ddmlib versions="27.2.2,30.1.2,30.3.0-alpha07"/> + <ddmlib versions="27.2.2,30.4.2,31.1.0-alpha10"/> </com.android.tools.ddms> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/emulator/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/emulator/group-index.xml index 6ace642a06..7c62badcb6 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/emulator/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/emulator/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools.emulator> - <proto versions="30.1.2,30.3.0-alpha07"/> + <proto versions="30.4.2,31.1.0-alpha10"/> </com.android.tools.emulator> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/external/com-intellij/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/external/com-intellij/group-index.xml index 8309481a24..6ad95c9edd 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/external/com-intellij/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/external/com-intellij/group-index.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools.external.com-intellij> - <intellij-core versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <kotlin-compiler versions="27.2.2,30.1.2,30.3.0-alpha07"/> + <intellij-core versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <kotlin-compiler versions="27.2.2,30.4.2,31.1.0-alpha10"/> <uast versions="171.4249.33"/> </com.android.tools.external.com-intellij> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/external/org-jetbrains/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/external/org-jetbrains/group-index.xml index 52c7ec0d5f..4608cfedbf 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/external/org-jetbrains/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/external/org-jetbrains/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools.external.org-jetbrains> - <uast versions="27.2.2,30.1.2,30.3.0-alpha07"/> + <uast versions="27.2.2,30.4.2,31.1.0-alpha10"/> </com.android.tools.external.org-jetbrains> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/fakeadbserver/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/fakeadbserver/group-index.xml index ae5b48887c..56c412c388 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/fakeadbserver/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/fakeadbserver/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools.fakeadbserver> - <fakeadbserver versions="27.2.2,30.1.2,30.3.0-alpha07"/> + <fakeadbserver versions="27.2.2,30.4.2,31.1.0-alpha10"/> </com.android.tools.fakeadbserver> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/group-index.xml index d4739bff7c..383ce41113 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/group-index.xml @@ -1,18 +1,22 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools> - <annotations versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <common versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <desugar_jdk_libs versions="1.1.5"/> - <desugar_jdk_libs_configuration versions="0.12.0,1.1.5"/> + <annotations versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <common versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <desugar_jdk_libs versions="1.2.2,2.0.2"/> + <desugar_jdk_libs_configuration versions="1.2.2,2.0.2"/> + <desugar_jdk_libs_configuration_minimal versions="2.0.2"/> + <desugar_jdk_libs_configuration_nio versions="2.0.2"/> + <desugar_jdk_libs_minimal versions="2.0.2"/> + <desugar_jdk_libs_nio versions="2.0.2"/> <devicelib versions="26.6.4,27.0.0-alpha01"/> - <draw9patch versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <dvlib versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <ninepatch versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <play-sdk-proto versions="30.3.0-alpha07"/> - <r8 versions="2.2.64,3.1.51"/> - <repository versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <sdk-common versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <sdklib versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <testutils versions="27.2.2,30.1.2,30.3.0-alpha07"/> + <draw9patch versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <dvlib versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <ninepatch versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <play-sdk-proto versions="30.4.2,31.1.0-alpha10"/> + <r8 versions="4.0.52,8.0.34"/> + <repository versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <sdk-common versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <sdklib versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <testutils versions="27.2.2,30.4.2,31.1.0-alpha10"/> </com.android.tools> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/layoutlib/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/layoutlib/group-index.xml index b3bfc3b61f..e0ee254681 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/layoutlib/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/layoutlib/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools.layoutlib> - <layoutlib-api versions="27.2.2,30.1.2,30.3.0-alpha07"/> + <layoutlib-api versions="27.2.2,30.4.2,31.1.0-alpha10"/> </com.android.tools.layoutlib> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/lint/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/lint/group-index.xml index 7f8182e033..6934a008a4 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/lint/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/lint/group-index.xml @@ -1,13 +1,13 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools.lint> - <lint versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <lint-api versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <lint-checks versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <lint-gradle versions="27.2.2,30.1.2,30.3.0-alpha07"/> + <lint versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <lint-api versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <lint-checks versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <lint-gradle versions="27.2.2,30.4.2,31.1.0-alpha10"/> <lint-gradle-api versions="26.6.4,27.2.2,30.0.0-alpha05"/> <lint-kotlin versions="26.2.1,26.3.0-alpha12"/> - <lint-model versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <lint-tests versions="27.2.2,30.1.2,30.3.0-alpha07"/> - <lint-typedef-remover versions="30.3.0-alpha07"/> + <lint-model versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <lint-tests versions="27.2.2,30.4.2,31.1.0-alpha10"/> + <lint-typedef-remover versions="30.4.2,31.1.0-alpha10"/> </com.android.tools.lint> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/metalava/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/metalava/group-index.xml index f195fecaaf..d1437de384 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/metalava/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/metalava/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools.metalava> - <metalava versions="1.0.0-alpha05"/> + <metalava versions="1.0.0-alpha07"/> </com.android.tools.metalava> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/pixelprobe/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/pixelprobe/group-index.xml index ff17d90efe..291dc6d5f1 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/pixelprobe/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/pixelprobe/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools.pixelprobe> - <pixelprobe versions="27.2.2,30.1.2,30.3.0-alpha07"/> + <pixelprobe versions="27.2.2,30.4.2,31.1.0-alpha10"/> </com.android.tools.pixelprobe> diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/smali/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/smali/group-index.xml new file mode 100644 index 0000000000..084a200ad7 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/smali/group-index.xml @@ -0,0 +1,8 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.android.tools.smali> + <smali versions="3.0.2"/> + <smali-baksmali versions="3.0.2"/> + <smali-dexlib2 versions="3.0.2"/> + <smali-util versions="3.0.2"/> +</com.android.tools.smali> + diff --git a/sdk-common/src/main/resources/versions-offline/com/android/tools/utp/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/android/tools/utp/group-index.xml index 538c75531d..21b3066eb1 100644 --- a/sdk-common/src/main/resources/versions-offline/com/android/tools/utp/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/android/tools/utp/group-index.xml @@ -1,19 +1,24 @@ <?xml version='1.0' encoding='UTF-8'?> <com.android.tools.utp> - <android-device-provider-ddmlib versions="30.1.2,30.3.0-alpha07"/> - <android-device-provider-ddmlib-proto versions="30.1.2,30.3.0-alpha07"/> - <android-device-provider-gradle versions="30.1.2,30.3.0-alpha07"/> - <android-device-provider-gradle-proto versions="30.1.2,30.3.0-alpha07"/> - <android-test-plugin-host-additional-test-output versions="30.1.2,30.3.0-alpha07"/> - <android-test-plugin-host-additional-test-output-proto versions="30.1.2,30.3.0-alpha07"/> - <android-test-plugin-host-coverage versions="30.1.2,30.3.0-alpha07"/> - <android-test-plugin-host-coverage-proto versions="30.1.2,30.3.0-alpha07"/> - <android-test-plugin-host-device-info versions="30.1.2,30.3.0-alpha07"/> - <android-test-plugin-host-device-info-proto versions="30.1.2,30.3.0-alpha07"/> - <android-test-plugin-host-logcat versions="30.1.2,30.3.0-alpha07"/> - <android-test-plugin-host-retention versions="30.1.2,30.3.0-alpha07"/> - <android-test-plugin-host-retention-proto versions="30.1.2,30.3.0-alpha07"/> - <android-test-plugin-result-listener-gradle versions="30.1.2,30.3.0-alpha07"/> - <android-test-plugin-result-listener-gradle-proto versions="30.1.2,30.3.0-alpha07"/> + <android-device-provider-ddmlib versions="30.4.2,31.1.0-alpha10"/> + <android-device-provider-ddmlib-proto versions="30.4.2,31.1.0-alpha10"/> + <android-device-provider-gradle versions="30.4.2,31.1.0-alpha10"/> + <android-device-provider-gradle-proto versions="30.4.2,31.1.0-alpha10"/> + <android-test-plugin-host-additional-test-output versions="30.4.2,31.1.0-alpha10"/> + <android-test-plugin-host-additional-test-output-proto versions="30.4.2,31.1.0-alpha10"/> + <android-test-plugin-host-apk-installer versions="31.1.0-alpha10"/> + <android-test-plugin-host-apk-installer-proto versions="31.1.0-alpha10"/> + <android-test-plugin-host-coverage versions="30.4.2,31.1.0-alpha10"/> + <android-test-plugin-host-coverage-proto versions="30.4.2,31.1.0-alpha10"/> + <android-test-plugin-host-device-info versions="30.4.2,31.1.0-alpha10"/> + <android-test-plugin-host-device-info-proto versions="30.4.2,31.1.0-alpha10"/> + <android-test-plugin-host-emulator-control versions="31.1.0-alpha10"/> + <android-test-plugin-host-emulator-control-proto versions="31.1.0-alpha10"/> + <android-test-plugin-host-logcat versions="30.4.2,31.1.0-alpha10"/> + <android-test-plugin-host-logcat-proto versions="31.1.0-alpha10"/> + <android-test-plugin-host-retention versions="30.4.2,31.1.0-alpha10"/> + <android-test-plugin-host-retention-proto versions="30.4.2,31.1.0-alpha10"/> + <android-test-plugin-result-listener-gradle versions="30.4.2,31.1.0-alpha10"/> + <android-test-plugin-result-listener-gradle-proto versions="30.4.2,31.1.0-alpha10"/> </com.android.tools.utp> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/ads/interactivemedia/v3/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/ads/interactivemedia/v3/group-index.xml index 2245a628d5..ce52333ebe 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/ads/interactivemedia/v3/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/ads/interactivemedia/v3/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.ads.interactivemedia.v3> - <interactivemedia versions="3.27.0"/> + <interactivemedia versions="3.29.0"/> </com.google.ads.interactivemedia.v3> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/ads/mediation/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/ads/mediation/group-index.xml index afd9bdf3ef..254f30b654 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/ads/mediation/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/ads/mediation/group-index.xml @@ -1,22 +1,23 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.ads.mediation> - <adcolony versions="4.7.0.0"/> - <applovin versions="10.3.5.0,11.3.1.0"/> - <chartboost versions="8.3.1.0"/> - <facebook versions="6.8.0.0"/> - <fyber versions="7.8.4.0,8.1.3.0"/> - <imobile versions="2.0.23.0"/> - <inmobi versions="9.2.1.0,10.0.5.0"/> - <ironsource versions="7.2.1.0"/> + <adcolony versions="4.8.0.0"/> + <applovin versions="10.3.5.0,11.8.2.0"/> + <chartboost versions="8.4.3.0,9.2.1.0"/> + <facebook versions="6.13.7.0"/> + <fyber versions="7.8.4.0,8.2.2.0"/> + <imobile versions="2.3.0.0"/> + <inmobi versions="9.2.1.0,10.5.4.0"/> + <ironsource versions="7.2.7.0"/> <maio versions="1.1.16.0"/> + <mintegral versions="16.3.91.0"/> <mopub versions="5.18.0.0"/> - <mytarget versions="5.15.0.0"/> - <nend versions="7.1.0.0,8.1.0.0"/> - <pangle versions="4.3.0.4.0"/> - <snap versions="2.3.2.0"/> - <tapjoy versions="12.9.0.0"/> - <unity versions="3.7.5.0,4.1.0.0"/> + <mytarget versions="5.16.4.0"/> + <nend versions="8.2.0.0,9.0.0.0"/> + <pangle versions="4.9.0.6.0,5.0.1.0.0"/> + <snap versions="2.3.4.0"/> + <tapjoy versions="12.11.1.0"/> + <unity versions="3.7.5.0,4.6.1.0"/> <verizonmedia versions="1.14.0.0"/> - <vungle versions="6.10.5.0"/> + <vungle versions="6.12.1.0"/> </com.google.ads.mediation> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/ambient/crossdevice/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/ambient/crossdevice/group-index.xml new file mode 100644 index 0000000000..40ec1ddde5 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/google/ambient/crossdevice/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.google.ambient.crossdevice> + <crossdevice versions="0.1.0-preview01"/> +</com.google.ambient.crossdevice> + diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/ads/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/ads/group-index.xml index 371c12a90b..71e14d9ff9 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/android/ads/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/ads/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.android.ads> - <mediation-test-suite versions="1.5.0,2.0.0"/> + <mediation-test-suite versions="2.0.0,3.0.0"/> </com.google.android.ads> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/apps/common/testing/accessibility/framework/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/apps/common/testing/accessibility/framework/group-index.xml index 6b298904c0..fc4d9f5fcf 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/android/apps/common/testing/accessibility/framework/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/apps/common/testing/accessibility/framework/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.android.apps.common.testing.accessibility.framework> - <accessibility-test-framework versions="3.1.2"/> + <accessibility-test-framework versions="3.1.2,4.0.0"/> </com.google.android.apps.common.testing.accessibility.framework> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/car/connectionservice/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/car/connectionservice/group-index.xml new file mode 100644 index 0000000000..11da8bb586 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/car/connectionservice/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.google.android.car.connectionservice> + <connectionservice versions="1.2.1,2.0.8"/> +</com.google.android.car.connectionservice> + diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/datatransport/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/datatransport/group-index.xml index d11422dd66..4de75e3efd 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/android/datatransport/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/datatransport/group-index.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.android.datatransport> <transport-api versions="2.2.1,3.0.0"/> - <transport-backend-cct versions="2.3.3,3.1.2"/> - <transport-runtime versions="2.2.6,3.1.2"/> + <transport-backend-cct versions="2.3.3,3.1.9"/> + <transport-runtime versions="2.2.6,3.1.9"/> </com.google.android.datatransport> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/exoplayer/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/exoplayer/group-index.xml index 2f1f88ec4f..dd9e049463 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/android/exoplayer/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/exoplayer/group-index.xml @@ -1,30 +1,31 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.android.exoplayer> - <exoplayer versions="2.17.1"/> - <exoplayer-common versions="2.17.1"/> - <exoplayer-core versions="2.17.1"/> - <exoplayer-dash versions="2.17.1"/> - <exoplayer-database versions="2.17.1"/> - <exoplayer-datasource versions="2.17.1"/> - <exoplayer-decoder versions="2.17.1"/> - <exoplayer-extractor versions="2.17.1"/> - <exoplayer-hls versions="2.17.1"/> - <exoplayer-robolectricutils versions="2.17.1"/> - <exoplayer-rtsp versions="2.17.1"/> - <exoplayer-smoothstreaming versions="2.17.1"/> - <exoplayer-testutils versions="2.17.1"/> - <exoplayer-transformer versions="2.17.1"/> - <exoplayer-ui versions="2.17.1"/> - <extension-cast versions="2.17.1"/> - <extension-cronet versions="2.17.1"/> + <exoplayer versions="2.18.5"/> + <exoplayer-common versions="2.18.5"/> + <exoplayer-core versions="2.18.5"/> + <exoplayer-dash versions="2.18.5"/> + <exoplayer-database versions="2.18.5"/> + <exoplayer-datasource versions="2.18.5"/> + <exoplayer-decoder versions="2.18.5"/> + <exoplayer-effect versions="2.18.5"/> + <exoplayer-extractor versions="2.18.5"/> + <exoplayer-hls versions="2.18.5"/> + <exoplayer-robolectricutils versions="2.18.5"/> + <exoplayer-rtsp versions="2.18.5"/> + <exoplayer-smoothstreaming versions="2.18.5"/> + <exoplayer-testutils versions="2.18.5"/> + <exoplayer-transformer versions="2.18.5"/> + <exoplayer-ui versions="2.18.5"/> + <extension-cast versions="2.18.5"/> + <extension-cronet versions="2.18.5"/> <extension-gvr versions="2.15.1"/> - <extension-ima versions="2.17.1"/> + <extension-ima versions="2.18.5"/> <extension-jobdispatcher versions="2.13.3"/> - <extension-leanback versions="2.17.1"/> - <extension-media2 versions="2.17.1"/> - <extension-mediasession versions="2.17.1"/> - <extension-okhttp versions="2.17.1"/> - <extension-rtmp versions="2.17.1"/> - <extension-workmanager versions="2.17.1"/> + <extension-leanback versions="2.18.5"/> + <extension-media2 versions="2.18.5"/> + <extension-mediasession versions="2.18.5"/> + <extension-okhttp versions="2.18.5"/> + <extension-rtmp versions="2.18.5"/> + <extension-workmanager versions="2.18.5"/> </com.google.android.exoplayer> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/fhir/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/fhir/group-index.xml index bf95aa961b..f24e94fbf4 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/android/fhir/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/fhir/group-index.xml @@ -1,8 +1,8 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.android.fhir> - <common versions="0.1.0-alpha02"/> - <data-capture versions="0.1.0-beta02"/> - <engine versions="0.1.0-alpha06"/> - <workflow versions="0.1.0-alpha01"/> + <common versions="0.1.0-alpha03"/> + <data-capture versions="1.0.0"/> + <engine versions="0.1.0-beta02"/> + <workflow versions="0.1.0-alpha02"/> </com.google.android.fhir> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/gms/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/gms/group-index.xml index ef5c29a4d7..10f9b44046 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/android/gms/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/gms/group-index.xml @@ -1,94 +1,103 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.android.gms> <auth-api-impl versions="11.6.0"/> - <oss-licenses-plugin versions="0.10.5"/> + <oss-licenses-plugin versions="0.10.6"/> <play-services versions="11.8.0,12.0.1"/> - <play-services-ads versions="19.8.0,20.6.0"/> - <play-services-ads-base versions="19.8.0,20.6.0"/> + <play-services-ads versions="20.6.0,21.5.0"/> + <play-services-ads-base versions="20.6.0,21.5.0"/> <play-services-ads-identifier versions="17.1.0,18.0.1"/> <play-services-ads-license versions="11.8.0,12.0.1"/> - <play-services-ads-lite versions="19.8.0,20.6.0"/> + <play-services-ads-lite versions="20.6.0,21.5.0"/> <play-services-ads-lite-license versions="11.8.0,12.0.1"/> <play-services-afs-native versions="18.1.0,19.0.3"/> <play-services-all-wear versions="12.0.1,15.0.1"/> - <play-services-analytics versions="17.0.1,18.0.1"/> - <play-services-analytics-impl versions="17.0.1,18.0.1"/> + <play-services-analytics versions="17.0.1,18.0.2"/> + <play-services-analytics-impl versions="17.0.1,18.0.2"/> <play-services-analytics-impl-license versions="11.8.0,12.0.1"/> <play-services-analytics-license versions="11.8.0,12.0.1"/> + <play-services-appindex versions="16.1.0"/> <play-services-appindexing versions="8.4.0,9.8.0"/> <play-services-appinvite versions="17.0.0,18.0.0"/> <play-services-appinvite-license versions="11.8.0,12.0.1"/> <play-services-appset versions="16.0.2"/> <play-services-appstate versions="7.8.0,8.4.0"/> <play-services-audience versions="16.0.0,17.0.0"/> - <play-services-auth versions="19.2.0,20.1.0"/> + <play-services-auth versions="19.2.0,20.4.1"/> <play-services-auth-api-phone versions="17.5.1,18.0.1"/> <play-services-auth-api-phone-license versions="11.8.0,12.0.1"/> - <play-services-auth-base versions="17.1.4,18.0.2"/> + <play-services-auth-base versions="17.1.4,18.0.7"/> <play-services-auth-base-license versions="11.8.0,12.0.1"/> - <play-services-auth-blockstore versions="16.1.0"/> + <play-services-auth-blockstore versions="16.2.0"/> <play-services-auth-license versions="11.4.2"/> <play-services-awareness versions="18.0.2,19.0.1"/> <play-services-awareness-license versions="11.8.0,12.0.1"/> - <play-services-base versions="17.6.0,18.0.1"/> + <play-services-base versions="17.6.0,18.2.0"/> <play-services-base-license versions="11.8.0,12.0.1"/> - <play-services-basement versions="17.6.0,18.0.1"/> + <play-services-base-testing versions="16.0.0"/> + <play-services-basement versions="17.6.0,18.2.0"/> <play-services-basement-license versions="11.8.0,12.0.1"/> - <play-services-cast versions="20.1.0,21.0.1"/> - <play-services-cast-framework versions="20.1.0,21.0.1"/> + <play-services-cast versions="20.1.0,21.2.0"/> + <play-services-cast-framework versions="20.1.0,21.2.0"/> <play-services-cast-framework-license versions="11.8.0,12.0.1"/> <play-services-cast-license versions="11.8.0,12.0.1"/> - <play-services-cast-tv versions="18.0.0,19.0.1"/> + <play-services-cast-tv versions="19.0.1,20.0.0"/> <play-services-clearcut versions="16.0.0,17.0.0"/> <play-services-cloud-messaging versions="16.0.0,17.0.2"/> + <play-services-code-scanner versions="16.0.0"/> <play-services-contextmanager versions="9.4.0"/> <play-services-cronet versions="17.0.1,18.0.1"/> + <play-services-deviceperformance versions="16.0.0"/> <play-services-drive versions="16.1.0,17.0.0"/> <play-services-drive-license versions="11.8.0,12.0.1"/> - <play-services-fido versions="17.0.0,18.1.0,19.0.0-beta"/> + <play-services-dtdi versions="16.0.0-beta01"/> + <play-services-fido versions="18.1.0,19.0.1"/> <play-services-fido-license versions="11.8.0,12.0.1"/> - <play-services-fitness versions="20.0.0,21.0.1"/> + <play-services-fitness versions="20.0.0,21.1.0"/> <play-services-fitness-license versions="11.8.0,12.0.1"/> <play-services-flags versions="17.0.1,18.0.1"/> - <play-services-games versions="21.0.0,22.0.1"/> + <play-services-games versions="22.0.1,23.1.0"/> <play-services-games-license versions="11.8.0,12.0.1"/> <play-services-games-v2 versions="17.0.0"/> + <play-services-games-v2-native-c versions="17.0.0-beta1"/> <play-services-gass versions="19.8.0,20.0.0"/> <play-services-gass-license versions="11.8.0,12.0.1"/> <play-services-gcm versions="16.1.0,17.0.0"/> <play-services-gcm-license versions="11.8.0,12.0.1"/> + <play-services-gni-native-c versions="1.0.0-beta2"/> + <play-services-home versions="16.0.0"/> <play-services-identity versions="17.0.1,18.0.1"/> <play-services-identity-license versions="11.8.0,12.0.1"/> <play-services-iid versions="16.0.1,17.0.0"/> <play-services-iid-license versions="11.8.0,12.0.1"/> <play-services-instantapps versions="17.0.1,18.0.1"/> <play-services-instantapps-license versions="11.8.0,12.0.1"/> - <play-services-location versions="18.0.0,19.0.1"/> + <play-services-location versions="20.0.0,21.0.1"/> <play-services-location-license versions="11.8.0,12.0.1"/> - <play-services-maps versions="17.0.1,18.0.2"/> + <play-services-maps versions="17.0.1,18.1.0"/> <play-services-maps-license versions="11.8.0,12.0.1"/> - <play-services-measurement versions="19.0.2,20.1.2"/> - <play-services-measurement-api versions="19.0.2,20.1.2"/> - <play-services-measurement-base versions="19.0.2,20.1.2"/> - <play-services-measurement-impl versions="19.0.2,20.1.2"/> - <play-services-measurement-sdk versions="19.0.2,20.1.2"/> - <play-services-measurement-sdk-api versions="19.0.2,20.1.2"/> - <play-services-mlkit-barcode-scanning versions="17.0.0,18.0.0"/> - <play-services-mlkit-face-detection versions="16.2.1,17.0.1"/> - <play-services-mlkit-image-labeling versions="16.0.7"/> - <play-services-mlkit-image-labeling-custom versions="16.0.0-beta3"/> - <play-services-mlkit-language-id versions="17.0.0-beta1"/> - <play-services-mlkit-text-recognition versions="17.0.1,18.0.0"/> - <play-services-mlkit-text-recognition-common versions="16.1.0,17.0.0"/> - <play-services-nearby versions="17.0.0,18.0.2"/> + <play-services-measurement versions="20.1.2,21.2.1"/> + <play-services-measurement-api versions="20.1.2,21.2.1"/> + <play-services-measurement-base versions="20.1.2,21.2.1"/> + <play-services-measurement-impl versions="20.1.2,21.2.1"/> + <play-services-measurement-sdk versions="20.1.2,21.2.1"/> + <play-services-measurement-sdk-api versions="20.1.2,21.2.1"/> + <play-services-mlkit-barcode-scanning versions="17.0.0,18.2.0"/> + <play-services-mlkit-face-detection versions="16.2.1,17.1.0"/> + <play-services-mlkit-image-labeling versions="16.0.8"/> + <play-services-mlkit-image-labeling-custom versions="16.0.0-beta4"/> + <play-services-mlkit-language-id versions="17.0.0"/> + <play-services-mlkit-smart-reply versions="16.0.0-beta1"/> + <play-services-mlkit-text-recognition versions="17.0.1,18.0.2"/> + <play-services-mlkit-text-recognition-common versions="17.1.0,18.0.0"/> + <play-services-nearby versions="17.0.0,18.5.0"/> <play-services-nearby-license versions="11.8.0,12.0.1"/> <play-services-oss-licenses versions="16.0.2,17.0.0"/> <play-services-oss-licenses-license versions="11.8.0,12.0.1"/> - <play-services-pal versions="18.0.0,19.0.0"/> + <play-services-pal versions="19.0.0,20.0.1"/> <play-services-panorama versions="16.0.0,17.0.0"/> <play-services-panorama-license versions="11.8.0,12.0.1"/> <play-services-password-complexity versions="17.0.1,18.0.1"/> - <play-services-pay versions="16.0.3"/> + <play-services-pay versions="16.1.0"/> <play-services-phenotype versions="16.0.0,17.0.0"/> <play-services-places versions="16.1.0,17.0.0"/> <play-services-places-license versions="11.8.0,12.0.1"/> @@ -99,18 +108,21 @@ <play-services-safetynet versions="17.0.1,18.0.1"/> <play-services-safetynet-license versions="11.8.0,12.0.1"/> <play-services-stats versions="16.0.1,17.0.3"/> - <play-services-streamprotect versions="16.0.2"/> - <play-services-tagmanager versions="17.0.1,18.0.1"/> - <play-services-tagmanager-api versions="17.0.1,18.0.1"/> + <play-services-streamprotect versions="16.1.0"/> + <play-services-tagmanager versions="17.0.1,18.0.2"/> + <play-services-tagmanager-api versions="17.0.1,18.0.2"/> <play-services-tagmanager-api-license versions="11.8.0,12.0.1"/> <play-services-tagmanager-license versions="11.8.0,12.0.1"/> - <play-services-tagmanager-v4-impl versions="17.0.1,18.0.1"/> + <play-services-tagmanager-v4-impl versions="17.0.1,18.0.2"/> <play-services-tagmanager-v4-impl-license versions="11.8.0,12.0.1"/> - <play-services-tasks versions="17.2.1,18.0.1"/> + <play-services-tasks versions="17.2.1,18.0.2"/> <play-services-tasks-license versions="11.8.0,12.0.1"/> - <play-services-tflite-impl versions="16.0.0-beta01"/> - <play-services-tflite-java versions="16.0.0-beta01"/> - <play-services-tflite-support versions="16.0.0-beta01"/> + <play-services-tasks-native-c versions="18.0.2-beta1"/> + <play-services-tflite-gpu versions="16.1.0"/> + <play-services-tflite-impl versions="16.0.1"/> + <play-services-tflite-java versions="16.0.1"/> + <play-services-tflite-support versions="16.0.1"/> + <play-services-threadnetwork versions="16.0.0"/> <play-services-vision versions="19.0.0,20.1.3"/> <play-services-vision-common versions="18.0.0,19.1.3"/> <play-services-vision-common-license versions="11.8.0,12.0.1"/> @@ -120,8 +132,8 @@ <play-services-vision-license versions="11.8.0,12.0.1"/> <play-services-wallet versions="18.1.3,19.1.0"/> <play-services-wallet-license versions="11.8.0,12.0.1"/> - <play-services-wearable versions="16.0.1,17.1.0"/> + <play-services-wearable versions="17.1.0,18.0.0"/> <play-services-wearable-license versions="11.8.0,12.0.1"/> - <strict-version-matcher-plugin versions="1.2.2"/> + <strict-version-matcher-plugin versions="1.2.4"/> </com.google.android.gms> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/cloud/telco/subgraph/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/cloud/telco/subgraph/group-index.xml new file mode 100644 index 0000000000..56f9c61509 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/cloud/telco/subgraph/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.google.android.libraries.cloud.telco.subgraph> + <cloud_telco_subgraph versions="0.5.0"/> +</com.google.android.libraries.cloud.telco.subgraph> + diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/healthdata/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/healthdata/group-index.xml index 2d341038d2..a37d9577cd 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/healthdata/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/healthdata/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.android.libraries.healthdata> - <health-data-api versions="1.0.1-alpha01"/> + <health-data-api versions="1.1.0-alpha01"/> </com.google.android.libraries.healthdata> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/identity/googleid/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/identity/googleid/group-index.xml new file mode 100644 index 0000000000..922b302c1f --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/identity/googleid/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.google.android.libraries.identity.googleid> + <googleid versions="0.0.2,1.0.0"/> +</com.google.android.libraries.identity.googleid> + diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/places/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/places/group-index.xml index 8b4ec14899..b0a85e2b64 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/places/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/places/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.android.libraries.places> - <places versions="1.1.0,2.5.0"/> - <places-compat versions="1.1.0,2.5.0"/> + <places versions="2.7.0,3.0.0"/> + <places-compat versions="1.1.0,2.6.0"/> </com.google.android.libraries.places> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/play/games/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/play/games/group-index.xml new file mode 100644 index 0000000000..4710d3b895 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/libraries/play/games/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.google.android.libraries.play.games> + <inputmapping versions="1.1.0-beta"/> +</com.google.android.libraries.play.games> + diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/livesharing/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/livesharing/group-index.xml new file mode 100644 index 0000000000..d21cef15ed --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/livesharing/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.google.android.livesharing> + <livesharing versions="1.2.0,2.0.0-alpha01"/> +</com.google.android.livesharing> + diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/material/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/material/group-index.xml index 202f6d15a7..636f3f66bf 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/android/material/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/material/group-index.xml @@ -1,7 +1,8 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.android.material> - <compose-theme-adapter versions="1.1.6"/> - <compose-theme-adapter-3 versions="1.0.6"/> - <material versions="1.5.0,1.6.0-beta01"/> + <compose-theme-adapter versions="1.2.1"/> + <compose-theme-adapter-3 versions="1.1.1"/> + <compose-theme-adapter-core versions="1.0.1"/> + <material versions="1.8.0,1.9.0-beta01"/> </com.google.android.material> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/play/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/play/group-index.xml index e4d4b0e51e..dfd22e64f7 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/android/play/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/play/group-index.xml @@ -1,7 +1,16 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.android.play> + <app-update versions="2.0.1"/> + <app-update-ktx versions="2.0.1"/> + <asset-delivery versions="2.0.2"/> + <asset-delivery-ktx versions="2.0.1"/> <core versions="1.10.3"/> + <core-common versions="2.0.2"/> <core-ktx versions="1.8.1"/> - <integrity versions="1.0.1"/> + <feature-delivery versions="2.0.1"/> + <feature-delivery-ktx versions="2.0.1"/> + <integrity versions="1.1.0"/> + <review versions="2.0.1"/> + <review-ktx versions="2.0.1"/> </com.google.android.play> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/recaptcha/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/recaptcha/group-index.xml new file mode 100644 index 0000000000..c970a5b4dc --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/recaptcha/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.google.android.recaptcha> + <recaptcha versions="18.1.1"/> +</com.google.android.recaptcha> + diff --git a/sdk-common/src/main/resources/versions-offline/com/google/android/tv/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/android/tv/group-index.xml new file mode 100644 index 0000000000..2c3d0bbcf7 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/google/android/tv/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.google.android.tv> + <tv-ads versions="1.0.0-alpha02"/> +</com.google.android.tv> + diff --git a/sdk-common/src/main/resources/versions-offline/com/google/androidbrowserhelper/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/androidbrowserhelper/group-index.xml index 7dad5a7982..ee44d3562e 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/androidbrowserhelper/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/androidbrowserhelper/group-index.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.androidbrowserhelper> - <androidbrowserhelper versions="1.4.0,2.3.0"/> - <billing versions="1.0.0-alpha08"/> + <androidbrowserhelper versions="1.4.0,2.4.0"/> + <billing versions="1.0.0-alpha09"/> <locationdelegation versions="1.0.1"/> </com.google.androidbrowserhelper> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/ar/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/ar/group-index.xml index 5abfdef03c..611a292fe8 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/ar/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/ar/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.ar> - <core versions="0.91.0,1.30.0"/> + <core versions="0.91.0,1.36.0"/> </com.google.ar> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/assistant/suggestion/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/assistant/suggestion/group-index.xml index 24442a4a21..e7ad86ae80 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/assistant/suggestion/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/assistant/suggestion/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.assistant.suggestion> - <assistant-suggestions versions="2.1.0"/> + <assistant-suggestions versions="2.2.0"/> </com.google.assistant.suggestion> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/camerax/effects/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/camerax/effects/group-index.xml new file mode 100644 index 0000000000..a8fcb5c6ab --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/google/camerax/effects/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.google.camerax.effects> + <portrait versions="0.0.1"/> +</com.google.camerax.effects> + diff --git a/sdk-common/src/main/resources/versions-offline/com/google/d2c/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/d2c/group-index.xml new file mode 100644 index 0000000000..32e84ef0c5 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/google/d2c/group-index.xml @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.google.d2c> + <com.google.d2c.gradle.plugin versions="0.2.06"/> + <d2c-gradle-plugin versions="0.2.06"/> +</com.google.d2c> + diff --git a/sdk-common/src/main/resources/versions-offline/com/google/devtools/ksp/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/devtools/ksp/group-index.xml index e2ecd0dea6..307535a21d 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/devtools/ksp/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/devtools/ksp/group-index.xml @@ -1,9 +1,9 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.devtools.ksp> - <com.google.devtools.ksp.gradle.plugin versions="1.5.30-1.0.0-beta09"/> - <symbol-processing versions="1.5.30-1.0.0-beta09"/> - <symbol-processing-api versions="1.5.30-1.0.0-beta09"/> - <symbol-processing-cmdline versions="1.5.30-1.0.0-beta09"/> - <symbol-processing-gradle-plugin versions="1.5.30-1.0.0-beta09"/> + <com.google.devtools.ksp.gradle.plugin versions="1.5.30-1.0.0-beta08"/> + <symbol-processing versions="1.5.30-1.0.0-beta08"/> + <symbol-processing-api versions="1.5.30-1.0.0-beta08"/> + <symbol-processing-cmdline versions="1.5.30-1.0.0-beta08"/> + <symbol-processing-gradle-plugin versions="1.5.30-1.0.0-beta08"/> </com.google.devtools.ksp> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/firebase/appdistribution/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/firebase/appdistribution/group-index.xml index 2bc53aacee..5d5b5e46ba 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/firebase/appdistribution/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/firebase/appdistribution/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.firebase.appdistribution> - <com.google.firebase.appdistribution.gradle.plugin versions="2.2.0,3.0.1"/> + <com.google.firebase.appdistribution.gradle.plugin versions="3.2.0,4.0.0"/> </com.google.firebase.appdistribution> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/firebase/crashlytics/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/firebase/crashlytics/group-index.xml index 4e3db08550..2d667c1168 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/firebase/crashlytics/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/firebase/crashlytics/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.firebase.crashlytics> - <com.google.firebase.crashlytics.gradle.plugin versions="2.8.1"/> + <com.google.firebase.crashlytics.gradle.plugin versions="2.9.4"/> </com.google.firebase.crashlytics> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/firebase/firebase-perf/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/firebase/firebase-perf/group-index.xml index dac6b91a23..2dc1d1e8d5 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/firebase/firebase-perf/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/firebase/firebase-perf/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.firebase.firebase-perf> - <com.google.firebase.firebase-perf.gradle.plugin versions="1.4.1"/> + <com.google.firebase.firebase-perf.gradle.plugin versions="1.4.2"/> </com.google.firebase.firebase-perf> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/firebase/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/firebase/group-index.xml index 24283703b2..de6ebd10ba 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/firebase/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/firebase/group-index.xml @@ -1,88 +1,92 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.firebase> <crash-plugin versions="1.1.5"/> - <firebase-abt versions="20.0.0,21.0.1"/> - <firebase-ads versions="19.8.0,20.6.0"/> - <firebase-ads-lite versions="19.8.0,20.6.0"/> - <firebase-analytics versions="19.0.2,20.1.2"/> + <firebase-abt versions="20.0.0,21.1.1"/> + <firebase-ads versions="20.6.0,21.5.0"/> + <firebase-ads-lite versions="20.6.0,21.5.0"/> + <firebase-analytics versions="20.1.2,21.2.1"/> <firebase-analytics-impl versions="15.0.2,16.3.0"/> <firebase-analytics-impl-license versions="11.8.0,12.0.1"/> - <firebase-analytics-ktx versions="19.0.2,20.1.2"/> + <firebase-analytics-ktx versions="20.1.2,21.2.1"/> <firebase-analytics-license versions="11.8.0,12.0.1"/> - <firebase-annotations versions="16.1.0"/> - <firebase-appcheck versions="16.0.0-beta05"/> - <firebase-appcheck-debug versions="16.0.0-beta05"/> - <firebase-appcheck-debug-testing versions="16.0.0-beta05"/> - <firebase-appcheck-interop versions="16.0.0-beta05"/> - <firebase-appcheck-safetynet versions="16.0.0-beta05"/> - <firebase-appdistribution versions="16.0.0-beta01"/> - <firebase-appdistribution-gradle versions="2.2.0,3.0.1"/> - <firebase-appdistribution-ktx versions="16.0.0-beta01"/> + <firebase-annotations versions="16.2.0"/> + <firebase-appcheck versions="16.1.2"/> + <firebase-appcheck-debug versions="16.1.2"/> + <firebase-appcheck-debug-testing versions="16.1.2"/> + <firebase-appcheck-interop versions="16.1.1"/> + <firebase-appcheck-ktx versions="16.1.2"/> + <firebase-appcheck-playintegrity versions="16.1.2"/> + <firebase-appcheck-safetynet versions="16.1.2"/> + <firebase-appdistribution versions="16.0.0-beta07"/> + <firebase-appdistribution-api versions="16.0.0-beta07"/> + <firebase-appdistribution-api-ktx versions="16.0.0-beta07"/> + <firebase-appdistribution-gradle versions="3.2.0,4.0.0"/> + <firebase-appdistribution-ktx versions="16.0.0-beta02"/> <firebase-appindexing versions="19.2.0,20.0.0"/> <firebase-appindexing-license versions="11.8.0,12.0.1"/> - <firebase-auth versions="20.0.4,21.0.3"/> + <firebase-auth versions="20.0.4,21.1.0"/> <firebase-auth-common versions="9.8.0"/> <firebase-auth-impl versions="11.0.0,16.1.0"/> <firebase-auth-interop versions="19.0.2,20.0.0"/> - <firebase-auth-ktx versions="20.0.4,21.0.3"/> + <firebase-auth-ktx versions="20.0.4,21.1.0"/> <firebase-auth-license versions="11.8.0,12.0.1"/> <firebase-auth-module versions="9.8.0"/> - <firebase-bom versions="28.4.2,29.3.0"/> - <firebase-common versions="19.5.0,20.1.0"/> - <firebase-common-ktx versions="19.5.0,20.1.0"/> + <firebase-bom versions="30.5.0,31.3.0"/> + <firebase-common versions="19.5.0,20.3.2"/> + <firebase-common-ktx versions="19.5.0,20.3.2"/> <firebase-common-license versions="11.8.0,12.0.1"/> - <firebase-components versions="16.1.0,17.0.0"/> - <firebase-config versions="20.0.4,21.0.2"/> - <firebase-config-ktx versions="20.0.4,21.0.2"/> + <firebase-components versions="16.1.0,17.1.0"/> + <firebase-config versions="20.0.4,21.3.0"/> + <firebase-config-ktx versions="20.0.4,21.3.0"/> <firebase-config-license versions="11.8.0,12.0.1"/> - <firebase-core versions="19.0.2,20.1.2"/> + <firebase-core versions="20.1.2,21.1.1"/> <firebase-crash versions="15.0.2,16.2.1"/> <firebase-crash-license versions="11.8.0,12.0.1"/> - <firebase-crashlytics versions="17.4.1,18.2.9"/> - <firebase-crashlytics-buildtools versions="2.8.1"/> - <firebase-crashlytics-gradle versions="2.8.1"/> - <firebase-crashlytics-ktx versions="17.4.1,18.2.9"/> - <firebase-crashlytics-ndk versions="17.4.1,18.2.9"/> - <firebase-database versions="19.7.0,20.0.4"/> + <firebase-crashlytics versions="17.4.1,18.3.6"/> + <firebase-crashlytics-buildtools versions="2.9.4"/> + <firebase-crashlytics-gradle versions="2.9.4"/> + <firebase-crashlytics-ktx versions="17.4.1,18.3.6"/> + <firebase-crashlytics-ndk versions="17.4.1,18.3.6"/> + <firebase-database versions="19.7.0,20.1.0"/> <firebase-database-collection versions="17.0.1,18.0.1"/> <firebase-database-connection versions="15.0.1,16.0.2"/> <firebase-database-connection-license versions="11.8.0,12.0.1"/> - <firebase-database-ktx versions="19.7.0,20.0.4"/> + <firebase-database-ktx versions="19.7.0,20.1.0"/> <firebase-database-license versions="11.8.0,12.0.1"/> - <firebase-datatransport versions="17.0.11,18.1.1"/> - <firebase-dynamic-links versions="20.1.1,21.0.1"/> - <firebase-dynamic-links-ktx versions="20.1.1,21.0.1"/> + <firebase-datatransport versions="17.0.11,18.1.8"/> + <firebase-dynamic-links versions="20.1.1,21.1.0"/> + <firebase-dynamic-links-ktx versions="20.1.1,21.1.0"/> <firebase-dynamic-links-license versions="11.8.0,12.0.1"/> - <firebase-dynamic-module-support versions="16.0.0-beta01"/> + <firebase-dynamic-module-support versions="16.0.0-beta03"/> <firebase-encoders versions="16.1.0,17.0.0"/> - <firebase-encoders-json versions="17.1.0,18.0.0"/> + <firebase-encoders-json versions="17.1.0,18.0.1"/> <firebase-encoders-proto versions="16.0.0"/> - <firebase-firestore versions="23.0.4,24.1.0"/> - <firebase-firestore-ktx versions="23.0.4,24.1.0"/> - <firebase-functions versions="19.2.0,20.0.2"/> - <firebase-functions-ktx versions="19.2.0,20.0.2"/> + <firebase-firestore versions="23.0.4,24.4.5"/> + <firebase-firestore-ktx versions="23.0.4,24.4.5"/> + <firebase-functions versions="19.2.0,20.2.2"/> + <firebase-functions-ktx versions="19.2.0,20.2.2"/> <firebase-functions-license versions="12.0.1"/> <firebase-iid versions="20.3.0,21.1.0"/> <firebase-iid-interop versions="16.0.1,17.1.0"/> <firebase-iid-license versions="11.8.0,12.0.1"/> - <firebase-inappmessaging versions="19.1.5,20.1.2"/> - <firebase-inappmessaging-display versions="19.1.5,20.1.2"/> - <firebase-inappmessaging-display-ktx versions="19.1.5,20.1.2"/> - <firebase-inappmessaging-ktx versions="19.1.5,20.1.2"/> - <firebase-installations versions="16.3.5,17.0.1"/> - <firebase-installations-interop versions="16.0.1,17.0.1"/> - <firebase-installations-ktx versions="16.3.5,17.0.1"/> + <firebase-inappmessaging versions="19.1.5,20.3.1"/> + <firebase-inappmessaging-display versions="19.1.5,20.3.1"/> + <firebase-inappmessaging-display-ktx versions="19.1.5,20.3.1"/> + <firebase-inappmessaging-ktx versions="19.1.5,20.3.1"/> + <firebase-installations versions="16.3.5,17.1.3"/> + <firebase-installations-interop versions="16.0.1,17.1.0"/> + <firebase-installations-ktx versions="16.3.5,17.1.3"/> <firebase-invites versions="16.1.1,17.0.0"/> <firebase-measurement-connector versions="19.0.0,20.0.0"/> <firebase-measurement-connector-impl versions="16.0.1,17.0.5"/> - <firebase-messaging versions="22.0.0,23.0.2"/> - <firebase-messaging-directboot versions="22.0.0,23.0.2"/> - <firebase-messaging-ktx versions="22.0.0,23.0.2"/> + <firebase-messaging versions="22.0.0,23.1.2"/> + <firebase-messaging-directboot versions="22.0.0,23.1.2"/> + <firebase-messaging-ktx versions="22.0.0,23.1.2"/> <firebase-messaging-license versions="11.8.0,12.0.1"/> <firebase-ml-common versions="21.0.0,22.1.2"/> <firebase-ml-model-interpreter versions="21.0.0,22.0.4"/> - <firebase-ml-modeldownloader versions="23.0.1,24.0.3"/> - <firebase-ml-modeldownloader-ktx versions="23.0.1,24.0.3"/> + <firebase-ml-modeldownloader versions="23.0.1,24.1.2"/> + <firebase-ml-modeldownloader-ktx versions="23.0.1,24.1.2"/> <firebase-ml-natural-language versions="21.0.3,22.0.1"/> <firebase-ml-natural-language-language-id-model versions="19.0.1,20.0.8"/> <firebase-ml-natural-language-smart-reply versions="17.0.1,18.0.8"/> @@ -96,16 +100,16 @@ <firebase-ml-vision-image-label-model versions="19.0.0,20.0.2"/> <firebase-ml-vision-internal-vkp versions="16.0.2,17.0.2"/> <firebase-ml-vision-object-detection-model versions="18.0.0,19.0.6"/> - <firebase-perf versions="19.1.1,20.0.6"/> - <firebase-perf-ktx versions="19.1.1,20.0.6"/> + <firebase-perf versions="19.1.1,20.3.1"/> + <firebase-perf-ktx versions="19.1.1,20.3.1"/> <firebase-perf-license versions="11.8.0,12.0.1"/> <firebase-plugins versions="1.2.0,2.0.0"/> - <firebase-storage versions="19.2.2,20.0.1"/> + <firebase-storage versions="19.2.2,20.1.0"/> <firebase-storage-common versions="16.0.2,17.0.0"/> <firebase-storage-common-license versions="11.8.0,12.0.1"/> - <firebase-storage-ktx versions="19.2.2,20.0.1"/> + <firebase-storage-ktx versions="19.2.2,20.1.0"/> <firebase-storage-license versions="11.8.0,12.0.1"/> - <perf-plugin versions="1.4.1"/> + <perf-plugin versions="1.4.2"/> <protolite-well-known-types versions="17.1.1,18.0.0"/> <testlab-instr-lib versions="0.2"/> </com.google.firebase> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/firebase/testlab/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/firebase/testlab/group-index.xml new file mode 100644 index 0000000000..55646e0e15 --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/google/firebase/testlab/group-index.xml @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.google.firebase.testlab> + <com.google.firebase.testlab.gradle.plugin versions="0.0.1-alpha01"/> + <testlab-gradle-plugin versions="0.0.1-alpha01"/> +</com.google.firebase.testlab> + diff --git a/sdk-common/src/main/resources/versions-offline/com/google/gms/google-services/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/gms/google-services/group-index.xml index 154ce0de99..c536a79489 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/gms/google-services/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/gms/google-services/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.gms.google-services> - <com.google.gms.google-services.gradle.plugin versions="4.3.10"/> + <com.google.gms.google-services.gradle.plugin versions="4.3.15"/> </com.google.gms.google-services> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/gms/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/gms/group-index.xml index 466ceb98f1..0e10f9e089 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/gms/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/gms/group-index.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.gms> - <google-services versions="3.3.1,4.3.10"/> + <google-services versions="3.3.1,4.3.15"/> <oss-licenses versions="0.9.2"/> </com.google.gms> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/jacquard/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/jacquard/group-index.xml index a9831f692e..9857af40ac 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/jacquard/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/jacquard/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.jacquard> - <jacquard-sdk versions="0.2.0"/> + <jacquard-sdk versions="0.2.0,1.0.0"/> </com.google.jacquard> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/mediapipe/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/mediapipe/group-index.xml index e15d9bebaa..299d771d3a 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/mediapipe/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/mediapipe/group-index.xml @@ -1,8 +1,12 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.mediapipe> - <facedetection versions="0.8.9-alpha-5"/> - <facemesh versions="0.8.9-alpha-5"/> - <hands versions="0.8.9-alpha-5"/> - <solution-core versions="0.8.9-alpha-5"/> + <facedetection versions="0.9.2"/> + <facemesh versions="0.9.2"/> + <hands versions="0.9.2"/> + <solution-core versions="0.9.2"/> + <tasks-audio versions="0.1.0-alpha-6"/> + <tasks-core versions="0.1.0-alpha-6"/> + <tasks-text versions="0.1.0-alpha-6"/> + <tasks-vision versions="0.1.0-alpha-6"/> </com.google.mediapipe> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/mlkit/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/mlkit/group-index.xml index 9b9ac27b9a..2a0033ac36 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/mlkit/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/mlkit/group-index.xml @@ -1,40 +1,43 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.mlkit> <acceleration versions="16.0.0-beta1"/> - <barcode-scanning versions="16.2.0,17.0.2"/> + <barcode-scanning versions="16.2.0,17.1.0"/> <barcode-scanning-common versions="16.0.0,17.0.0"/> <camera versions="16.0.0-beta3"/> - <common versions="17.5.0,18.1.0"/> - <digital-ink-recognition versions="17.0.1,18.0.0"/> + <common versions="17.5.0,18.7.0"/> + <digital-ink-recognition versions="17.0.1,18.1.0"/> <entity-extraction versions="16.0.0-beta4"/> <face-detection versions="16.1.5"/> + <face-mesh-detection versions="16.0.0-beta1"/> <image-labeling versions="16.2.0,17.0.7"/> <image-labeling-automl versions="16.2.1"/> - <image-labeling-common versions="17.2.0,18.0.0"/> + <image-labeling-common versions="17.2.0,18.1.0"/> <image-labeling-custom versions="16.3.1,17.0.1"/> <image-labeling-custom-common versions="16.0.1,17.0.0"/> <image-labeling-default-common versions="16.0.2,17.0.0"/> - <language-id versions="16.1.1,17.0.3"/> + <language-id versions="16.1.1,17.0.4"/> + <language-id-common versions="16.1.0"/> <linkfirebase versions="16.1.1,17.0.0"/> - <mediapipe-internal versions="16.0.0,17.0.0-beta7"/> + <mediapipe-internal versions="16.0.0,17.0.0-beta8"/> <object-detection versions="16.2.8,17.0.0"/> <object-detection-common versions="17.2.0,18.0.0"/> <object-detection-custom versions="16.3.4,17.0.0"/> <playstore-dynamic-feature-support versions="16.0.0-beta2"/> - <pose-detection versions="16.0.0,17.0.0,18.0.0-beta2"/> - <pose-detection-accurate versions="17.0.0,18.0.0-beta2"/> - <pose-detection-common versions="17.0.0,18.0.0-beta2"/> + <pose-detection versions="16.0.0,17.0.0,18.0.0-beta3"/> + <pose-detection-accurate versions="17.0.0,18.0.0-beta3"/> + <pose-detection-common versions="17.0.0,18.0.0-beta3"/> <segmentation-selfie versions="16.0.0-beta4"/> - <smart-reply versions="16.2.0,17.0.0"/> - <text-recognition versions="16.0.0-beta3"/> - <text-recognition-bundled-common versions="16.0.0-beta3"/> - <text-recognition-chinese versions="16.0.0-beta3"/> - <text-recognition-devanagari versions="16.0.0-beta3"/> - <text-recognition-japanese versions="16.0.0-beta3"/> - <text-recognition-korean versions="16.0.0-beta3"/> - <translate versions="16.1.2,17.0.0"/> - <vision-common versions="16.7.0,17.1.0"/> - <vision-interfaces versions="16.0.0"/> + <smart-reply versions="16.2.0,17.0.2"/> + <smart-reply-common versions="16.1.0"/> + <text-recognition versions="16.0.0-beta6"/> + <text-recognition-bundled-common versions="16.0.0-beta6"/> + <text-recognition-chinese versions="16.0.0-beta6"/> + <text-recognition-devanagari versions="16.0.0-beta6"/> + <text-recognition-japanese versions="16.0.0-beta6"/> + <text-recognition-korean versions="16.0.0-beta6"/> + <translate versions="16.1.2,17.0.1"/> + <vision-common versions="16.7.0,17.3.0"/> + <vision-interfaces versions="16.2.0"/> <vision-internal-vkp versions="17.0.1,18.2.2"/> </com.google.mlkit> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/net/cronet/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/net/cronet/group-index.xml new file mode 100644 index 0000000000..8ff387e94f --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/google/net/cronet/group-index.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.google.net.cronet> + <cronet-okhttp versions="0.1.0"/> +</com.google.net.cronet> + diff --git a/sdk-common/src/main/resources/versions-offline/com/google/oboe/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/oboe/group-index.xml index df2c1dd592..34dddbe2fe 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/oboe/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/oboe/group-index.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.oboe> - <oboe versions="1.6.1"/> + <oboe versions="1.7.0"/> </com.google.oboe> diff --git a/sdk-common/src/main/resources/versions-offline/com/google/relay/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/relay/group-index.xml new file mode 100644 index 0000000000..96e565a4ff --- /dev/null +++ b/sdk-common/src/main/resources/versions-offline/com/google/relay/group-index.xml @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<com.google.relay> + <com.google.relay.gradle.plugin versions="0.3.04"/> + <relay-gradle-plugin versions="0.3.04"/> +</com.google.relay> + diff --git a/sdk-common/src/main/resources/versions-offline/com/google/testing/platform/group-index.xml b/sdk-common/src/main/resources/versions-offline/com/google/testing/platform/group-index.xml index 0ae69a151e..1fa0183f87 100644 --- a/sdk-common/src/main/resources/versions-offline/com/google/testing/platform/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/com/google/testing/platform/group-index.xml @@ -1,8 +1,13 @@ <?xml version='1.0' encoding='UTF-8'?> <com.google.testing.platform> + <android-device-controller-adb versions="0.0.4-dev"/> + <android-device-provider-gradle versions="0.0.8-alpha07"/> <android-device-provider-local versions="0.0.8-alpha08"/> + <android-device-provider-virtual versions="0.0.6-dev"/> <android-driver-instrumentation versions="0.0.8-alpha08"/> <android-test-plugin versions="0.0.8-alpha08"/> + <android-test-plugin-host-device-info versions="0.0.8-alpha07"/> + <android-test-plugin-host-retention versions="0.0.8-alpha07"/> <core versions="0.0.8-alpha08"/> <core-proto versions="0.0.8-alpha08"/> <launcher versions="0.0.8-alpha08"/> diff --git a/sdk-common/src/main/resources/versions-offline/master-index.xml b/sdk-common/src/main/resources/versions-offline/master-index.xml index b56b243169..369bdfd2cb 100644 --- a/sdk-common/src/main/resources/versions-offline/master-index.xml +++ b/sdk-common/src/main/resources/versions-offline/master-index.xml @@ -15,6 +15,10 @@ <androidx.arch.core/> <androidx.asynclayoutinflater/> <androidx.autofill/> + <androidx.baselineprofile/> + <androidx.baselineprofile.apptarget/> + <androidx.baselineprofile.consumer/> + <androidx.baselineprofile.producer/> <androidx.benchmark/> <androidx.biometric/> <androidx.browser/> @@ -36,6 +40,8 @@ <androidx.contentpager/> <androidx.coordinatorlayout/> <androidx.core/> + <androidx.core.uwb/> + <androidx.credentials/> <androidx.cursoradapter/> <androidx.customview/> <androidx.databinding/> @@ -52,11 +58,15 @@ <androidx.games/> <androidx.gaming/> <androidx.glance/> + <androidx.graphics/> <androidx.gridlayout/> <androidx.health/> + <androidx.health.connect/> <androidx.heifwriter/> <androidx.hilt/> + <androidx.input/> <androidx.interpolator/> + <androidx.javascriptengine/> <androidx.leanback/> <androidx.legacy/> <androidx.lifecycle/> @@ -76,6 +86,10 @@ <androidx.percentlayout/> <androidx.preference/> <androidx.print/> + <androidx.privacysandbox.ads/> + <androidx.privacysandbox.sdkruntime/> + <androidx.privacysandbox.tools/> + <androidx.privacysandbox.ui/> <androidx.profileinstaller/> <androidx.recommendation/> <androidx.recyclerview/> @@ -100,6 +114,7 @@ <androidx.textclassifier/> <androidx.tracing/> <androidx.transition/> + <androidx.tv/> <androidx.tvprovider/> <androidx.ui/> <androidx.vectordrawable/> @@ -108,10 +123,12 @@ <androidx.viewpager2/> <androidx.wear/> <androidx.wear.compose/> + <androidx.wear.protolayout/> <androidx.wear.tiles/> <androidx.wear.watchface/> <androidx.webkit/> <androidx.window/> + <androidx.window.extensions.core/> <androidx.work/> <com.android/> <com.android.application/> @@ -122,12 +139,16 @@ <com.android.car.ui/> <com.android.databinding/> <com.android.dynamic-feature/> + <com.android.fused-library/> <com.android.installreferrer/> + <com.android.internal.settings/> <com.android.java.tools.build/> <com.android.library/> <com.android.lint/> <com.android.ndk.thirdparty/> + <com.android.privacy-sandbox-sdk/> <com.android.reporting/> + <com.android.settings/> <com.android.support/> <com.android.support.constraint/> <com.android.support.test/> @@ -153,15 +174,18 @@ <com.android.tools.lint/> <com.android.tools.metalava/> <com.android.tools.pixelprobe/> + <com.android.tools.smali/> <com.android.tools.utp/> <com.android.volley/> <com.crashlytics.sdk.android/> <com.google.ads.afsn/> <com.google.ads.interactivemedia.v3/> <com.google.ads.mediation/> + <com.google.ambient.crossdevice/> <com.google.android.ads/> <com.google.android.ads.consent/> <com.google.android.apps.common.testing.accessibility.framework/> + <com.google.android.car.connectionservice/> <com.google.android.datatransport/> <com.google.android.enterprise.connectedapps/> <com.google.android.exoplayer/> @@ -173,17 +197,23 @@ <com.google.android.instantapps/> <com.google.android.instantapps.thirdpartycompat/> <com.google.android.libraries.car/> + <com.google.android.libraries.cloud.telco.subgraph/> <com.google.android.libraries.enterprise.amapi/> <com.google.android.libraries.healthdata/> + <com.google.android.libraries.identity.googleid/> <com.google.android.libraries.maps/> <com.google.android.libraries.mapsplatform.secrets-gradle-plugin/> <com.google.android.libraries.places/> + <com.google.android.libraries.play.games/> + <com.google.android.livesharing/> <com.google.android.material/> <com.google.android.mediahome/> <com.google.android.odml/> <com.google.android.play/> + <com.google.android.recaptcha/> <com.google.android.support/> <com.google.android.things/> + <com.google.android.tv/> <com.google.android.ump/> <com.google.android.wearable/> <com.google.androidbrowserhelper/> @@ -192,20 +222,25 @@ <com.google.ar.sceneform.ux/> <com.google.assistant.appactions/> <com.google.assistant.suggestion/> + <com.google.camerax.effects/> <com.google.chromeos/> + <com.google.d2c/> <com.google.devtools.ksp/> <com.google.fhir/> <com.google.firebase/> <com.google.firebase.appdistribution/> <com.google.firebase.crashlytics/> <com.google.firebase.firebase-perf/> + <com.google.firebase.testlab/> <com.google.gms/> <com.google.gms.google-services/> <com.google.jacquard/> <com.google.mediapipe/> <com.google.mlkit/> + <com.google.net.cronet/> <com.google.oboe/> <com.google.prefab/> + <com.google.relay/> <com.google.test.platform/> <com.google.testing.platform/> <io.fabric.sdk.android/> diff --git a/sdk-common/src/main/resources/versions-offline/org/chromium/net/group-index.xml b/sdk-common/src/main/resources/versions-offline/org/chromium/net/group-index.xml index 74a1336b18..e5a81dca2a 100644 --- a/sdk-common/src/main/resources/versions-offline/org/chromium/net/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/org/chromium/net/group-index.xml @@ -1,8 +1,8 @@ <?xml version='1.0' encoding='UTF-8'?> <org.chromium.net> - <cronet-api versions="95.4638.50,98.4758.101"/> - <cronet-common versions="95.4638.50,98.4758.101"/> - <cronet-embedded versions="95.4638.50,98.4758.101"/> - <cronet-fallback versions="95.4638.50,98.4758.101"/> + <cronet-api versions="106.5249.126,108.5359.79"/> + <cronet-common versions="106.5249.126,108.5359.79"/> + <cronet-embedded versions="106.5249.126,108.5359.79"/> + <cronet-fallback versions="106.5249.126,108.5359.79"/> </org.chromium.net> diff --git a/sdk-common/src/main/resources/versions-offline/org/jetbrains/kotlin/group-index.xml b/sdk-common/src/main/resources/versions-offline/org/jetbrains/kotlin/group-index.xml index 4c91e990b5..fbb17cf700 100644 --- a/sdk-common/src/main/resources/versions-offline/org/jetbrains/kotlin/group-index.xml +++ b/sdk-common/src/main/resources/versions-offline/org/jetbrains/kotlin/group-index.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <org.jetbrains.kotlin> <kotlin-compiler-embeddable versions="1.4.0-dev-withExperimentalGoogleExtensions-20200720"/> - <kotlin-ksp versions="1.4.0-rc-dev-experimental-20200828"/> - <kotlin-symbol-processing-api versions="1.4.0-rc-dev-experimental-20200828"/> + <kotlin-ksp versions="1.4.0-dev-experimental-20200828"/> + <kotlin-symbol-processing-api versions="1.4.0-dev-experimental-20200828"/> </org.jetbrains.kotlin> diff --git a/sdk-common/src/test/java/com/android/ide/common/gradle/ComponentTest.kt b/sdk-common/src/test/java/com/android/ide/common/gradle/ComponentTest.kt new file mode 100644 index 0000000000..bbcd614fd5 --- /dev/null +++ b/sdk-common/src/test/java/com/android/ide/common/gradle/ComponentTest.kt @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2023 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.ide.common.gradle + +import com.google.common.truth.Truth.assertThat +import org.junit.Assert.fail +import org.junit.Test + +class ComponentTest { + @Test + fun testParseAllPositions() { + val letters = "abcdefghijklmnopqrstuvwxyz" + for (i in 0..letters.length) { + for (j in i..letters.length) { + val id = "${letters.substring(0, i)}:${letters.substring(i, j)}:${letters.substring(j)}" + val component = Component.tryParse(id) + assertThat(Component.parse(id)).isEqualTo(component) + assertThat(component).isNotNull() + assertThat(component?.group).isEqualTo(letters.substring(0, i)) + assertThat(component?.name).isEqualTo(letters.substring(i, j)) + assertThat(component?.version).isEqualTo(Version.parse(letters.substring(j))) + assertThat(component?.toIdentifier()).isEqualTo(id) + assertThat(component?.toString()).isEqualTo(id) + } + } + } + + @Test + fun testParseInvalidZeroColons() { + val numbers = "0123456789" + assertThat(Component.tryParse(numbers)).isNull() + try { + Component.parse(numbers) + fail() + } + catch (_: IllegalArgumentException) { } + } + + @Test + fun testParseInvalidOneColon() { + val numbers = "0123456789" + for (i in 0..numbers.length) { + val id = "${numbers.substring(0, i)}:${numbers.substring(i)}" + assertThat(Component.tryParse(id)).isNull() + try { + Component.parse(id) + fail() + } catch (_: IllegalArgumentException) { } + } + } + + @Test + fun testParseThreeColons() { + val numbers = "0123456789" + for (i in 0..numbers.length) { + for (j in i..numbers.length) { + for (k in j..numbers.length) { + val id = numbers.run { "${substring(0, i)}:${substring(i, j)}:${substring(j, k)}:${substring(k)}" } + val component = Component.tryParse(id) + assertThat(component).isNotNull() + assertThat(Component.parse(id)).isEqualTo(component) + assertThat(component?.group).isEqualTo(numbers.substring(0, i)) + assertThat(component?.name).isEqualTo(numbers.substring(i, j)) + assertThat(component?.version).isEqualTo(Version.parse("${numbers.substring(j, k)}:${numbers.substring(k)}")) + assertThat(component?.toIdentifier()).isEqualTo(id) + assertThat(component?.toString()).isEqualTo(id) + } + } + } + } + + @Test + fun testToStringInvalid() { + val groups = listOf("abc", ":abc", "a:bc", "ab:c", "abc:") + val names = listOf("123", ":123", "1:23", "12:3", "123:") + for ((group, name) in groups.zip(names)) { + if (!group.contains(':') && !name.contains(':')) continue + val component = Component(Module(group, name), Version.parse("1.0")) + assertThat(component.toIdentifier()).isNull() + assertThat(component.toString()).matches("^Component\\(.*\\)$") + } + val component = Component("com.example", "foo", Version.prefixInfimum("1.0")) + assertThat(component.toIdentifier()).isNull() + assertThat(component.toString()).matches("^Component\\(.*\\)$") + } +} diff --git a/sdk-common/src/test/java/com/android/ide/common/gradle/ModuleTest.kt b/sdk-common/src/test/java/com/android/ide/common/gradle/ModuleTest.kt new file mode 100644 index 0000000000..dc10ee86c0 --- /dev/null +++ b/sdk-common/src/test/java/com/android/ide/common/gradle/ModuleTest.kt @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2023 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.ide.common.gradle + +import com.google.common.truth.Truth.assertThat +import org.junit.Assert.fail +import org.junit.Test + +class ModuleTest { + @Test + fun testParseAscii() { + val ascii = (32..126).map { Char(it) }.joinToString("") + val module = Module.tryParse(ascii) + assertThat(Module.parse(ascii)).isEqualTo(module) + assertThat(module).isNotNull() + assertThat(module?.group).isEqualTo(" !\"#$%&'()*+,-./0123456789") + assertThat(module?.name).isEqualTo(";<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~") + assertThat(module?.toIdentifier()).isEqualTo(ascii) + assertThat(module?.toString()).isEqualTo(ascii) + } + + @Test + fun testParseAllPositions() { + val letters = "abcdefghijklmnopqrstuvwxyz" + for (i in 0..letters.length) { + val id = "${letters.substring(0, i)}:${letters.substring(i)}" + val module = Module.tryParse(id) + assertThat(Module.parse(id)).isEqualTo(module) + assertThat(module).isNotNull() + assertThat(module?.group).isEqualTo(letters.substring(0, i)) + assertThat(module?.name).isEqualTo(letters.substring(i)) + assertThat(module?.toIdentifier()).isEqualTo(id) + assertThat(module?.toString()).isEqualTo(id) + } + } + + @Test + fun testParseInvalidNoColons() { + val numbers = "0123456789" + val module = Module.tryParse(numbers) + assertThat(module).isNull() + try { + Module.parse(numbers) + fail() + } + catch (_: IllegalArgumentException) { } + } + + @Test + fun testParseInvalidTooManyColons() { + val numbers = "0123456789" + for (i in 0 .. numbers.length) { + for (j in i .. numbers.length) { + val invalid = "${numbers.substring(0, i)}:${numbers.substring(i, j)}:${numbers.substring(j)}" + val module = Module.tryParse(invalid) + assertThat(module).isNull() + try { + Module.parse(invalid) + fail() + } + catch(_: IllegalArgumentException) { } + } + } + } + + @Test + fun testToStringInvalid() { + val groups = listOf("abc", ":abc", "a:bc", "ab:c", "abc:") + val names = listOf("123", ":123", "1:23", "12:3", "123:") + for ((group, name) in groups.zip(names)) { + if (!group.contains(':') && !name.contains(':')) continue + val module = Module(group, name) + assertThat(module.toIdentifier()).isNull() + assertThat(module.toString()).matches("^Module\\(.*\\)$") + } + } +} diff --git a/sdk-common/src/test/java/com/android/ide/common/gradle/VersionTest.kt b/sdk-common/src/test/java/com/android/ide/common/gradle/VersionTest.kt index 2060655f4b..70666693c1 100644 --- a/sdk-common/src/test/java/com/android/ide/common/gradle/VersionTest.kt +++ b/sdk-common/src/test/java/com/android/ide/common/gradle/VersionTest.kt @@ -452,6 +452,33 @@ class VersionTest { } @Test + fun testPrefixInfimumIsNotNecessarilyPreview() { + assertThat(Version.prefixInfimum("2").isPreview).isFalse() + assertThat(Version.prefixInfimum("2-alpha1").isPreview).isTrue() + assertThat(Version.prefixInfimum("2-alpha1-SNAPSHOT").isPreview).isTrue() + assertThat(Version.prefixInfimum("2-SNAPSHOT").isPreview).isTrue() + assertThat(Version.prefixInfimum("2-snapshot").isPreview).isTrue() + assertThat(Version.prefixInfimum("2-dev").isPreview).isTrue() + assertThat(Version.prefixInfimum("1.2").isPreview).isFalse() + assertThat(Version.prefixInfimum("1.2-alpha3").isPreview).isTrue() + assertThat(Version.prefixInfimum("1.2-alpha3-SNAPSHOT").isPreview).isTrue() + assertThat(Version.prefixInfimum("1.2-SNAPSHOT").isPreview).isTrue() + assertThat(Version.prefixInfimum("1.2.3").isPreview).isFalse() + assertThat(Version.prefixInfimum("1.2.3-alpha4").isPreview).isTrue() + assertThat(Version.prefixInfimum("1.2.3-alpha-4").isPreview).isTrue() + assertThat(Version.prefixInfimum("1.2.3-alpha4-SNAPSHOT").isPreview).isTrue() + assertThat(Version.prefixInfimum("1.2.3-alpha-4-SNAPSHOT").isPreview).isTrue() + assertThat(Version.prefixInfimum("1.2.3-SNAPSHOT").isPreview).isTrue() + assertThat(Version.prefixInfimum("1.2.3.4").isPreview).isFalse() + assertThat(Version.prefixInfimum("1.2.3.4.5-SNAPSHOT").isPreview).isTrue() + assertThat(Version.prefixInfimum("1.2.3.4.5.6-alpha9-SNAPSHOT").isPreview).isTrue() + assertThat(Version.prefixInfimum("7.0.0-dev03").isPreview).isTrue() + + assertThat(Version.prefixInfimum("1-SNAPSHOT.3").isPreview).isTrue() + assertThat(Version.prefixInfimum("1-dev.3").isPreview).isTrue() + } + + @Test fun testIsPrefixInfimum() { assertThat(Version.parse("1").isPrefixInfimum).isFalse() assertThat(Version.parse("1-dev").isPrefixInfimum).isFalse() diff --git a/sdk-common/src/test/java/com/android/ide/common/rendering/HardwareConfigHelperTest.java b/sdk-common/src/test/java/com/android/ide/common/rendering/HardwareConfigHelperTest.java index 7846e9f904..680de699b4 100644 --- a/sdk-common/src/test/java/com/android/ide/common/rendering/HardwareConfigHelperTest.java +++ b/sdk-common/src/test/java/com/android/ide/common/rendering/HardwareConfigHelperTest.java @@ -123,7 +123,8 @@ public class HardwareConfigHelperTest extends TestCase { assertFalse(isMobile(tv1080p)); assertFalse(isAutomotive(tv1080p)); assertFalse(tv1080p.isScreenRound()); - assertEquals("Android TV (1080p) (55.0\", 1920 \u00d7 1080, xhdpi)", getNexusLabel(tv1080p)); + assertEquals( + "Television (1080p) (55.0\", 1920 \u00d7 1080, xhdpi)", getNexusLabel(tv1080p)); assertEquals("1080p, 1920 \u00d7 1080, xhdpi (TV)", getNexusMenuLabel(tv1080p)); Device tv720p = deviceManager.getDevice("tv_720p", "Google"); diff --git a/sdk-common/src/test/java/com/android/ide/common/repository/KnownVersionStabilityTest.kt b/sdk-common/src/test/java/com/android/ide/common/repository/KnownVersionStabilityTest.kt index 87e69e8b00..d22cfecbb2 100644 --- a/sdk-common/src/test/java/com/android/ide/common/repository/KnownVersionStabilityTest.kt +++ b/sdk-common/src/test/java/com/android/ide/common/repository/KnownVersionStabilityTest.kt @@ -15,6 +15,7 @@ */ package com.android.ide.common.repository +import com.android.ide.common.gradle.Component import com.android.ide.common.gradle.Version import com.google.common.truth.Truth.assertThat import org.junit.Test @@ -22,40 +23,42 @@ import org.junit.Test class KnownVersionStabilityTest { @Test - fun testStabilityOf() { - assertThat(stabilityOf("com.android.support", "appcompat-v7")) + fun testComponentStability() { + fun component(group: String, name: String, version: String = "1.0.0") = + Component(group, name, Version.parse(version)) + assertThat(component("com.android.support", "appcompat-v7").stability) .isEqualTo(KnownVersionStability.INCOMPATIBLE) - assertThat(stabilityOf("androidx.appcompat", "appcompat")) + assertThat(component("androidx.appcompat", "appcompat").stability) .isEqualTo(KnownVersionStability.SEMANTIC) - assertThat(stabilityOf("com.android.support", "support-annotations")) + assertThat(component("com.android.support", "support-annotations").stability) .isEqualTo(KnownVersionStability.STABLE) - assertThat(stabilityOf("androidx.annotation", "annotation")) + assertThat(component("androidx.annotation", "annotation").stability) .isEqualTo(KnownVersionStability.SEMANTIC) - assertThat(stabilityOf("com.android.support", "design")) + assertThat(component("com.android.support", "design").stability) .isEqualTo(KnownVersionStability.INCOMPATIBLE) - assertThat(stabilityOf("com.google.android.material", "material")) + assertThat(component("com.google.android.material", "material").stability) .isEqualTo(KnownVersionStability.SEMANTIC) - assertThat(stabilityOf("com.android.support.constraint", "constraint-layout")) + assertThat(component("com.android.support.constraint", "constraint-layout").stability) .isEqualTo(KnownVersionStability.INCOMPATIBLE) - assertThat(stabilityOf("androidx.constraintlayout", "constraintlayout")) + assertThat(component("androidx.constraintlayout", "constraintlayout").stability) .isEqualTo(KnownVersionStability.SEMANTIC) - assertThat(stabilityOf("com.google.firebase", "firebase-core", "14.3.1")) + assertThat(component("com.google.firebase", "firebase-core", "14.3.1").stability) .isEqualTo(KnownVersionStability.INCOMPATIBLE) - assertThat(stabilityOf("com.google.firebase", "firebase-core", "15.0.1")) + assertThat(component("com.google.firebase", "firebase-core", "15.0.1").stability) .isEqualTo(KnownVersionStability.SEMANTIC) - assertThat(stabilityOf("com.google.android.gms", "play-services-ads", "14.3.1")) + assertThat(component("com.google.android.gms", "play-services-ads", "14.3.1").stability) .isEqualTo(KnownVersionStability.INCOMPATIBLE) - assertThat(stabilityOf("com.google.android.gms", "play-services-ads", "15.0.1")) + assertThat(component("com.google.android.gms", "play-services-ads", "15.0.1").stability) .isEqualTo(KnownVersionStability.SEMANTIC) - assertThat(stabilityOf("org.jetbrains.kotlin", "kotlin-stdlib")) + assertThat(component("org.jetbrains.kotlin", "kotlin-stdlib").stability) .isEqualTo(KnownVersionStability.STABLE) - assertThat(stabilityOf("org.jetbrains.kotlin", "kotlin-reflect")) + assertThat(component("org.jetbrains.kotlin", "kotlin-reflect").stability) .isEqualTo(KnownVersionStability.INCREMENTAL) } diff --git a/sdklib/src/main/java/com/android/sdklib/devices/DeviceManager.java b/sdklib/src/main/java/com/android/sdklib/devices/DeviceManager.java index 35cd982520..f15fea6ab3 100644 --- a/sdklib/src/main/java/com/android/sdklib/devices/DeviceManager.java +++ b/sdklib/src/main/java/com/android/sdklib/devices/DeviceManager.java @@ -16,6 +16,16 @@ package com.android.sdklib.devices; +import static com.android.sdklib.internal.avd.AvdManager.AVD_INI_FOLD_AT_POSTURE; +import static com.android.sdklib.internal.avd.AvdManager.AVD_INI_HINGE; +import static com.android.sdklib.internal.avd.AvdManager.AVD_INI_HINGE_ANGLES_POSTURE_DEFINITIONS; +import static com.android.sdklib.internal.avd.AvdManager.AVD_INI_HINGE_AREAS; +import static com.android.sdklib.internal.avd.AvdManager.AVD_INI_HINGE_COUNT; +import static com.android.sdklib.internal.avd.AvdManager.AVD_INI_HINGE_DEFAULTS; +import static com.android.sdklib.internal.avd.AvdManager.AVD_INI_HINGE_RANGES; +import static com.android.sdklib.internal.avd.AvdManager.AVD_INI_HINGE_SUB_TYPE; +import static com.android.sdklib.internal.avd.AvdManager.AVD_INI_HINGE_TYPE; +import static com.android.sdklib.internal.avd.AvdManager.AVD_INI_POSTURE_LISTS; import static com.android.sdklib.internal.avd.AvdManager.AVD_INI_RAM_SIZE; import com.android.SdkConstants; @@ -629,6 +639,24 @@ public class DeviceManager { Integer.toString(hw.getScreen().getFoldedHeight3())); } } + + Hinge hinge = hw.getHinge(); + + if (hinge != null) { + props.put(AVD_INI_HINGE, hinge.getCount() > 0 ? "yes" : "no"); + props.put(AVD_INI_HINGE_COUNT, Integer.toString(hinge.getCount())); + props.put(AVD_INI_HINGE_TYPE, Integer.toString(hinge.getType())); + props.put(AVD_INI_HINGE_SUB_TYPE, Integer.toString(hinge.getSubtype())); + props.put(AVD_INI_HINGE_RANGES, hinge.getRanges()); + props.put(AVD_INI_HINGE_DEFAULTS, Integer.toString(hinge.getDefaults())); + props.put(AVD_INI_HINGE_AREAS, hinge.getAreas()); + hinge.getFoldAtPosture() + .ifPresent(fold -> props.put(AVD_INI_FOLD_AT_POSTURE, Integer.toString(fold))); + props.put(AVD_INI_POSTURE_LISTS, hinge.getPostureList()); + props.put( + AVD_INI_HINGE_ANGLES_POSTURE_DEFINITIONS, + hinge.getHingeAnglePostureDefinitions()); + } return props; } diff --git a/sdklib/src/main/java/com/android/sdklib/devices/DeviceParser.java b/sdklib/src/main/java/com/android/sdklib/devices/DeviceParser.java index e06206a109..a22d1e5eb7 100644 --- a/sdklib/src/main/java/com/android/sdklib/devices/DeviceParser.java +++ b/sdklib/src/main/java/com/android/sdklib/devices/DeviceParser.java @@ -123,6 +123,8 @@ public class DeviceParser { mMeta.setFrameOffsetPortrait(new Point()); } else if (DeviceSchema.NODE_SCREEN.equals(localName)) { mHardware.setScreen(new Screen()); + } else if (DeviceSchema.NODE_HINGE.equals(localName)) { + mHardware.setHinge(new Hinge()); } else if (DeviceSchema.NODE_BOOT_PROP.equals(localName)) { mBootProp = new String[2]; } @@ -206,6 +208,24 @@ public class DeviceParser { mHardware.getScreen().setFoldedWidth3(getInteger(mStringAccumulator)); } else if (DeviceSchema.NODE_Y_FOLDED_DIMENSION_3.equals(localName)) { mHardware.getScreen().setFoldedHeight3(getInteger(mStringAccumulator)); + } else if (DeviceSchema.NODE_HINGE_COUNT.equals(localName)) { + mHardware.getHinge().setCount(getInteger(mStringAccumulator)); + } else if (DeviceSchema.NODE_HINGE_TYPE.equals(localName)) { + mHardware.getHinge().setType(getInteger(mStringAccumulator)); + } else if (DeviceSchema.NODE_HINGE_SUB_TYPE.equals(localName)) { + mHardware.getHinge().setSubtype(getInteger(mStringAccumulator)); + } else if (DeviceSchema.NODE_HINGE_RANGES.equals(localName)) { + mHardware.getHinge().setRanges(getString(mStringAccumulator)); + } else if (DeviceSchema.NODE_HINGE_DEFAULTS.equals(localName)) { + mHardware.getHinge().setDefaults(getInteger(mStringAccumulator)); + } else if (DeviceSchema.NODE_HINGE_AREAS.equals(localName)) { + mHardware.getHinge().setAreas(getString(mStringAccumulator)); + } else if (DeviceSchema.NODE_HINGE_FOLD_AT_POSTURE.equals(localName)) { + mHardware.getHinge().setFoldAtPosture(getInteger(mStringAccumulator)); + } else if (DeviceSchema.NODE_HINGE_POSTURE_LIST.equals(localName)) { + mHardware.getHinge().setPostureList(getString(mStringAccumulator)); + } else if (DeviceSchema.NODE_HINGE_ANGLES_POSTURE_DEFINITIONS.equals(localName)) { + mHardware.getHinge().setHingeAnglePostureDefinitions(getString(mStringAccumulator)); } else if (DeviceSchema.NODE_XDPI.equals(localName)) { mHardware.getScreen().setXdpi(getDouble(mStringAccumulator)); } else if (DeviceSchema.NODE_YDPI.equals(localName)) { diff --git a/sdklib/src/main/java/com/android/sdklib/devices/Hardware.java b/sdklib/src/main/java/com/android/sdklib/devices/Hardware.java index 5e3424bc55..660b9992af 100644 --- a/sdklib/src/main/java/com/android/sdklib/devices/Hardware.java +++ b/sdklib/src/main/java/com/android/sdklib/devices/Hardware.java @@ -31,6 +31,7 @@ import java.util.Set; public class Hardware { private Screen mScreen; + private Hinge mHinge; private EnumSet<Network> mNetworking = EnumSet.noneOf(Network.class); private EnumSet<Sensor> mSensors = EnumSet.noneOf(Sensor.class); private boolean mMic; @@ -246,9 +247,17 @@ public class Hardware { mScreen = s; } + public Hinge getHinge() { + return mHinge; + } + + public void setHinge(Hinge mHinge) { + this.mHinge = mHinge; + } + /** - * Returns a copy of the object that shares no state with it, - * but is initialized to equivalent values. + * Returns a copy of the object that shares no state with it, but is initialized to equivalent + * values. * * @return A copy of the object. */ @@ -256,7 +265,8 @@ public class Hardware { public Hardware deepCopy() { Hardware hw = new Hardware(); hw.mScreen = mScreen != null ? mScreen.deepCopy() : null; - hw.mNetworking = mNetworking.clone(); + hw.mHinge = mHinge != null ? mHinge.deepCopy() : null; + hw.mNetworking = mNetworking.clone(); hw.mSensors = mSensors.clone(); // Get the constant boolean value hw.mMic = mMic; diff --git a/sdklib/src/main/java/com/android/sdklib/devices/Hinge.java b/sdklib/src/main/java/com/android/sdklib/devices/Hinge.java new file mode 100644 index 0000000000..9912663d57 --- /dev/null +++ b/sdklib/src/main/java/com/android/sdklib/devices/Hinge.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2023 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.sdklib.devices; + +import java.util.OptionalInt; + +final class Hinge { + private int mCount; + private int mType; + private int mSubtype; + private String mRanges; + private int mDefaults; + private String mAreas; + private int mFoldAtPosture = -1; + private String mPostureList; + private String mHingeAnglePostureDefinitions; + + int getCount() { + return mCount; + } + + void setCount(int count) { + this.mCount = count; + } + + int getType() { + return mType; + } + + void setType(int type) { + this.mType = type; + } + + int getSubtype() { + return mSubtype; + } + + void setSubtype(int subtype) { + this.mSubtype = subtype; + } + + String getRanges() { + return mRanges; + } + + void setRanges(String ranges) { + this.mRanges = ranges; + } + + int getDefaults() { + return mDefaults; + } + + void setDefaults(int defaults) { + this.mDefaults = defaults; + } + + String getAreas() { + return mAreas; + } + + void setAreas(String areas) { + this.mAreas = areas; + } + + OptionalInt getFoldAtPosture() { + return mFoldAtPosture == -1 ? OptionalInt.empty() : OptionalInt.of(mFoldAtPosture); + } + + void setFoldAtPosture(int foldAtPosture) { + this.mFoldAtPosture = foldAtPosture; + } + + String getPostureList() { + return mPostureList; + } + + void setPostureList(String postureList) { + this.mPostureList = postureList; + } + + String getHingeAnglePostureDefinitions() { + return mHingeAnglePostureDefinitions; + } + + void setHingeAnglePostureDefinitions(String hingeAnglePostureDefinitions) { + this.mHingeAnglePostureDefinitions = hingeAnglePostureDefinitions; + } + + /** + * Returns a copy of the object that shares no state with it, but is initialized to equivalent + * values. + * + * @return A copy of the object. + */ + Hinge deepCopy() { + Hinge h = new Hinge(); + h.mCount = mCount; + h.mType = mType; + h.mSubtype = mSubtype; + h.mRanges = mRanges; + h.mDefaults = mDefaults; + h.mAreas = mAreas; + h.mFoldAtPosture = mFoldAtPosture; + h.mPostureList = mPostureList; + h.mHingeAnglePostureDefinitions = mHingeAnglePostureDefinitions; + return h; + } +} diff --git a/sdklib/src/main/java/com/android/sdklib/repository/AndroidSdkHandler.java b/sdklib/src/main/java/com/android/sdklib/repository/AndroidSdkHandler.java index f5a3e2d0eb..5a7faf7ec9 100644 --- a/sdklib/src/main/java/com/android/sdklib/repository/AndroidSdkHandler.java +++ b/sdklib/src/main/java/com/android/sdklib/repository/AndroidSdkHandler.java @@ -338,25 +338,24 @@ public final class AndroidSdkHandler { /** * @param packages a {@link Collection} of packages which share a common {@code prefix}, from - * which we wish to extract the "Latest" package, as sorted with {@code mapper} and {@code - * comparator} on the suffixes. + * which we wish to extract the "Latest" package, as sorted in natural order with {@code + * mapper}. * @param filter the revision predicate that has to be satisfied by the returned package * @param allowPreview whether we allow returning a preview package. * @param mapper maps from path suffix to a {@link Comparable}, so that we can sort the packages - * by suffix. - * @param comparator how to sort suffixes after mapping them. + * by suffix in natural order. * @param <P> {@link LocalPackage} or {@link RemotePackage} - * @param <T> {@link Comparable} that we map the suffix to. - * @return the "Latest" package from the {@link Collection}, as sorted with {@code mapper} and - * {@code comparator} on the last path component. + * @param <T> {@link Comparable<T>} that we map the suffix to. + * @return the "Latest" package from the {@link Collection}, as sorted with {@code mapper} on + * the last path component. */ @Nullable - public static <P extends RepoPackage, T> P getLatestPackageFromPrefixCollection( - @NonNull Collection<P> packages, - @Nullable Predicate<Revision> filter, - boolean allowPreview, - @NonNull Function<String, T> mapper, - @NonNull Comparator<T> comparator) { + public static <P extends RepoPackage, T extends Comparable<T>> + P getLatestPackageFromPrefixCollection( + @NonNull Collection<P> packages, + @Nullable Predicate<Revision> filter, + boolean allowPreview, + @NonNull Function<String, T> mapper) { Function<P, T> keyGen = p -> mapper.apply(p.getPath().substring( p.getPath().lastIndexOf(RepoPackage.PATH_SEPARATOR) + 1)); return packages.stream() @@ -364,7 +363,7 @@ public final class AndroidSdkHandler { p -> (filter == null || filter.test(p.getVersion())) && (allowPreview || !p.getVersion().isPreview())) - .max((p1, p2) -> comparator.compare(keyGen.apply(p1), keyGen.apply(p2))) + .max(Comparator.comparing(keyGen)) .orElse(null); } @@ -390,31 +389,22 @@ public final class AndroidSdkHandler { } /** - * @see #getLatestLocalPackageForPrefix(String, Predicate, boolean, Function, Comparator, - * ProgressIndicator) , where {@link Comparator} is just the default order. Highest is latest. - */ - @Nullable - public LocalPackage getLatestLocalPackageForPrefix( - @NonNull String prefix, @Nullable Predicate<Revision> filter, boolean allowPreview, - @NonNull Function<String, ? extends Comparable> mapper, - @NonNull ProgressIndicator progress) { - return getLatestLocalPackageForPrefix( - prefix, filter, allowPreview, mapper, Comparator.naturalOrder(), progress); - } - - /** * This grabs the {@link Collection} of {@link LocalPackage}s from {@link RepoManager} with the - * same prefix using {@link RepositoryPackages#getLocalPackagesForPrefix(String)} - * and forwards it to {@link #getLatestPackageFromPrefixCollection} + * same prefix using {@link RepositoryPackages#getLocalPackagesForPrefix(String)} and forwards + * it to {@link #getLatestPackageFromPrefixCollection} */ @Nullable - public <T> LocalPackage getLatestLocalPackageForPrefix(@NonNull String prefix, - @Nullable Predicate<Revision> filter, boolean allowPreview, - @NonNull Function<String, T> mapper, @NonNull Comparator<T> comparator, + public <T extends Comparable<T>> LocalPackage getLatestLocalPackageForPrefix( + @NonNull String prefix, + @Nullable Predicate<Revision> filter, + boolean allowPreview, + @NonNull Function<String, T> mapper, @NonNull ProgressIndicator progress) { return getLatestPackageFromPrefixCollection( getSdkManager(progress).getPackages().getLocalPackagesForPrefix(prefix), - filter, allowPreview, mapper, comparator); + filter, + allowPreview, + mapper); } /** @@ -434,27 +424,17 @@ public final class AndroidSdkHandler { * ProgressIndicator), but for {@link RemotePackage}s instead. */ @Nullable - public RemotePackage getLatestRemotePackageForPrefix( + public <T extends Comparable<T>> RemotePackage getLatestRemotePackageForPrefix( @NonNull String prefix, - @Nullable Predicate<Revision> filter, boolean allowPreview, - @NonNull Function<String, ? extends Comparable> mapper, - @NonNull ProgressIndicator progress) { - return getLatestRemotePackageForPrefix( - prefix, filter, allowPreview, mapper, Comparator.naturalOrder(), progress); - } - - /** - * @see #getLatestLocalPackageForPrefix(String, Predicate, boolean, Function, Comparator, - * ProgressIndicator), but for {@link RemotePackage}s instead. - */ - @Nullable - public <T> RemotePackage getLatestRemotePackageForPrefix(@NonNull String prefix, - @Nullable Predicate<Revision> filter, boolean allowPreview, - @NonNull Function<String, T> mapper, @NonNull Comparator<T> comparator, + @Nullable Predicate<Revision> filter, + boolean allowPreview, + @NonNull Function<String, T> mapper, @NonNull ProgressIndicator progress) { return getLatestPackageFromPrefixCollection( getSdkManager(progress).getPackages().getRemotePackagesForPrefix(prefix), - filter, allowPreview, mapper, comparator); + filter, + allowPreview, + mapper); } /** diff --git a/sdklib/src/main/resources/com/android/sdklib/devices/devices.xml b/sdklib/src/main/resources/com/android/sdklib/devices/devices.xml index 2a7b9eedcb..1ab7f68f29 100644 --- a/sdklib/src/main/resources/com/android/sdklib/devices/devices.xml +++ b/sdklib/src/main/resources/com/android/sdklib/devices/devices.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <d:devices xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:d="http://schemas.android.com/sdk/devices/6"> + xmlns:d="http://schemas.android.com/sdk/devices/7"> <d:device> <d:name>Resizable (Experimental)</d:name> @@ -31,6 +31,16 @@ <d:y-folded-dimension>2208</d:y-folded-dimension> </d:foldable-region> </d:screen> + <d:hinge> + <d:count>1</d:count> + <d:type>1</d:type> + <d:sub-type>1</d:sub-type> + <d:ranges>0-180</d:ranges> + <d:defaults>180</d:defaults> + <d:areas>884-0-1-2208</d:areas> + <d:posture-list>1, 2, 3</d:posture-list> + <d:hinge-angles-posture-definitions>0-30, 30-150, 150-180</d:hinge-angles-posture-definitions> + </d:hinge> <d:networking> Wifi Bluetooth @@ -210,6 +220,16 @@ <d:y-folded-dimension>2208</d:y-folded-dimension> </d:foldable-region> </d:screen> + <d:hinge> + <d:count>1</d:count> + <d:type>1</d:type> + <d:sub-type>1</d:sub-type> + <d:ranges>0-180</d:ranges> + <d:defaults>180</d:defaults> + <d:areas>884-0-1-2208</d:areas> + <d:posture-list>1, 2, 3</d:posture-list> + <d:hinge-angles-posture-definitions>0-30, 30-150, 150-180</d:hinge-angles-posture-definitions> + </d:hinge> <d:networking> Wifi Bluetooth @@ -303,6 +323,17 @@ <d:y-folded-dimension>2480</d:y-folded-dimension> </d:foldable-region> </d:screen> + <d:hinge> + <d:count>1</d:count> + <d:type>1</d:type> + <d:sub-type>1</d:sub-type> + <d:ranges>180-360</d:ranges> + <d:defaults>180</d:defaults> + <d:areas>1148-0-1-2480</d:areas> + <d:fold-at-posture>4</d:fold-at-posture> + <d:posture-list>3, 4</d:posture-list> + <d:hinge-angles-posture-definitions>180-330, 330-360</d:hinge-angles-posture-definitions> + </d:hinge> <d:networking> Wifi Bluetooth @@ -390,6 +421,16 @@ <d:screen-type>capacitive</d:screen-type> </d:touch> </d:screen> + <d:hinge> + <d:count>1</d:count> + <d:type>0</d:type> + <d:sub-type>1</d:sub-type> + <d:ranges>0-180</d:ranges> + <d:defaults>180</d:defaults> + <d:areas>0-1318-1080-1</d:areas> + <d:posture-list>1, 2, 3</d:posture-list> + <d:hinge-angles-posture-definitions>0-30, 30-150, 150-180</d:hinge-angles-posture-definitions> + </d:hinge> <d:networking> Wifi Bluetooth diff --git a/sdklib/src/main/resources/com/android/sdklib/devices/tv.xml b/sdklib/src/main/resources/com/android/sdklib/devices/tv.xml index 3891e8dd42..9233eb4712 100644 --- a/sdklib/src/main/resources/com/android/sdklib/devices/tv.xml +++ b/sdklib/src/main/resources/com/android/sdklib/devices/tv.xml @@ -17,7 +17,7 @@ <d:devices xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:d="http://schemas.android.com/sdk/devices/1"> <d:device> - <d:name>Android TV (4K)</d:name> + <d:name>Television (4K)</d:name> <d:id>tv_4k</d:id> <d:manufacturer>Google</d:manufacturer> <d:hardware> @@ -85,7 +85,7 @@ </d:device> <d:device> - <d:name>Android TV (1080p)</d:name> + <d:name>Television (1080p)</d:name> <d:id>tv_1080p</d:id> <d:manufacturer>Google</d:manufacturer> <d:hardware> @@ -156,7 +156,7 @@ </d:device> <d:device> - <d:name>Android TV (720p)</d:name> + <d:name>Television (720p)</d:name> <d:id>tv_720p</d:id> <d:manufacturer>Google</d:manufacturer> <d:hardware> diff --git a/sdklib/src/test/java/com/android/sdklib/devices/DeviceManagerTest.java b/sdklib/src/test/java/com/android/sdklib/devices/DeviceManagerTest.java index 30687b4c09..df98abc150 100644 --- a/sdklib/src/test/java/com/android/sdklib/devices/DeviceManagerTest.java +++ b/sdklib/src/test/java/com/android/sdklib/devices/DeviceManagerTest.java @@ -115,9 +115,9 @@ public class DeviceManagerTest { // cf /sdklib/src/main/java/com/android/sdklib/devices/nexus.xml assertThat(listDisplayNames(dm.getDevices(DeviceFilter.VENDOR))) .containsExactly( - "Android TV (4K)", - "Android TV (1080p)", - "Android TV (720p)", + "Television (4K)", + "Television (1080p)", + "Television (720p)", "Large Desktop", "Medium Desktop", "Small Desktop", @@ -182,9 +182,9 @@ public class DeviceManagerTest { "8\" Fold-out", "13.5\" Freeform", "Resizable (Experimental)", - "Android TV (4K)", - "Android TV (1080p)", - "Android TV (720p)", + "Television (4K)", + "Television (1080p)", + "Television (720p)", "Large Desktop", "Medium Desktop", "Small Desktop", @@ -297,9 +297,9 @@ public class DeviceManagerTest { // cf /sdklib/src/main/java/com/android/sdklib/devices/nexus.xml assertThat(listDisplayNames(dm2.getDevices(DeviceFilter.VENDOR))) .containsExactly( - "Android TV (4K)", - "Android TV (1080p)", - "Android TV (720p)", + "Television (4K)", + "Television (1080p)", + "Television (720p)", "Large Desktop", "Medium Desktop", "Small Desktop", @@ -362,9 +362,9 @@ public class DeviceManagerTest { "8\" Fold-out", "13.5\" Freeform", "Resizable (Experimental)", - "Android TV (4K)", - "Android TV (1080p)", - "Android TV (720p)", + "Television (4K)", + "Television (1080p)", + "Television (720p)", "Large Desktop", "Medium Desktop", "Small Desktop", @@ -471,9 +471,9 @@ public class DeviceManagerTest { // cf /sdklib/src/main/java/com/android/sdklib/devices/nexus.xml assertThat(listDisplayNames(dm.getDevices(DeviceFilter.VENDOR))) .containsExactly( - "Android TV (4K)", - "Android TV (1080p)", - "Android TV (720p)", + "Television (4K)", + "Television (1080p)", + "Television (720p)", "Large Desktop", "Medium Desktop", "Small Desktop", @@ -536,9 +536,9 @@ public class DeviceManagerTest { "8\" Fold-out", "13.5\" Freeform", "Resizable (Experimental)", - "Android TV (4K)", - "Android TV (1080p)", - "Android TV (720p)", + "Television (4K)", + "Television (1080p)", + "Television (720p)", "Large Desktop", "Medium Desktop", "Small Desktop", diff --git a/sdklib/src/test/java/com/android/sdklib/repository/AndroidSdkHandlerTest.java b/sdklib/src/test/java/com/android/sdklib/repository/AndroidSdkHandlerTest.java index 550ebf8443..2a052757f7 100644 --- a/sdklib/src/test/java/com/android/sdklib/repository/AndroidSdkHandlerTest.java +++ b/sdklib/src/test/java/com/android/sdklib/repository/AndroidSdkHandlerTest.java @@ -28,7 +28,6 @@ import com.android.testutils.TestUtils; import com.android.testutils.file.InMemoryFileSystems; import com.google.common.collect.ImmutableList; import java.nio.file.Path; -import java.util.Comparator; import java.util.List; import java.util.Locale; import junit.framework.TestCase; @@ -57,128 +56,110 @@ public class AndroidSdkHandlerTest extends TestCase { RepositoryPackages packages = new RepositoryPackages(); packages.setLocalPkgInfos(ImmutableList.of(p1_1, p1_20, p2_1, p2_2_rc3, qr2_0, qr2_1)); - LocalPackage latest = AndroidSdkHandler.getLatestPackageFromPrefixCollection( - packages.getLocalPackagesForPrefix("p"), - null, - false, // allowPreview - Revision::parseRevision, - Comparator.<Revision>naturalOrder()); + LocalPackage latest = + AndroidSdkHandler.getLatestPackageFromPrefixCollection( + packages.getLocalPackagesForPrefix("p"), + null, + false, // allowPreview + Revision::parseRevision); assertNotNull(latest); assertEquals("p;2.1", latest.getPath()); - LocalPackage earliest = AndroidSdkHandler.getLatestPackageFromPrefixCollection( - packages.getLocalPackagesForPrefix("p"), - null, - false, // allowPreview - Revision::parseRevision, - Comparator.<Revision>reverseOrder()); - assertNotNull(earliest); - assertEquals("p;1.1", earliest.getPath()); - - LocalPackage longest = AndroidSdkHandler.getLatestPackageFromPrefixCollection( - packages.getLocalPackagesForPrefix("p"), - null, - false, // allowPreview - String::length, - Comparator.naturalOrder()); + LocalPackage longest = + AndroidSdkHandler.getLatestPackageFromPrefixCollection( + packages.getLocalPackagesForPrefix("p"), + null, + false, // allowPreview + String::length); assertNotNull(longest); assertEquals("p;1.20", longest.getPath()); - longest = AndroidSdkHandler.getLatestPackageFromPrefixCollection( - packages.getLocalPackagesForPrefix("p"), - null, - true, // allowPreview - String::length, - Comparator.naturalOrder()); + longest = + AndroidSdkHandler.getLatestPackageFromPrefixCollection( + packages.getLocalPackagesForPrefix("p"), + null, + true, // allowPreview + String::length); assertNotNull(longest); assertEquals("p;2.2-rc3", longest.getPath()); - latest = AndroidSdkHandler.getLatestPackageFromPrefixCollection( - packages.getLocalPackagesForPrefix("p"), - null, - true, // allowPreview - Revision::parseRevision, - Comparator.<Revision>naturalOrder()); + latest = + AndroidSdkHandler.getLatestPackageFromPrefixCollection( + packages.getLocalPackagesForPrefix("p"), + null, + true, // allowPreview + Revision::parseRevision); assertNotNull(latest); assertEquals("p;2.2-rc3", latest.getPath()); - latest = AndroidSdkHandler.getLatestPackageFromPrefixCollection( - packages.getLocalPackagesForPrefix("q;r"), - null, - true, // allowPreview - Revision::parseRevision, - Comparator.<Revision>naturalOrder()); + latest = + AndroidSdkHandler.getLatestPackageFromPrefixCollection( + packages.getLocalPackagesForPrefix("q;r"), + null, + true, // allowPreview + Revision::parseRevision); assertNotNull(latest); assertEquals("q;r;2.1", latest.getPath()); - latest = AndroidSdkHandler.getLatestPackageFromPrefixCollection( - packages.getLocalPackagesForPrefix("o"), - null, - true, // allowPreview - Revision::parseRevision, - Comparator.<Revision>naturalOrder()); + latest = + AndroidSdkHandler.getLatestPackageFromPrefixCollection( + packages.getLocalPackagesForPrefix("o"), + null, + true, // allowPreview + Revision::parseRevision); assertNull(latest); - latest = AndroidSdkHandler.getLatestPackageFromPrefixCollection( - packages.getLocalPackagesForPrefix("p"), - (revision) -> revision.getMinor() != 1, - false, // allowPreview - Revision::parseRevision, - Comparator.<Revision>naturalOrder()); + latest = + AndroidSdkHandler.getLatestPackageFromPrefixCollection( + packages.getLocalPackagesForPrefix("p"), + (revision) -> revision.getMinor() != 1, + false, // allowPreview + Revision::parseRevision); assertNotNull(latest); assertEquals("p;1.20", latest.getPath()); - earliest = AndroidSdkHandler.getLatestPackageFromPrefixCollection( - packages.getLocalPackagesForPrefix("p"), - (revision) -> revision.getMinor() != 1, - false, // allowPreview - Revision::parseRevision, - Comparator.<Revision>reverseOrder()); - assertNotNull(earliest); - assertEquals("p;1.20", earliest.getPath()); - - longest = AndroidSdkHandler.getLatestPackageFromPrefixCollection( - packages.getLocalPackagesForPrefix("p"), - (revision) -> revision.getMajor() != 1, - false, // allowPreview - String::length, - Comparator.naturalOrder()); + longest = + AndroidSdkHandler.getLatestPackageFromPrefixCollection( + packages.getLocalPackagesForPrefix("p"), + (revision) -> revision.getMajor() != 1, + false, // allowPreview + String::length); assertNotNull(longest); assertEquals("p;2.1", longest.getPath()); - longest = AndroidSdkHandler.getLatestPackageFromPrefixCollection( - packages.getLocalPackagesForPrefix("p"), - (revision) -> revision.getMajor() != 2, - true, // allowPreview - String::length, - Comparator.naturalOrder()); + longest = + AndroidSdkHandler.getLatestPackageFromPrefixCollection( + packages.getLocalPackagesForPrefix("p"), + (revision) -> revision.getMajor() != 2, + true, // allowPreview + String::length); assertNotNull(longest); assertEquals("p;1.20", longest.getPath()); - latest = AndroidSdkHandler.getLatestPackageFromPrefixCollection( - packages.getLocalPackagesForPrefix("p"), - (revision) -> !revision.isPreview(), - true, // allowPreview - Revision::parseRevision, - Comparator.<Revision>naturalOrder()); + latest = + AndroidSdkHandler.getLatestPackageFromPrefixCollection( + packages.getLocalPackagesForPrefix("p"), + (revision) -> !revision.isPreview(), + true, // allowPreview + Revision::parseRevision); assertNotNull(latest); assertEquals("p;2.1", latest.getPath()); - latest = AndroidSdkHandler.getLatestPackageFromPrefixCollection( - packages.getLocalPackagesForPrefix("q;r"), - (revision) -> revision.getMinor() != 1, - true, // allowPreview - Revision::parseRevision, - Comparator.<Revision>naturalOrder()); + latest = + AndroidSdkHandler.getLatestPackageFromPrefixCollection( + packages.getLocalPackagesForPrefix("q;r"), + (revision) -> revision.getMinor() != 1, + true, // allowPreview + Revision::parseRevision); assertNotNull(latest); assertEquals("q;r;2.0", latest.getPath()); - latest = AndroidSdkHandler.getLatestPackageFromPrefixCollection( - packages.getLocalPackagesForPrefix("o"), - (revision) -> revision.getMajor() == 3, - true, // allowPreview - Revision::parseRevision, - Comparator.<Revision>naturalOrder()); + latest = + AndroidSdkHandler.getLatestPackageFromPrefixCollection( + packages.getLocalPackagesForPrefix("o"), + (revision) -> revision.getMajor() == 3, + true, // allowPreview + Revision::parseRevision); assertNull(latest); } @@ -196,8 +177,7 @@ public class AndroidSdkHandlerTest extends TestCase { packages.getLocalPackagesForPrefix("p"), null, false, // allowPreview - Revision::parseRevision, - Comparator.<Revision>naturalOrder()); + Revision::parseRevision); fail(); } catch (NumberFormatException ignored) { } diff --git a/sdklib/src/test/java/com/android/sdklib/tool/AvdManagerCliTest.java b/sdklib/src/test/java/com/android/sdklib/tool/AvdManagerCliTest.java index 043adee523..3d12dc1208 100644 --- a/sdklib/src/test/java/com/android/sdklib/tool/AvdManagerCliTest.java +++ b/sdklib/src/test/java/com/android/sdklib/tool/AvdManagerCliTest.java @@ -397,9 +397,6 @@ public class AvdManagerCliTest { mCli.run(new String[] {"list", "devices", "-c"}); assertEquals( ImmutableList.of( - "P tv_1080p\n", - "P tv_4k\n", - "P tv_720p\n", "P automotive_1024p_landscape\n", "P Galaxy Nexus\n", "P desktop_large\n", @@ -435,6 +432,9 @@ public class AvdManagerCliTest { "P pixel_xl\n", "P resizable\n", "P desktop_small\n", + "P tv_1080p\n", + "P tv_4k\n", + "P tv_720p\n", "P wearos_large_round\n", "P wearos_rect\n", "P wearos_small_round\n", diff --git a/studio-grpc-testutils/testSrc/com/studiogrpc/testutils/ForwardingInterceptor.kt b/studio-grpc-testutils/testSrc/com/studiogrpc/testutils/ForwardingInterceptor.kt new file mode 100644 index 0000000000..7e8b4b682d --- /dev/null +++ b/studio-grpc-testutils/testSrc/com/studiogrpc/testutils/ForwardingInterceptor.kt @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2023 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.studiogrpc.testutils + +import com.android.tools.idea.io.grpc.CallOptions +import com.android.tools.idea.io.grpc.Channel +import com.android.tools.idea.io.grpc.ClientInterceptor +import com.android.tools.idea.io.grpc.ForwardingClientCall +import com.android.tools.idea.io.grpc.MethodDescriptor + +/** A no-op interceptor. */ +object ForwardingInterceptor : ClientInterceptor { + + override fun <ReqT, RespT> interceptCall( + descriptor: MethodDescriptor<ReqT, RespT>, + options: CallOptions, + channel: Channel + ) = + object : + ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>( + channel.newCall(descriptor, options) + ) {} +} diff --git a/third_party/kotlin/BUILD b/third_party/kotlin/BUILD index b657928dfa..febac34848 100644 --- a/third_party/kotlin/BUILD +++ b/third_party/kotlin/BUILD @@ -3,8 +3,10 @@ load("//tools/base/bazel:maven.bzl", "maven_repository") maven_repository( name = "kotlin-m2repository", artifacts = [ - "@maven//:org.jetbrains.kotlin.jvm.org.jetbrains.kotlin.jvm.gradle.plugin", - "@maven//:org.jetbrains.kotlin.kotlin-stdlib-jdk8", + "@maven//:org.jetbrains.kotlin.jvm.org.jetbrains.kotlin.jvm.gradle.plugin_1.7.10", + "@maven//:org.jetbrains.kotlin.kotlin-gradle-plugin_1.7.10", + "@maven//:org.jetbrains.kotlin.kotlin-gradle-plugin-api_1.7.10", + "@maven//:org.jetbrains.kotlin.kotlin-stdlib-jdk8_1.7.10", ], visibility = ["//visibility:public"], ) diff --git a/transport/native/utils/log.h b/transport/native/utils/log.h index 3cf99f9de2..4058cfffe1 100644 --- a/transport/native/utils/log.h +++ b/transport/native/utils/log.h @@ -46,10 +46,11 @@ class Log { __attribute__((format(printf, 2, 3))); struct Tag { - static constexpr const char *const TRANSPORT = "StudioTransport"; - static constexpr const char *const PROFILER = "StudioProfiler"; - static constexpr const char *const APPINSPECT = "AppInspection"; - static constexpr const char *const COROUTINE_DEBUGGER = "CoroutineDebugger"; + static constexpr const char *const TRANSPORT = "studio.transport"; + static constexpr const char *const PROFILER = "studio.profiler"; + static constexpr const char *const APPINSPECT = "studio.appInspection"; + static constexpr const char *const COROUTINE_DEBUGGER = + "studio.coroutineDebugger"; }; }; diff --git a/wizard/template-impl/res/icon-robots.txt b/wizard/template-impl/res/icon-robots.txt new file mode 100644 index 0000000000..1313ad9016 --- /dev/null +++ b/wizard/template-impl/res/icon-robots.txt @@ -0,0 +1 @@ +skip: * diff --git a/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/common/composeVersions.kt b/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/common/composeVersions.kt index fa7e139da9..d002caa14c 100644 --- a/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/common/composeVersions.kt +++ b/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/common/composeVersions.kt @@ -15,5 +15,5 @@ */ package com.android.tools.idea.wizard.template.impl.activities.common -internal const val COMPOSE_BOM_VERSION = "2022.10.00" -internal const val COMPOSE_KOTLIN_COMPILER_VERSION = "1.3.2" +internal const val COMPOSE_BOM_VERSION = "2023.03.00" +internal const val COMPOSE_KOTLIN_COMPILER_VERSION = "1.4.3" diff --git a/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/composeActivityMaterial3/composeActivityRecipe.kt b/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/composeActivityMaterial3/composeActivityRecipe.kt index 7524c4a7a2..ff927e467a 100644 --- a/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/composeActivityMaterial3/composeActivityRecipe.kt +++ b/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/composeActivityMaterial3/composeActivityRecipe.kt @@ -39,8 +39,8 @@ fun RecipeExecutor.composeActivityRecipe( val (_, srcOut, resOut, _) = moduleData addAllKotlinDependencies(moduleData) - addDependency(mavenCoordinate = "androidx.lifecycle:lifecycle-runtime-ktx:2.3.1") - addDependency(mavenCoordinate = "androidx.activity:activity-compose:1.5.1") + addDependency(mavenCoordinate = "androidx.lifecycle:lifecycle-runtime-ktx:+") + addDependency(mavenCoordinate = "androidx.activity:activity-compose:+") // Add Compose dependencies, using the BOM to set versions addPlatformDependency(mavenCoordinate = "androidx.compose:compose-bom:$COMPOSE_BOM_VERSION") diff --git a/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/composeWearActivity/composeWearActivityRecipe.kt b/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/composeWearActivity/composeWearActivityRecipe.kt index 1b00956542..db6497c3a7 100644 --- a/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/composeWearActivity/composeWearActivityRecipe.kt +++ b/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/composeWearActivity/composeWearActivityRecipe.kt @@ -41,13 +41,14 @@ private fun RecipeExecutor.commonComposeRecipe( isLauncher: Boolean, greeting: String, wearAppName: String, - defaultPreview: String + defaultPreview: String, + composeBomVersion: String = COMPOSE_BOM_VERSION ) { addAllKotlinDependencies(moduleData) // Add Compose dependencies, using the BOM to set versions - addPlatformDependency(mavenCoordinate = "androidx.compose:compose-bom:$COMPOSE_BOM_VERSION") - addPlatformDependency(mavenCoordinate = "androidx.compose:compose-bom:$COMPOSE_BOM_VERSION", "androidTestImplementation") + addPlatformDependency(mavenCoordinate = "androidx.compose:compose-bom:$composeBomVersion") + addPlatformDependency(mavenCoordinate = "androidx.compose:compose-bom:$composeBomVersion", "androidTestImplementation") addDependency(mavenCoordinate = "androidx.compose.ui:ui") addDependency(mavenCoordinate = "androidx.compose.ui:ui-tooling-preview") @@ -151,7 +152,8 @@ fun RecipeExecutor.composeWearActivityWithTileAndComplicationRecipe( isLauncher, greeting, wearAppName, - defaultPreview + defaultPreview, + composeBomVersion = "2022.10.00" // TODO: 2023.03.00 makes the MainTileService broken ) val wearTilesVersionVarName = diff --git a/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/tabbedActivity/src/app_package/ui/main/pageViewModelJava.kt b/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/tabbedActivity/src/app_package/ui/main/pageViewModelJava.kt index bba0a30862..dace24a0ed 100644 --- a/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/tabbedActivity/src/app_package/ui/main/pageViewModelJava.kt +++ b/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/tabbedActivity/src/app_package/ui/main/pageViewModelJava.kt @@ -24,21 +24,17 @@ fun pageViewModelJava( """package ${packageName}.ui.main; +import static androidx.lifecycle.Transformations.map; + import ${getMaterialComponentName("android.arch.core.util.Function", useAndroidX)}; import ${getMaterialComponentName("android.arch.lifecycle.LiveData", useAndroidX)}; import ${getMaterialComponentName("android.arch.lifecycle.MutableLiveData", useAndroidX)}; -import ${getMaterialComponentName("android.arch.lifecycle.Transformations", useAndroidX)}; import ${getMaterialComponentName("android.arch.lifecycle.ViewModel", useAndroidX)}; public class PageViewModel extends ViewModel { private MutableLiveData<Integer> mIndex = new MutableLiveData<>(); - private LiveData<String> mText = Transformations.map(mIndex, new Function<Integer, String>() { - @Override - public String apply(Integer input) { - return "Hello world from section: " + input; - } - }); + private LiveData<String> mText = map(mIndex, input -> "Hello world from section: " + input); public void setIndex(int index) { mIndex.setValue(index); diff --git a/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/tabbedActivity/src/app_package/ui/main/pageViewModelKt.kt b/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/tabbedActivity/src/app_package/ui/main/pageViewModelKt.kt index 83cdbe595c..f7d5fe502c 100644 --- a/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/tabbedActivity/src/app_package/ui/main/pageViewModelKt.kt +++ b/wizard/template-impl/src/com/android/tools/idea/wizard/template/impl/activities/tabbedActivity/src/app_package/ui/main/pageViewModelKt.kt @@ -26,14 +26,14 @@ fun pageViewModelKt( import ${getMaterialComponentName("android.arch.lifecycle.LiveData", useAndroidX)} import ${getMaterialComponentName("android.arch.lifecycle.MutableLiveData", useAndroidX)} -import ${getMaterialComponentName("android.arch.lifecycle.Transformations", useAndroidX)} import ${getMaterialComponentName("android.arch.lifecycle.ViewModel", useAndroidX)} import ${getMaterialComponentName("android.arch.lifecycle.ViewModelProvider", useAndroidX)} +import androidx.lifecycle.map class PageViewModel : ViewModel() { private val _index = MutableLiveData<Int>() - val text: LiveData<String> = Transformations.map(_index) { + val text: LiveData<String> = _index.map { "Hello world from section: ${"$"}it" } diff --git a/wizard/template-plugin/src/com/android/tools/idea/wizard/template/Template.kt b/wizard/template-plugin/src/com/android/tools/idea/wizard/template/Template.kt index f522916abc..0373cab385 100644 --- a/wizard/template-plugin/src/com/android/tools/idea/wizard/template/Template.kt +++ b/wizard/template-plugin/src/com/android/tools/idea/wizard/template/Template.kt @@ -42,7 +42,7 @@ enum class Category { enum class FormFactor(val displayName: String) { Mobile("Phone and Tablet"), Wear("Wear OS"), - Tv("Android TV"), + Tv("Television"), Automotive("Automotive"), Generic("Generic"); diff --git a/wizard/template-plugin/src/com/android/tools/idea/wizard/template/TemplateData.kt b/wizard/template-plugin/src/com/android/tools/idea/wizard/template/TemplateData.kt index 00c7fdf4f9..8db96f58aa 100644 --- a/wizard/template-plugin/src/com/android/tools/idea/wizard/template/TemplateData.kt +++ b/wizard/template-plugin/src/com/android/tools/idea/wizard/template/TemplateData.kt @@ -62,9 +62,27 @@ enum class BytecodeLevel(val description: String, val versionString: String) { } } -enum class BuildConfigurationLanguage(val description: String) { - KTS("Kotlin script (Recommended)"), - Groovy("Groovy"); +enum class BuildConfigurationLanguageForNewProject( + val description: String, + val useKts: Boolean, + val useVersionCatalog: Boolean +) { + KTS("Kotlin DSL (build.gradle.kts) [Recommended]", true, false), + KTS_VERSION_CATALOG( + "Kotlin DSL (build.gradle.kts) + Gradle Version Catalogs [Experimental] ", + true, + true + ), + Groovy("Groovy DSL (build.gradle)", false, false); + + override fun toString() = description +} + +enum class BuildConfigurationLanguageForNewModule( + val description: String +) { + KTS("Kotlin DSL (build.gradle.kts) [Recommended]"), + Groovy("Groovy DSL (build.gradle)"); override fun toString() = description } |