Skip to content

Conversation

@JorgeMucientes
Copy link
Contributor

@JorgeMucientes JorgeMucientes commented Dec 11, 2025

Part of WOOMOB-1859

Description

This PR integrates Play Age Signals API in Woo Android.

The added logic works as follows:

  • Every time the app is opened (after being previously killed) we'll check the Google Age Signal API values to verify if the user is still eligible to use the app.
  • If the user is ineligible (more on when this could happen) the we'll log the user out and show a dialog that the access to the app is restricted for them based on their age.

When is a user ineligible to use WooCommerce app? Discussion p2y3YZ-anO-p2#comment-24048.
According to WooCommerce TOS our app usage is expected for 13+ years old users:

All of our apps have a required age of 13+ and so we would need the app stores to return a result showing the user is at least that age. Parents can also revoke consent for a minor in their family account; the API should be capable of informing us of such revocations and we’ll need to figure out how to honor those.

With the TOS in mind the logic to determine if a user is eligible will be based on the 4 different user statuses the API provides:

Screenshot 2025-12-12 at 18 11 47
  • Verified users will be granted access bu default
  • Supervised users above +13 plus we'll be granted access by default.
  • Supervised users whose access was denied will be log out and access restricted via a blocking dialog. See screen recording below.
  • Any other case were we fail to retrieve the userStatus, we'll grant access by default.

Test Steps

We currently can't test in prod, because we app needs to be downloaded from Google Play in order for the API to work. For that Google provides a FakeAgeSignalsManager() that enables us to test the different scenarios.

Apply the following patch in order to simulate the different API responses we'll get from the Play Signals API:

Use_FakeAgeSignalsManager_to_simulate_supervised_users.patch

For each of the following tests you'll need to open AgeSignalsClient.kt. and update the mocked userStatus

Test Case 1: User 18+ (Verified)

  • Set userStatus to VERIFIED
  • Open the app
  • Log in as usual

Test Case 2: Approved 13+ user (Supervised)

  • Set userStatus to SUPERVISED
  • Set ageUpper to 14 (use setAgeUpper(14))
  • Open the app
  • Log in as usual

Test Case 3: Supervised user under 13

  • Set userStatus to SUPERVISED_APPROVAL_PENDING
  • Set ageUpper to 12
  • Open the app
  • Log in as usual

Test Case 4: Supervised user approval denied

  • Set userStatus to SUPERVISED_APPROVAL_DENIED
  • No matter what the age is.
  • Open the app
  • You'll be logged out and a dialog displayed saying you Google account is restricted from using the app.

Images/gif

User logged in eventually looses access

Screen_recording_20251211_174346.mp4

Once access is lost dialog will prevent user from accessing the app

Screen_recording_20251211_174412.mp4
  • I have considered if this change warrants release notes and have added them to RELEASE-NOTES.txt if necessary. Use the "[Internal]" label for non-user-facing changes.

@dangermattic
Copy link
Collaborator

dangermattic commented Dec 11, 2025

2 Warnings
⚠️ Class DefaultAgeSignalsClient is missing tests, but unit-tests-exemption label was set to ignore this.
⚠️ This PR is assigned to the milestone 23.9. The due date for this milestone has already passed.
Please assign it to a milestone with a later deadline or check whether the release for this milestone has already been finished.

Generated by 🚫 Danger

@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Dec 11, 2025

Project dependencies changes

list
+ New Dependencies
com.google.android.play:age-signals:0.0.2

! Upgraded Dependencies
androidx.exifinterface:exifinterface:1.4.1, (changed from 1.4.2)
com.google.android.gms:play-services-basement:18.9.0, (changed from 18.5.0)
tree
 +--- com.google.firebase:firebase-messaging -> 25.0.1
 |    +--- com.google.firebase:firebase-common:22.0.1
 |    |    +--- org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.9.0 -> 1.10.2
 |    |    |    \--- com.google.android.gms:play-services-tasks:16.0.1 -> 18.2.0
-|    |    |         \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0
+|    |    |         \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0
-|    |    \--- com.google.android.gms:play-services-basement:18.3.0 -> 18.5.0 (*)
+|    |    \--- com.google.android.gms:play-services-basement:18.3.0 -> 18.9.0 (*)
 |    +--- com.google.firebase:firebase-iid-interop:17.1.0
-|    |    \--- com.google.android.gms:play-services-basement:17.0.0 -> 18.5.0 (*)
+|    |    \--- com.google.android.gms:play-services-basement:17.0.0 -> 18.9.0 (*)
 |    +--- com.google.firebase:firebase-measurement-connector:19.0.0
-|    |    \--- com.google.android.gms:play-services-basement:17.0.0 -> 18.5.0 (*)
+|    |    \--- com.google.android.gms:play-services-basement:17.0.0 -> 18.9.0 (*)
 |    +--- com.google.android.gms:play-services-base:18.1.0 -> 18.5.0
-|    |    \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|    |    \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
-|    +--- com.google.android.gms:play-services-basement:18.3.0 -> 18.5.0 (*)
+|    +--- com.google.android.gms:play-services-basement:18.3.0 -> 18.9.0 (*)
 |    +--- com.google.android.gms:play-services-cloud-messaging:17.2.0
-|    |    \--- com.google.android.gms:play-services-basement:18.3.0 -> 18.5.0 (*)
+|    |    \--- com.google.android.gms:play-services-basement:18.3.0 -> 18.9.0 (*)
 |    \--- com.google.android.gms:play-services-stats:17.0.2
-|         \--- com.google.android.gms:play-services-basement:18.0.0 -> 18.5.0 (*)
+|         \--- com.google.android.gms:play-services-basement:18.0.0 -> 18.9.0 (*)
 +--- com.google.firebase:firebase-config -> 23.0.1
 |    \--- com.google.firebase:firebase-abt:21.1.1
-|         \--- com.google.android.gms:play-services-basement:18.1.0 -> 18.5.0 (*)
+|         \--- com.google.android.gms:play-services-basement:18.1.0 -> 18.9.0 (*)
 +--- com.google.firebase:firebase-analytics -> 23.0.0
 |    +--- com.google.android.gms:play-services-measurement:23.0.0
 |    |    +--- com.google.android.gms:play-services-ads-identifier:18.0.0
-|    |    |    \--- com.google.android.gms:play-services-basement:18.0.0 -> 18.5.0 (*)
+|    |    |    \--- com.google.android.gms:play-services-basement:18.0.0 -> 18.9.0 (*)
-|    |    +--- com.google.android.gms:play-services-basement:18.5.0 (*)
+|    |    +--- com.google.android.gms:play-services-basement:18.5.0 -> 18.9.0 (*)
 |    |    +--- com.google.android.gms:play-services-measurement-base:23.0.0
-|    |    |    \--- com.google.android.gms:play-services-basement:18.5.0 (*)
+|    |    |    \--- com.google.android.gms:play-services-basement:18.5.0 -> 18.9.0 (*)
 |    |    +--- com.google.android.gms:play-services-measurement-impl:23.0.0
-|    |    |    \--- com.google.android.gms:play-services-basement:18.5.0 (*)
+|    |    |    \--- com.google.android.gms:play-services-basement:18.5.0 -> 18.9.0 (*)
 |    |    \--- com.google.android.gms:play-services-measurement-sdk-api:23.0.0
-|    |         \--- com.google.android.gms:play-services-basement:18.5.0 (*)
+|    |         \--- com.google.android.gms:play-services-basement:18.5.0 -> 18.9.0 (*)
 |    +--- com.google.android.gms:play-services-measurement-api:23.0.0
-|    |    \--- com.google.android.gms:play-services-basement:18.5.0 (*)
+|    |    \--- com.google.android.gms:play-services-basement:18.5.0 -> 18.9.0 (*)
 |    \--- com.google.android.gms:play-services-measurement-sdk:23.0.0
-|         \--- com.google.android.gms:play-services-basement:18.5.0 (*)
+|         \--- com.google.android.gms:play-services-basement:18.5.0 -> 18.9.0 (*)
 +--- com.google.android.gms:play-services-auth:21.4.0
 |    +--- com.google.android.gms:play-services-auth-api-phone:18.0.2
-|    |    \--- com.google.android.gms:play-services-basement:18.0.2 -> 18.5.0 (*)
+|    |    \--- com.google.android.gms:play-services-basement:18.0.2 -> 18.9.0 (*)
 |    +--- com.google.android.gms:play-services-auth-base:18.0.10
-|    |    \--- com.google.android.gms:play-services-basement:18.2.0 -> 18.5.0 (*)
+|    |    \--- com.google.android.gms:play-services-basement:18.2.0 -> 18.9.0 (*)
-|    +--- com.google.android.gms:play-services-basement:18.5.0 (*)
+|    +--- com.google.android.gms:play-services-basement:18.5.0 -> 18.9.0 (*)
 |    \--- com.google.android.gms:play-services-fido:20.0.1 -> 21.0.0
-|         \--- com.google.android.gms:play-services-basement:18.3.0 -> 18.5.0 (*)
+|         \--- com.google.android.gms:play-services-basement:18.3.0 -> 18.9.0 (*)
++--- com.google.android.play:age-signals:0.0.2
+|    +--- com.google.android.gms:play-services-basement:18.9.0 (*)
+|    +--- com.google.android.gms:play-services-tasks:18.2.0 (*)
+|    \--- com.google.android.play:core-common:2.0.4
 +--- project :libs:fluxc
-|    \--- androidx.exifinterface:exifinterface:1.4.2
+|    \--- androidx.exifinterface:exifinterface:1.4.1
 +--- project :libs:login
 |    +--- com.github.bumptech.glide:glide:5.0.5
-|    |    \--- androidx.exifinterface:exifinterface:1.3.6 -> 1.4.2 (*)
+|    |    \--- androidx.exifinterface:exifinterface:1.3.6 -> 1.4.1 (*)
 |    \--- androidx.credentials:credentials-play-services-auth:1.5.0
 |         +--- com.google.android.gms:play-services-auth-blockstore:16.4.0
-|         |    \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|         |    \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
 |         \--- com.google.android.gms:play-services-identity-credentials:16.0.0-alpha02
-|              \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|              \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
 +--- project :libs:cardreader
 |    \--- com.stripe:stripeterminal-taptopay:4.7.5
 |         \--- com.google.android.play:integrity:1.1.0
-|              \--- com.google.android.gms:play-services-basement:18.1.0 -> 18.5.0 (*)
+|              \--- com.google.android.gms:play-services-basement:18.1.0 -> 18.9.0 (*)
 +--- com.google.android.play:app-update:2.1.0
-|    \--- com.google.android.gms:play-services-basement:18.1.0 -> 18.5.0 (*)
+|    \--- com.google.android.gms:play-services-basement:18.1.0 -> 18.9.0 (*)
 +--- com.google.android.play:review:2.0.2
-|    \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|    \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
 +--- com.google.android.gms:play-services-code-scanner:16.1.0
-|    +--- com.google.android.gms:play-services-basement:18.1.0 -> 18.5.0 (*)
+|    +--- com.google.android.gms:play-services-basement:18.1.0 -> 18.9.0 (*)
 |    \--- com.google.mlkit:barcode-scanning-common:17.0.0
-|         +--- com.google.android.gms:play-services-basement:18.0.0 -> 18.5.0 (*)
+|         +--- com.google.android.gms:play-services-basement:18.0.0 -> 18.9.0 (*)
 |         \--- com.google.mlkit:vision-common:17.0.0 -> 17.3.0
-|              +--- androidx.exifinterface:exifinterface:1.0.0 -> 1.4.2 (*)
+|              +--- androidx.exifinterface:exifinterface:1.0.0 -> 1.4.1 (*)
-|              +--- com.google.android.gms:play-services-basement:18.1.0 -> 18.5.0 (*)
+|              +--- com.google.android.gms:play-services-basement:18.1.0 -> 18.9.0 (*)
 |              \--- com.google.mlkit:common:18.6.0 -> 18.11.0
-|                   \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|                   \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
 +--- com.google.mlkit:text-recognition:16.0.1
-|    +--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|    +--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
 |    +--- com.google.android.gms:play-services-mlkit-text-recognition:19.0.1
-|    |    +--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|    |    +--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
 |    |    \--- com.google.android.gms:play-services-mlkit-text-recognition-common:19.1.0
-|    |         +--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|    |         +--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
 |    |         \--- com.google.mlkit:vision-interfaces:16.3.0
-|    |              \--- com.google.android.gms:play-services-basement:18.1.0 -> 18.5.0 (*)
+|    |              \--- com.google.android.gms:play-services-basement:18.1.0 -> 18.9.0 (*)
 |    \--- com.google.mlkit:text-recognition-bundled-common:17.0.0
-|         \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|         \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
 +--- com.google.android.gms:play-services-mlkit-text-recognition-japanese:16.0.1
-|    \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|    \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
 +--- com.google.android.gms:play-services-mlkit-text-recognition-chinese:16.0.1
-|    \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|    \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
 +--- com.google.android.gms:play-services-mlkit-text-recognition-korean:16.0.1
-|    \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|    \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
 +--- com.google.android.gms:play-services-mlkit-subject-segmentation:16.0.0-beta1
-|    \--- com.google.android.gms:play-services-basement:18.1.0 -> 18.5.0 (*)
+|    \--- com.google.android.gms:play-services-basement:18.1.0 -> 18.9.0 (*)
 +--- com.google.mlkit:barcode-scanning:17.3.0
-|    +--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|    +--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
 |    \--- com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.1
-|         \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|         \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
 +--- com.google.android.gms:play-services-wearable:19.0.0
-|    \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.5.0 (*)
+|    \--- com.google.android.gms:play-services-basement:18.4.0 -> 18.9.0 (*)
 +--- com.zendesk:support:5.5.1
 |    \--- com.squareup.picasso:picasso:2.8
-|         \--- androidx.exifinterface:exifinterface:1.0.0 -> 1.4.2 (*)
+|         \--- androidx.exifinterface:exifinterface:1.0.0 -> 1.4.1 (*)
 +--- io.coil-kt:coil-compose:2.7.0
 |    \--- io.coil-kt:coil-compose-base:2.7.0
 |         \--- io.coil-kt:coil-base:2.7.0
-|              \--- androidx.exifinterface:exifinterface:1.3.7 -> 1.4.2 (*)
+|              \--- androidx.exifinterface:exifinterface:1.3.7 -> 1.4.1 (*)
 +--- androidx.camera:camera-lifecycle:1.5.1
 |    \--- androidx.camera:camera-core:1.5.1
-|         \--- androidx.exifinterface:exifinterface:1.3.2 -> 1.4.2 (*)
+|         \--- androidx.exifinterface:exifinterface:1.3.2 -> 1.4.1 (*)

@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Dec 11, 2025

📲 You can test the changes from this Pull Request in WooCommerce-Wear Android by scanning the QR code below to install the corresponding build.
App NameWooCommerce-Wear Android
Platform⌚️ Wear OS
FlavorJalapeno
Build TypeDebug
Commita2b9a02
Direct Downloadwoocommerce-wear-prototype-build-pr15085-a2b9a02.apk

Refactor the legacy viewmodel implementation that was previously added to LoginActivity
@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Dec 11, 2025

🤖 Test Failure Analysis

Your tests failed. Claude has analyzed the failures - check the annotation for details.

@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Dec 11, 2025

📲 You can test the changes from this Pull Request in WooCommerce Android by scanning the QR code below to install the corresponding build.

App NameWooCommerce Android
Platform📱 Mobile
FlavorJalapeno
Build TypeDebug
Commita2b9a02
Direct Downloadwoocommerce-prototype-build-pr15085-a2b9a02.apk

@JorgeMucientes JorgeMucientes modified the milestones: 23.8 ❄️, 23.9 Dec 12, 2025
@JorgeMucientes JorgeMucientes marked this pull request as ready for review December 12, 2025 18:22
@codecov-commenter
Copy link

Codecov Report

❌ Patch coverage is 61.81818% with 21 lines in your changes missing coverage. Please review.
✅ Project coverage is 38.63%. Comparing base (d8377f2) to head (a2b9a02).
⚠️ Report is 4 commits behind head on trunk.

Files with missing lines Patch % Lines
...android/ui/ageeligibility/AgeEligibilityChecker.kt 76.47% 2 Missing and 6 partials ⚠️
...erce/android/ui/ageeligibility/AgeSignalsClient.kt 30.00% 7 Missing ⚠️
...n/kotlin/com/woocommerce/android/AppInitializer.kt 0.00% 4 Missing ⚠️
...rc/main/kotlin/com/woocommerce/android/AppPrefs.kt 50.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##              trunk   #15085   +/-   ##
=========================================
  Coverage     38.62%   38.63%           
- Complexity    10401    10412   +11     
=========================================
  Files          2169     2171    +2     
  Lines        123459   123513   +54     
  Branches      17039    17047    +8     
=========================================
+ Hits          47691    47723   +32     
- Misses        70958    70976   +18     
- Partials       4810     4814    +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@JorgeMucientes JorgeMucientes removed the request for review from a team December 13, 2025 08:43
@irfano irfano self-assigned this Dec 15, 2025
@JorgeMucientes
Copy link
Contributor Author

This is a fairly critical change I'd also would like to ask if someone from Android in Peacock could give a look to this. Would really appreciate if one of you can take a look into this 🙏🏼 @malinajirka @kidinov @samiuelson.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants