Repository navigation
Fix #6179 and Fix #6272: Play Age Signals Integration[Blocked on #6239] - #6456
adhiamboperes wants to merge 9 commits into
Conversation
Coverage ReportResultsNumber of files assessed: 6 Failure Cases
Passing coverageFiles with passing code coverage
Exempted coverageFiles exempted from coverage
|
There was a problem hiding this comment.
This PR is taking me quite a bit of time to review even for the simplest parts, and there are several parts of the Age Signals integration that I don’t fully understand yet. I will pass on this review for now and assign it to @Sandesh282 to take the first pass.
Sandesh282
left a comment
There was a problem hiding this comment.
@adhiamboperes Overall the design sounds right. I have some nits though.
| .addOnFailureListener { exception -> | ||
| oppiaLogger.e("AgeSignalsController", "Failed to ingest age signals", exception) | ||
| } | ||
| } catch (e: RuntimeException) { |
There was a problem hiding this comment.
The comment says "Catching Throwable" but the catch is RuntimeException. Also "missing classes on non-GMS devices" would throw NoClassDefFoundError, which is a LinkageError, which is already handled by the separate catch (e: LinkageError) below. The comment is misleading. Should be something like: "Catching RuntimeException to guard against unexpected failures from the Play SDK call itself."
| @@ -0,0 +1,390 @@ | |||
| package org.oppia.android.domain.agesignals | |||
There was a problem hiding this comment.
The TestAgeSignalsManager has both creationCount and creationFailure properties, suggesting the intent was to test Provider-level initialization failures (i.e., when ageSignalsManagerProvider.get() itself throws). There's no test exercising this path. A test like testCompletedInitialization_managerCreationFails_doesNotCrash would complete the coverage for the LinkageError path at Provider construction time vs. at checkAgeSignals() call time.
|
Unassigning @Sandesh282 since the review is done. |
|
Hi @adhiamboperes, it looks like some changes were requested on this pull request by @Sandesh282. PTAL. Thanks! |
|
Hi @adhiamboperes, I'm going to mark this PR as stale because it hasn't had any updates for 7 days. If no further activity occurs within 7 days, it will be automatically closed so that others can take up the issue. |
|
Hi @adhiamboperes, I'm going to mark this PR as stale because it hasn't had any updates for 7 days. If no further activity occurs within 7 days, it will be automatically closed so that others can take up the issue. |
|
Hi @adhiamboperes, I'm going to mark this PR as stale because it hasn't had any updates for 7 days. If no further activity occurs within 7 days, it will be automatically closed so that others can take up the issue. |
|
@adhiamboperes is there a discussion anywhere that explains why this is blocked on #6239? From what I can tell this PR builds and the app runs with it. That almost certainly means that there isn't actually a requirement to upgrade AndroidX Core here. Am I missing something? |
|
@BenHenning, you can see that the prod flavors of the app failed to build. The Builds on this PR have expired, but please see this gist: https://gist.github.com/adhiamboperes/fdb08bd84fcac546e86fd2e68c2f6d5a for the Proguard error produced. |
|
In
What I got from MVNRepository:
Age Signals 0.0.3
Edit: TL;DR Age Signals is declaring basement 18.9.0 which references PendingIntentCompat and BuildCompat.isAtLeastV(), and these classes are not in our current version of core. |
|
Thanks @adhiamboperes. There's definitely something finicky going on because those dependencies are supposed to resolve through Maven (but I'm assuming there's some historical bad decisions coming out here from the way Play Services is designed, but I digress). It's good that Proguard is catching the issue. The problem seems to be that we need an AndroidX Core version new enough to include both My thoughts are that we fortunately do not actually need Bazel 7 for the AndroidX Core upgrade, but we do need at least Kotlin 1.7. I think we should prioritize #6234 and #6235 first, and then we'll need one more change on those 2 for the AndroidX Core upgrade (note: #6236 may also end up being needed for some complex dependency reasons), in order to unblock this change. I've reopened the first PR with it being up-to-date with the latest develop to see how CI shakes out. I was originally going to put more in that PR ahead of the Bazel 7 chain but I'm thinking instead that I'll work to finalize that PR and get it into review and then turn my attention to the others (which should actually be easier). Unfortunately it will probably take a few weeks to get all of these built and merged with my current availability, but this is a pathway forward. |
|
Hi @adhiamboperes, I'm going to mark this PR as stale because it hasn't had any updates for 7 days. If no further activity occurs within 7 days, it will be automatically closed so that others can take up the issue. |
|
Confirming that we probably will actually need to depend on #6236 unfortunately (the version of R8 we're using causes some issues when trying to upgrade AndroidX). |
Explanation
Fixes #6179
Fixes #6272
This PR integrates
Google Play Age Signals SDK 0.0.3into app's startup. It adds the ability to request age-related information from Google Play as part of the work to support regulatory requirements in Brazil and Texas. The integration does not introduce age-verification screens, restrict access to lessons, or change app behavior based on the returned signals.The new
AgeSignalsControllerlives in the domain layer and implementsApplicationStartupListener. It starts an asynchronous request after application initialization has completed. The manager is injected through a Provider, so creating the startup listener does not immediately initialize the Play SDK. The existing startup framework invokes this callback once per application process, and the request does not block the remaining startup listeners while waiting for a response.Successful responses are discarded without reading or storing age ranges, installation IDs, or parental-approval information. Asynchronous failures, synchronous runtime exceptions, and linkage errors are handled so that unavailable or incompatible Google components do not prevent normal app use.
The dependency changes add both the Age Signals SDK and an explicit Play Services Tasks dependency, together with the corresponding Maven lockfile and license metadata updates. Declaring Tasks directly allows the controller and tests to use its APIs under Bazel’s strict dependency visibility.
The new
AgeSignalsControllerTestusesFakeAgeSignalsManagerfor normal responses and documented API errors. A small test-only adapter,TestAgeSignalsManager, adds control over pending requests, synchronous failures, and request counts without contacting Google Play or using mocks.The behaviour tested:
The in-app privacy policy now describes Oppia’s temporary, local handling of age signals and explicitly excludes their use for advertising, profiling, or analytics. It also distinguishes Oppia’s handling of returned signals from Google Play’s own processing.
Some additional notes:
Essential Checklist
Disclosure of LLM Usage
YesorNo. YesWorkManagerinitialization #6062 for an example.Codex was used to write tests.
Output
When the app is launched, the learner should be able to proceed regardless of the outcome of the age signals request. The app will retry during a subsequent startup.
Successful Request

Failed Request due to Device Missing Google Play Services
