Skip to content

Commit

Permalink
show notification upon detection of Play Integrity token request
Browse files Browse the repository at this point in the history
  • Loading branch information
muhomorr authored and thestinger committed Jan 25, 2025
1 parent 72de276 commit d73354b
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import android.content.Context;
import android.content.pm.GosPackageState;
import android.content.pm.GosPackageStateFlag;
import android.ext.settings.app.AswBlockPlayIntegrityApi;
import android.os.Binder;
import android.os.BinderWrapper;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;

import com.android.internal.gmscompat.GmsCompatApp;
import com.android.internal.os.BackgroundThread;

import static android.app.compat.gms.GmsCompat.appContext;
Expand Down Expand Up @@ -46,6 +48,14 @@ private void onIntegrityTokenRequest(boolean isBlocked) {
.addFlag(GosPackageStateFlag.PLAY_INTEGRITY_API_USED_AT_LEAST_ONCE)
.apply();
}
if (!AswBlockPlayIntegrityApi.I.isNotificationEnabled(gosPs)) {
return;
}
try {
GmsCompatApp.iClientOfGmsCore2Gca().showPlayIntegrityNotification(ctx.getPackageName(), isBlocked);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
};
BackgroundThread.getHandler().post(r);
}
Expand Down
6 changes: 6 additions & 0 deletions res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,10 @@ Update to an unknown version may cause crashes and errors in sandboxed Google Pl

<string name="notif_android_auto_needs_baseline_perms_title">Android Auto needs setup</string>
<string name="notif_android_auto_needs_baseline_perms_text">Go to Settings ➔ Apps ➔ Sandboxed Google Play ➔ Android Auto</string>

<string name="notif_ch_manage_play_integrity_api">Play Integrity API usage</string>
<string name="notif_app_used_play_integrity_api_title">Play Integrity API usage</string>
<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>
</resources>
52 changes: 52 additions & 0 deletions src/app/grapheneos/gmscompat/BinderClientOfGmsCore2Gca.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package app.grapheneos.gmscompat

import android.app.Notification
import android.app.PendingIntent
import android.content.pm.GosPackageState
import android.content.pm.GosPackageStateFlag
import android.ext.SettingsIntents
import android.ext.settings.app.AswBlockPlayIntegrityApi
import android.os.Binder
import android.os.BinderDef
import android.util.Log
import com.android.internal.gmscompat.IClientOfGmsCore2Gca
import com.android.internal.gmscompat.dynamite.server.IFileProxyService

Expand All @@ -20,5 +28,49 @@ object BinderClientOfGmsCore2Gca : IClientOfGmsCore2Gca.Stub() {

Notifications.handleMissingApp(Notifications.CH_MISSING_APP, App.ctx().getText(prompt), pkgName)
}

override fun showPlayIntegrityNotification(pkgName: String, isBlocked: Boolean) {
val ctx = App.ctx()
if (ctx.packageManager.getPackageUid(pkgName, 0) != Binder.getCallingUid()) {
// this method should be called by app itself
throw SecurityException()
}

val TAG = "showPlayIntegrityNotification"
Log.d(TAG, "caller: $pkgName")

val setting = AswBlockPlayIntegrityApi.I
val gosPs = GosPackageState.get(pkgName, ctx.userId)
if (!setting.isNotificationEnabled(gosPs)) {
// there's a client-side isNotificationEnabled() check before the call
Log.e(TAG, "notification is disabled")
return
}

Notifications.builder(Notifications.CH_MANAGE_PLAY_INTEGRITY_API).run {
setSmallIcon(R.drawable.ic_configuration_required)
setContentTitle(R.string.notif_app_used_play_integrity_api_title)
val text = if (isBlocked) R.string.notif_app_play_integrity_api_blocked
else R.string.notif_app_used_play_integrity_api
setContentText(ctx.getString(text, getApplicationLabel(ctx, pkgName)))
run {
val intent = SettingsIntents.getAppIntent(ctx, SettingsIntents.APP_MANAGE_PLAY_INTEGRITY_API, pkgName)
val pendingIntent = PendingIntent.getActivity(ctx, 0, intent, PendingIntent.FLAG_IMMUTABLE)
addAction(Notification.Action.Builder(null,
ctx.getText(R.string.notif_app_used_play_integrity_api_action_more_info),
pendingIntent).build())
}
run {
val pendingIntent = PendingActionReceiver.makeWriteGosPackageStateAndCancelNotif(
ctx, pkgName,
GosPackageStateFlag.SUPPRESS_PLAY_INTEGRITY_API_NOTIF, true,
Notifications.ID_MANAGE_PLAY_INTEGRITY_API)
addAction(Notification.Action.Builder(null,
ctx.getText(R.string.dont_show_again), pendingIntent).build())
}
setShowWhen(true)
show(Notifications.ID_MANAGE_PLAY_INTEGRITY_API)
}
}
}

3 changes: 3 additions & 0 deletions src/app/grapheneos/gmscompat/Notifications.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ object Notifications {
const val CH_MISSING_PLAY_GAMES_APP = "missing_play_games_app"
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 ID_PERSISTENT_FG_SERVICE = 1
const val ID_PLAY_STORE_PENDING_USER_ACTION = 2
Expand All @@ -36,6 +37,7 @@ object Notifications {
const val ID_MISSING_POST_NOTIFICATIONS_PERM = 9;
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

private val uniqueNotificationId = AtomicInteger(10_000)
fun generateUniqueNotificationId() = uniqueNotificationId.getAndIncrement()
Expand All @@ -51,6 +53,7 @@ object Notifications {
ch(CH_MISSING_PLAY_GAMES_APP, R.string.notif_ch_missing_play_games_app, IMPORTANCE_HIGH),
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),
)

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

0 comments on commit d73354b

Please sign in to comment.