Skip to content

Commit b7dff2c

Browse files
Update TrialManager.kt
1 parent 3d8f8c2 commit b7dff2c

1 file changed

Lines changed: 29 additions & 44 deletions

File tree

app/src/main/kotlin/com/google/ai/sample/TrialManager.kt

Lines changed: 29 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ object TrialManager {
1010
const val TRIAL_DURATION_MS = 30 * 60 * 1000L // 30 minutes in milliseconds
1111

1212
// SharedPreferences keys for flags. The actual timestamp is managed via Keystore aliases.
13-
// private const val KEY_TRIAL_END_TIME_UNENCRYPTED = "trialUtcEndTimeUnencrypted" // REMOVED
1413
private const val KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME = "trialAwaitingFirstInternetTime"
1514
private const val KEY_PURCHASED_FLAG = "appPurchased"
16-
private const val KEY_TRIAL_CONFIRMED_EXPIRED = "trialConfirmedExpired"
15+
// private const val KEY_TRIAL_CONFIRMED_EXPIRED = "trialConfirmedExpired" // REMOVED
1716

1817
private const val TAG = "TrialManager"
1918

@@ -29,18 +28,14 @@ object TrialManager {
2928
return context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
3029
}
3130

32-
// Stores the trial end time by creating a Keystore alias.
3331
private fun recordTrialEndTimeInKeystore(context: Context, utcEndTimeMs: Long) {
3432
Log.d(TAG, "recordTrialEndTimeInKeystore called with utcEndTimeMs: $utcEndTimeMs")
35-
KeystoreHelper.storeTimestampAlias(context, utcEndTimeMs) // Context is needed for KeystoreHelper
33+
KeystoreHelper.storeTimestampAlias(context, utcEndTimeMs)
3634
Log.d(TAG, "Requested storage of trial end time alias for $utcEndTimeMs in Keystore.")
3735
}
3836

39-
// Retrieves the trial end time by parsing a Keystore alias.
4037
private fun getTrialEndTimeFromKeystore(context: Context): Long? {
4138
Log.d(TAG, "getTrialEndTimeFromKeystore called")
42-
// Context is not strictly needed by KeystoreHelper.getStoredTimestampFromAlias current impl,
43-
// but passed for consistency or future KeystoreHelper changes.
4439
val endTime = KeystoreHelper.getStoredTimestampFromAlias()
4540
if (endTime == null) {
4641
Log.d(TAG, "No trial end time alias found in Keystore.")
@@ -65,24 +60,20 @@ object TrialManager {
6560
if (existingEndTimeInKeystore == null && isAwaitingFirstInternet) {
6661
val utcEndTimeMs = currentUtcTimeMs + TRIAL_DURATION_MS
6762
Log.d(TAG, "Conditions met to start trial. Calculated utcEndTimeMs: $utcEndTimeMs")
68-
recordTrialEndTimeInKeystore(context, utcEndTimeMs) // Store in Keystore
63+
recordTrialEndTimeInKeystore(context, utcEndTimeMs)
6964

70-
// After successfully requesting to store in Keystore, update SharedPreferences
7165
Log.d(TAG, "Setting KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME to false.")
7266
prefs.edit().putBoolean(KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME, false).apply()
7367
Log.i(TAG, "Trial started with internet time (Keystore alias). Ends at UTC: $utcEndTimeMs. Awaiting flag set to false.")
7468
} else {
7569
if (existingEndTimeInKeystore != null) {
7670
Log.d(TAG, "Trial not started: End time already exists in Keystore ($existingEndTimeInKeystore).")
77-
// If Keystore has data, ensure 'isAwaitingFirstInternet' is false for consistency.
7871
if (isAwaitingFirstInternet) {
7972
Log.w(TAG, "Inconsistency: Trial end time found in Keystore, but KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME is true. Setting to false.")
8073
prefs.edit().putBoolean(KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME, false).apply()
8174
}
82-
} else { // existingEndTimeInKeystore is null but isAwaitingFirstInternet is false
83-
Log.d(TAG, "Trial not started: Not awaiting first internet, but no Keystore alias found. This might mean Keystore was cleared or failed to save previously.")
84-
// This state implies something went wrong. It might be best to revert to awaiting state
85-
// if we expect a trial to be possible. For now, just logging.
75+
} else {
76+
Log.d(TAG, "Trial not started: Not awaiting first internet (flag is false), but no Keystore alias found. This might mean Keystore was cleared or failed to save previously.")
8677
}
8778
}
8879
}
@@ -97,23 +88,28 @@ object TrialManager {
9788
}
9889

9990
val isAwaitingFirstInternetTime = prefs.getBoolean(KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME, true)
100-
val trialUtcEndTime = getTrialEndTimeFromKeystore(context) // Retrieve from Keystore
101-
val confirmedExpired = prefs.getBoolean(KEY_TRIAL_CONFIRMED_EXPIRED, false)
102-
Log.d(TAG, "getTrialState: isAwaitingFirstInternetTime: $isAwaitingFirstInternetTime, trialUtcEndTime (from Keystore): $trialUtcEndTime, confirmedExpired: $confirmedExpired")
91+
val trialUtcEndTime = getTrialEndTimeFromKeystore(context)
92+
// val confirmedExpired = prefs.getBoolean(KEY_TRIAL_CONFIRMED_EXPIRED, false) // REMOVED
93+
Log.d(TAG, "getTrialState: isAwaitingFirstInternetTime: $isAwaitingFirstInternetTime, trialUtcEndTime (from Keystore): $trialUtcEndTime")
10394

104-
if (confirmedExpired) {
105-
Log.d(TAG, "getTrialState: Trial previously confirmed expired (flag was true). Returning EXPIRED_INTERNET_TIME_CONFIRMED.")
106-
return TrialState.EXPIRED_INTERNET_TIME_CONFIRMED
107-
}
95+
// if (confirmedExpired) { // REMOVED
96+
// Log.d(TAG, "getTrialState: Trial previously confirmed expired (flag was true). Returning EXPIRED_INTERNET_TIME_CONFIRMED.")
97+
// return TrialState.EXPIRED_INTERNET_TIME_CONFIRMED
98+
// }
10899

109100
if (currentUtcTimeMs == null) {
110101
Log.d(TAG, "getTrialState: currentUtcTimeMs is null.")
102+
// If we have an end time from Keystore, but no current time, we can't confirm expiry.
103+
// However, if that end time *could* be in the past, this is ambiguous.
104+
// The primary role here is to determine if we're awaiting or if we need internet.
111105
return if (trialUtcEndTime == null && isAwaitingFirstInternetTime) {
112-
Log.d(TAG, "getTrialState: Returning NOT_YET_STARTED_AWAITING_INTERNET (no Keystore alias, awaiting internet, not confirmed expired)")
106+
Log.d(TAG, "getTrialState: Returning NOT_YET_STARTED_AWAITING_INTERNET (no Keystore alias, awaiting internet)")
113107
TrialState.NOT_YET_STARTED_AWAITING_INTERNET
114108
} else {
115-
// If trialUtcEndTime exists OR not awaiting, but no current time to verify.
116-
Log.d(TAG, "getTrialState: Returning INTERNET_UNAVAILABLE_CANNOT_VERIFY (Keystore alias might exist or not awaiting, but no current time, not confirmed expired)")
109+
// This means either trial has started (endTime exists in Keystore) or it's not awaiting first internet,
110+
// but we don't have current time to check. Or, endTime is null but we are not awaiting (inconsistent state).
111+
// Or, Keystore has an end time which *might* be expired, but we can't be sure without current time.
112+
Log.d(TAG, "getTrialState: Returning INTERNET_UNAVAILABLE_CANNOT_VERIFY (Keystore alias might exist or not awaiting, but no current time)")
117113
TrialState.INTERNET_UNAVAILABLE_CANNOT_VERIFY
118114
}
119115
}
@@ -126,29 +122,25 @@ object TrialManager {
126122
TrialState.NOT_YET_STARTED_AWAITING_INTERNET
127123
}
128124
trialUtcEndTime == null && !isAwaitingFirstInternetTime -> {
129-
// This implies prefs say trial started (not awaiting), but Keystore has no record.
130-
// This could happen if Keystore entry was cleared or failed to save.
131125
Log.e(TAG, "INCONSISTENCY: Trial marked as started (not awaiting internet in prefs), but no trial end time alias found in Keystore. Resetting to await internet.")
132126
prefs.edit().putBoolean(KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME, true).apply()
133-
TrialState.NOT_YET_STARTED_AWAITING_INTERNET // Treat as if trial never properly started or Keystore was wiped.
127+
TrialState.NOT_YET_STARTED_AWAITING_INTERNET
134128
}
135-
trialUtcEndTime != null -> { // Keystore has a trial end time
136-
// Ensure 'isAwaitingFirstInternetTime' is false if we have Keystore data.
129+
trialUtcEndTime != null -> {
137130
if(isAwaitingFirstInternetTime) {
138131
Log.w(TAG, "Inconsistency: Active trial (Keystore data exists), but KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME is true. Setting to false.")
139132
prefs.edit().putBoolean(KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME, false).apply()
140133
}
141134
if (currentUtcTimeMs < trialUtcEndTime) {
142135
Log.d(TAG, "getTrialState: Case B: trialUtcEndTime (Keystore: $trialUtcEndTime) > currentUtcTimeMs ($currentUtcTimeMs). Returning ACTIVE_INTERNET_TIME_CONFIRMED")
143136
TrialState.ACTIVE_INTERNET_TIME_CONFIRMED
144-
} else { // currentUtcTimeMs >= trialUtcEndTime
145-
Log.i(TAG, "getTrialState: Case C: trialUtcEndTime (Keystore: $trialUtcEndTime) <= currentUtcTimeMs ($currentUtcTimeMs). Trial EXPIRED. Setting KEY_TRIAL_CONFIRMED_EXPIRED=true.")
146-
prefs.edit().putBoolean(KEY_TRIAL_CONFIRMED_EXPIRED, true).apply()
137+
} else {
138+
Log.i(TAG, "getTrialState: Case C: trialUtcEndTime (Keystore: $trialUtcEndTime) <= currentUtcTimeMs ($currentUtcTimeMs). Trial EXPIRED.")
139+
// No longer setting KEY_TRIAL_CONFIRMED_EXPIRED flag here. Expiry is purely based on time comparison.
147140
TrialState.EXPIRED_INTERNET_TIME_CONFIRMED
148141
}
149142
}
150143
else -> {
151-
// Should not be reached if logic above is exhaustive.
152144
Log.e(TAG, "Unhandled case in getTrialState. isAwaiting: $isAwaitingFirstInternetTime, endTimeFromKeystore: $trialUtcEndTime, currentTime: $currentUtcTimeMs. Defaulting to NOT_YET_STARTED_AWAITING_INTERNET.")
153145
TrialState.NOT_YET_STARTED_AWAITING_INTERNET
154146
}
@@ -160,11 +152,11 @@ object TrialManager {
160152
val editor = getSharedPreferences(context).edit()
161153

162154
Log.d(TAG, "Deleting trial timestamp alias(es) from Keystore.")
163-
KeystoreHelper.deleteAllTimestampAliases() // Delete Keystore entry/entries
155+
KeystoreHelper.deleteAllTimestampAliases()
164156

165-
Log.d(TAG, "Removing SharedPreferences keys: KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME, KEY_TRIAL_CONFIRMED_EXPIRED")
157+
Log.d(TAG, "Removing SharedPreferences keys: KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME") // KEY_TRIAL_CONFIRMED_EXPIRED removed from this list
166158
editor.remove(KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME)
167-
editor.remove(KEY_TRIAL_CONFIRMED_EXPIRED)
159+
// editor.remove(KEY_TRIAL_CONFIRMED_EXPIRED) // REMOVED
168160

169161
Log.d(TAG, "Setting KEY_PURCHASED_FLAG to true")
170162
editor.putBoolean(KEY_PURCHASED_FLAG, true)
@@ -183,9 +175,7 @@ object TrialManager {
183175

184176
if (isPurchased(context)) {
185177
Log.d(TAG, "App is purchased. No trial initialization needed.")
186-
// Ensure no lingering trial aliases if purchased
187178
KeystoreHelper.deleteAllTimestampAliases()
188-
// Ensure awaiting flag is false if purchased
189179
if (prefs.contains(KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME)) {
190180
prefs.edit().remove(KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME).apply()
191181
}
@@ -198,14 +188,10 @@ object TrialManager {
198188
Log.d(TAG, "Checking for existing flags/state: awaitingFlagExists=$awaitingFlagExists, trialEndTimeInKeystore=$trialEndTimeInKeystore")
199189

200190
if (trialEndTimeInKeystore == null) {
201-
// No trial started in Keystore.
202191
if (!awaitingFlagExists) {
203-
// And no awaiting flag in prefs, means fresh install or data cleared.
204192
Log.d(TAG, "No Keystore trial data and no awaiting flag. Initializing KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME to true.")
205193
prefs.edit().putBoolean(KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME, true).apply()
206194
} else {
207-
// Awaiting flag exists. If it's false, this is an inconsistent state (not awaiting but no Keystore data).
208-
// Revert to awaiting true for safety.
209195
val isAwaiting = prefs.getBoolean(KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME, true)
210196
if (!isAwaiting) {
211197
Log.w(TAG, "Inconsistency: No Keystore trial data, but KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME is false. Resetting to true.")
@@ -215,9 +201,8 @@ object TrialManager {
215201
}
216202
}
217203
} else {
218-
// Trial has started (Keystore has data). Ensure awaiting flag is false.
219204
Log.d(TAG, "Keystore has trial data (ends at $trialEndTimeInKeystore). Ensuring KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME is false.")
220-
if (!awaitingFlagExists || prefs.getBoolean(KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME, false)) {
205+
if (!awaitingFlagExists || prefs.getBoolean(KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME, false)) { // If flag exists and is true, or doesn't exist
221206
prefs.edit().putBoolean(KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME, false).apply()
222207
Log.d(TAG, "Set KEY_TRIAL_AWAITING_FIRST_INTERNET_TIME to false as Keystore has trial data.")
223208
}

0 commit comments

Comments
 (0)