Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add notification prompt for enabling Google's credential service #230

Merged
merged 1 commit into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,8 @@ Update to an unknown version may cause crashes and errors in sandboxed Google Pl
<string name="notif_app_used_play_integrity_api">%1$s used the Play Integrity API</string>
<string name="notif_app_play_integrity_api_blocked">%1$s was blocked from using the Play Integrity API</string>
<string name="notif_app_used_play_integrity_api_action_more_info">More info</string>

<string name="sign_in_with_google_notif_ch">Sign in with Google</string>
<string name="sign_in_with_google_notif_title">Enable Google’s credential service</string>
<string name="sign_in_with_google_notif_text">“Sign in with Google” requires Google’s credential service to be enabled. Tap to open settings.</string>
</resources>
43 changes: 43 additions & 0 deletions src/app/grapheneos/gmscompat/BinderClientOfGmsCore2Gca.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,21 @@ package app.grapheneos.gmscompat

import android.app.Notification
import android.app.PendingIntent
import android.app.compat.gms.GmsCompat
import android.content.Context
import android.content.Intent
import android.content.pm.GosPackageState
import android.content.pm.GosPackageStateFlag
import android.credentials.CredentialManager
import android.ext.PackageId
import android.ext.SettingsIntents
import android.ext.settings.app.AswBlockPlayIntegrityApi
import android.net.Uri
import android.os.Binder
import android.os.BinderDef
import android.provider.Settings
import android.util.Log
import androidx.core.content.getSystemService
import com.android.internal.gmscompat.IClientOfGmsCore2Gca
import com.android.internal.gmscompat.dynamite.server.IFileProxyService

Expand Down Expand Up @@ -72,5 +80,40 @@ object BinderClientOfGmsCore2Gca : IClientOfGmsCore2Gca.Stub() {
show(Notifications.ID_MANAGE_PLAY_INTEGRITY_API)
}
}

override fun onGoogleIdCredentialOptionInit() {
val ctx = App.ctx()
if (!GmsCompat.isEnabledFor(PackageId.GMS_CORE_NAME, ctx.userId)) {
return
}

if (isGoogleIdCredentialProviderEnabled(ctx)) {
return
}

Notifications.builder(Notifications.CH_SIGN_IN_WITH_GOOGLE).run {
val intent = Intent(Settings.ACTION_CREDENTIAL_PROVIDER, Uri.parse("package:" + PackageId.GMS_CORE_NAME))
setContentIntent(PendingIntent.getActivity(ctx, 0, intent, PendingIntent.FLAG_IMMUTABLE))

setSmallIcon(R.drawable.ic_configuration_required)
setContentTitle(ctx.getText(R.string.sign_in_with_google_notif_title))
setContentText(ctx.getText(R.string.sign_in_with_google_notif_text))
setAutoCancel(true)
show(Notifications.ID_ENABLE_GOOGLE_CREDENTIAL_PROVIDER)
}
}

private fun isGoogleIdCredentialProviderEnabled(ctx: Context): Boolean {
val credentialM = ctx.getSystemService<CredentialManager>()!!
// isEnabledCredentialProviderService only allows to query app's own services
val providers = credentialM.getCredentialProviderServices(ctx.userId,
CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY)

return providers.any {
it.isEnabled
&& it.componentName.packageName == PackageId.GMS_CORE_NAME
&& it.hasCapability("com.google.android.libraries.identity.googleid.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL")
}
}
}

3 changes: 3 additions & 0 deletions src/app/grapheneos/gmscompat/Notifications.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ object Notifications {
const val CH_BACKGROUND_ACTIVITY_START = "bg_activity_start"
const val CH_GMS_CRASHED = "gms_crashed"
const val CH_MANAGE_PLAY_INTEGRITY_API = "app_used_play_integrity_api"
const val CH_SIGN_IN_WITH_GOOGLE = "sign_in_with_google"

const val ID_PERSISTENT_FG_SERVICE = 1
const val ID_PLAY_STORE_PENDING_USER_ACTION = 2
Expand All @@ -38,6 +39,7 @@ object Notifications {
const val ID_ANDROID_AUTO_NEEDS_BASELINE_PERMS = 10
const val ID_GmsCore_BACKGROUND_DATA_EXEMPTION_PROMPT = 11
const val ID_MANAGE_PLAY_INTEGRITY_API = 12
const val ID_ENABLE_GOOGLE_CREDENTIAL_PROVIDER = 13

private val uniqueNotificationId = AtomicInteger(10_000)
fun generateUniqueNotificationId() = uniqueNotificationId.getAndIncrement()
Expand All @@ -54,6 +56,7 @@ object Notifications {
ch(CH_BACKGROUND_ACTIVITY_START, R.string.notif_channel_bg_activity_start, IMPORTANCE_HIGH),
ch(CH_GMS_CRASHED, R.string.notif_ch_gms_crash, IMPORTANCE_HIGH),
ch(CH_MANAGE_PLAY_INTEGRITY_API, R.string.notif_ch_manage_play_integrity_api, IMPORTANCE_HIGH),
ch(CH_SIGN_IN_WITH_GOOGLE, R.string.sign_in_with_google_notif_ch, IMPORTANCE_HIGH).apply { isBlockable = true },
)

App.notificationManager().createNotificationChannels(list)
Expand Down