Skip to content

Commit 8bb92b1

Browse files
committed
Merge branch 'main' into revert-758-patch-5
2 parents cdbac93 + 1b8b01c commit 8bb92b1

File tree

12 files changed

+178
-88
lines changed

12 files changed

+178
-88
lines changed

.github/workflows/AndroidCIWithGmd.yaml

Lines changed: 0 additions & 49 deletions
This file was deleted.

.github/workflows/Build.yaml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
branches:
66
- main
77
pull_request:
8+
89
concurrency:
910
group: build-${{ github.ref }}
1011
cancel-in-progress: true
@@ -108,3 +109,42 @@ jobs:
108109
with:
109110
name: test-reports-${{ matrix.api-level }}
110111
path: '**/build/reports/androidTests'
112+
113+
androidTest-GMD:
114+
needs: build
115+
runs-on: macOS-latest # enables hardware acceleration in the virtual machine
116+
timeout-minutes: 55
117+
118+
steps:
119+
- name: Checkout
120+
uses: actions/checkout@v3
121+
122+
- name: Copy CI gradle.properties
123+
run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties
124+
125+
- name: Set up JDK 17
126+
uses: actions/setup-java@v3
127+
with:
128+
distribution: 'zulu'
129+
java-version: 17
130+
131+
- name: Setup Gradle
132+
uses: gradle/gradle-build-action@v2
133+
134+
- name: Setup Android SDK
135+
uses: android-actions/setup-android@v2
136+
137+
- name: Build AndroidTest apps
138+
run: ./gradlew packageDemoDebug packageDemoDebugAndroidTest
139+
140+
- name: Run instrumented tests with GMD
141+
run: ./gradlew cleanManagedDevices --unused-only &&
142+
./gradlew ciDemoDebugAndroidTest -Dorg.gradle.workers.max=1
143+
-Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" -Pandroid.experimental.testOptions.managedDevices.emulator.showKernelLogging=true
144+
145+
- name: Upload test reports
146+
if: success() || failure()
147+
uses: actions/upload-artifact@v3
148+
with:
149+
name: test-reports
150+
path: '**/build/reports/androidTests'

.idea/icon.png

9.48 KB
Loading

.idea/icon_dark.png

10.7 KB
Loading

app/src/androidTest/java/com/google/samples/apps/nowinandroid/ui/NavigationTest.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import androidx.test.espresso.Espresso
3333
import androidx.test.espresso.NoActivityResumedException
3434
import com.google.samples.apps.nowinandroid.MainActivity
3535
import com.google.samples.apps.nowinandroid.R
36+
import com.google.samples.apps.nowinandroid.core.rules.GrantPostNotificationsPermissionRule
3637
import dagger.hilt.android.testing.BindValue
3738
import dagger.hilt.android.testing.HiltAndroidRule
3839
import dagger.hilt.android.testing.HiltAndroidTest
@@ -66,9 +67,15 @@ class NavigationTest {
6667
val tmpFolder: TemporaryFolder = TemporaryFolder.builder().assureDeletion().build()
6768

6869
/**
69-
* Use the primary activity to initialize the app normally.
70+
* Grant [android.Manifest.permission.POST_NOTIFICATIONS] permission.
7071
*/
7172
@get:Rule(order = 2)
73+
val postNotificationsPermission = GrantPostNotificationsPermissionRule()
74+
75+
/**
76+
* Use the primary activity to initialize the app normally.
77+
*/
78+
@get:Rule(order = 3)
7279
val composeTestRule = createAndroidComposeRule<MainActivity>()
7380

7481
private fun AndroidComposeTestRule<*, *>.stringResource(@StringRes resId: Int) =

app/src/androidTest/java/com/google/samples/apps/nowinandroid/ui/NavigationUiTest.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import androidx.compose.ui.unit.dp
2727
import com.google.accompanist.testharness.TestHarness
2828
import com.google.samples.apps.nowinandroid.core.data.repository.CompositeUserNewsResourceRepository
2929
import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor
30+
import com.google.samples.apps.nowinandroid.core.rules.GrantPostNotificationsPermissionRule
3031
import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepository
3132
import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
3233
import com.google.samples.apps.nowinandroid.uitesthiltmanifest.HiltComponentActivity
@@ -61,9 +62,15 @@ class NavigationUiTest {
6162
val tmpFolder: TemporaryFolder = TemporaryFolder.builder().assureDeletion().build()
6263

6364
/**
64-
* Use a test activity to set the content on.
65+
* Grant [android.Manifest.permission.POST_NOTIFICATIONS] permission.
6566
*/
6667
@get:Rule(order = 2)
68+
val postNotificationsPermission = GrantPostNotificationsPermissionRule()
69+
70+
/**
71+
* Use a test activity to set the content on.
72+
*/
73+
@get:Rule(order = 3)
6774
val composeTestRule = createAndroidComposeRule<HiltComponentActivity>()
6875

6976
val userNewsResourceRepository = CompositeUserNewsResourceRepository(
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2023 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.samples.apps.nowinandroid.interests
18+
19+
import androidx.benchmark.macro.CompilationMode
20+
import androidx.benchmark.macro.FrameTimingMetric
21+
import androidx.benchmark.macro.StartupMode
22+
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
23+
import androidx.test.ext.junit.runners.AndroidJUnit4
24+
import androidx.test.uiautomator.By
25+
import com.google.samples.apps.nowinandroid.PACKAGE_NAME
26+
import com.google.samples.apps.nowinandroid.allowNotifications
27+
import org.junit.Rule
28+
import org.junit.Test
29+
import org.junit.runner.RunWith
30+
31+
@RunWith(AndroidJUnit4::class)
32+
class ScrollTopicListBenchmark {
33+
@get:Rule
34+
val benchmarkRule = MacrobenchmarkRule()
35+
36+
@Test
37+
fun benchmarkStateChangeCompilationBaselineProfile() =
38+
benchmarkStateChange(CompilationMode.Partial())
39+
40+
private fun benchmarkStateChange(compilationMode: CompilationMode) =
41+
benchmarkRule.measureRepeated(
42+
packageName = PACKAGE_NAME,
43+
metrics = listOf(FrameTimingMetric()),
44+
compilationMode = compilationMode,
45+
iterations = 10,
46+
startupMode = StartupMode.WARM,
47+
setupBlock = {
48+
// Start the app
49+
pressHome()
50+
startActivityAndWait()
51+
allowNotifications()
52+
// Navigate to interests screen
53+
device.findObject(By.text("Interests")).click()
54+
device.waitForIdle()
55+
},
56+
) {
57+
interestsWaitForTopics()
58+
repeat(3) {
59+
interestsScrollTopicsDownUp()
60+
}
61+
}
62+
}

core/data/src/main/java/com/google/samples/apps/nowinandroid/core/data/util/ConnectivityManagerNetworkMonitor.kt

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import android.net.ConnectivityManager
2121
import android.net.ConnectivityManager.NetworkCallback
2222
import android.net.Network
2323
import android.net.NetworkCapabilities
24+
import android.net.NetworkRequest
2425
import android.net.NetworkRequest.Builder
2526
import android.os.Build.VERSION
2627
import android.os.Build.VERSION_CODES
@@ -44,36 +45,33 @@ class ConnectivityManagerNetworkMonitor @Inject constructor(
4445
}
4546

4647
/**
47-
* Sends the latest connectivity status to the underlying channel.
48-
*/
49-
fun update() {
50-
channel.trySend(connectivityManager.isCurrentlyConnected())
51-
}
52-
53-
/**
54-
* The callback's methods are invoked on changes to *any* network, not just the active
55-
* network. So to check for network connectivity, one must query the active network of the
56-
* ConnectivityManager.
48+
* The callback's methods are invoked on changes to *any* network matching the [NetworkRequest],
49+
* not just the active network. So we can simply track the presence (or absence) of such [Network].
5750
*/
5851
val callback = object : NetworkCallback() {
59-
override fun onAvailable(network: Network) = update()
6052

61-
override fun onLost(network: Network) = update()
53+
private val networks = mutableSetOf<Network>()
6254

63-
override fun onCapabilitiesChanged(
64-
network: Network,
65-
networkCapabilities: NetworkCapabilities,
66-
) = update()
55+
override fun onAvailable(network: Network) {
56+
networks += network
57+
channel.trySend(true)
58+
}
59+
60+
override fun onLost(network: Network) {
61+
networks -= network
62+
channel.trySend(networks.isNotEmpty())
63+
}
6764
}
6865

69-
connectivityManager.registerNetworkCallback(
70-
Builder()
71-
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
72-
.build(),
73-
callback,
74-
)
66+
val request = Builder()
67+
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
68+
.build()
69+
connectivityManager.registerNetworkCallback(request, callback)
7570

76-
update()
71+
/**
72+
* Sends the latest connectivity status to the underlying channel.
73+
*/
74+
channel.trySend(connectivityManager.isCurrentlyConnected())
7775

7876
awaitClose {
7977
connectivityManager.unregisterNetworkCallback(callback)
@@ -87,6 +85,7 @@ class ConnectivityManagerNetworkMonitor @Inject constructor(
8785
activeNetwork
8886
?.let(::getNetworkCapabilities)
8987
?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
88+
9089
else -> activeNetworkInfo?.isConnected
9190
} ?: false
9291
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2023 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.samples.apps.nowinandroid.core.rules
18+
19+
import android.Manifest.permission.POST_NOTIFICATIONS
20+
import android.os.Build.VERSION.SDK_INT
21+
import android.os.Build.VERSION_CODES.TIRAMISU
22+
import androidx.test.rule.GrantPermissionRule.grant
23+
import org.junit.rules.TestRule
24+
25+
/**
26+
* [TestRule] granting [POST_NOTIFICATIONS] permission if running on [SDK_INT] greater than [TIRAMISU].
27+
*/
28+
class GrantPostNotificationsPermissionRule :
29+
TestRule by if (SDK_INT >= TIRAMISU) grant(POST_NOTIFICATIONS) else grant()

feature/foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616

1717
package com.google.samples.apps.nowinandroid.feature.foryou
1818

19-
import android.Manifest
20-
import android.os.Build.VERSION.SDK_INT
21-
import android.os.Build.VERSION_CODES.TIRAMISU
2219
import androidx.activity.ComponentActivity
2320
import androidx.compose.foundation.layout.BoxWithConstraints
2421
import androidx.compose.ui.test.assertHasClickAction
@@ -31,8 +28,7 @@ import androidx.compose.ui.test.onFirst
3128
import androidx.compose.ui.test.onNodeWithContentDescription
3229
import androidx.compose.ui.test.onNodeWithText
3330
import androidx.compose.ui.test.performScrollToNode
34-
import androidx.test.rule.GrantPermissionRule
35-
import androidx.test.rule.GrantPermissionRule.grant
31+
import com.google.samples.apps.nowinandroid.core.rules.GrantPostNotificationsPermissionRule
3632
import com.google.samples.apps.nowinandroid.core.testing.data.followableTopicTestData
3733
import com.google.samples.apps.nowinandroid.core.testing.data.userNewsResourcesTestData
3834
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState
@@ -41,15 +37,10 @@ import org.junit.Test
4137

4238
class ForYouScreenTest {
4339

44-
@get:Rule
45-
val permissionTestRule: GrantPermissionRule =
46-
if (SDK_INT >= TIRAMISU) {
47-
grant(Manifest.permission.POST_NOTIFICATIONS)
48-
} else {
49-
grant()
50-
}
40+
@get:Rule(order = 0)
41+
val postNotificationsPermission = GrantPostNotificationsPermissionRule()
5142

52-
@get:Rule
43+
@get:Rule(order = 1)
5344
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
5445

5546
private val doneButtonMatcher by lazy {

0 commit comments

Comments
 (0)