Repo Created

This commit is contained in:
Fr4nz D13trich 2025-11-15 17:44:12 +01:00
parent eb305e2886
commit a8c22c65db
4784 changed files with 329907 additions and 2 deletions

View file

@ -0,0 +1,46 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
apply plugin: 'signing'
android {
namespace "com.google.android.gms.pay"
compileSdkVersion androidCompileSdk
buildToolsVersion "$androidBuildVersionTools"
buildFeatures {
aidl = true
}
defaultConfig {
versionName version
minSdkVersion androidMinSdk
targetSdkVersion androidTargetSdk
}
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
}
// Nothing to publish yet
//apply from: '../gradle/publish-android.gradle'
description = 'microG API for play-services-pay'
dependencies {
// Dependencies from play-services-pay:16.5.0
implementation "androidx.activity:activity:1.2.3"
implementation "androidx.fragment:fragment:1.3.4"
api project(':play-services-base')
api project(':play-services-basement')
api project(':play-services-tasks')
annotationProcessor project(':safe-parcel-processor')
}

View file

@ -0,0 +1,56 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'maven-publish'
apply plugin: 'signing'
dependencies {
api project(':play-services-pay')
implementation project(':play-services-base-core')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVersion"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion"
}
android {
namespace "org.microg.gms.pay.core"
compileSdkVersion androidCompileSdk
buildToolsVersion "$androidBuildVersionTools"
defaultConfig {
versionName version
minSdkVersion androidMinSdk
targetSdkVersion androidTargetSdk
}
sourceSets {
main {
java.srcDirs = ['src/main/kotlin']
}
}
lintOptions {
disable 'MissingTranslation'
}
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
kotlinOptions {
jvmTarget = 1.8
}
}
// Nothing to publish yet
//apply from: '../gradle/publish-android.gradle'
description = 'microG service implementation for play-services-pay'

View file

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ SPDX-FileCopyrightText: 2023 microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity-alias
android:name="com.google.android.gms.pay.main.PayActivity"
android:exported="true"
android:process=":ui"
android:targetActivity="org.microg.gms.pay.PayActivity">
<intent-filter>
<action android:name="com.google.android.gms.pay.PAY" />
<action android:name="com.google.android.gms.pay.PAY_OPTIONAL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity-alias>
<activity
android:name="org.microg.gms.pay.PayActivity"
android:exported="true"
android:process=":ui" />
<service android:name="org.microg.gms.pay.PayService">
<intent-filter>
<action android:name="com.google.android.gms.pay.service.BIND" />
</intent-filter>
</service>
<service
android:name="org.microg.gms.pay.ThirdPartyPayService"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.pay.service.THIRD_PARTY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
</application>
</manifest>

View file

@ -0,0 +1,21 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.pay
import android.app.Activity
import android.os.Bundle
import android.view.Gravity
import android.widget.TextView
class PayActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(TextView(this).apply {
text = "Not yet supported:\n${intent?.action}"
gravity = Gravity.CENTER
})
}
}

View file

@ -0,0 +1,99 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.pay
import android.os.Parcel
import com.google.android.gms.common.Feature
import com.google.android.gms.common.api.CommonStatusCodes
import com.google.android.gms.common.internal.ConnectionInfo
import com.google.android.gms.common.internal.GetServiceRequest
import com.google.android.gms.common.internal.IGmsCallbacks
import com.google.android.gms.pay.internal.IPayService
import org.microg.gms.BaseService
import org.microg.gms.common.GmsService
import org.microg.gms.utils.warnOnTransactionIssues
private const val TAG = "PayService"
class PayService : BaseService(TAG, GmsService.PAY) {
override fun handleServiceRequest(callback: IGmsCallbacks, request: GetServiceRequest, service: GmsService) {
callback.onPostInitCompleteWithConnectionInfo(CommonStatusCodes.SUCCESS, PayServiceImpl(), ConnectionInfo().apply {
features = arrayOf(
Feature("pay", 10),
Feature("pay_attestation_signal", 1),
Feature("pay_pay_capabilities", 1),
Feature("pay_feature_check", 1),
Feature("pay_get_card_centric_bundle", 1),
Feature("pay_get_passes", 1),
Feature("pay_get_pay_api_availability_status", 3),
Feature("pay_get_se_prepaid_card", 1),
Feature("pay_debit_se_prepaid_card", 1),
Feature("pay_get_specific_bulletin", 1),
Feature("pay_get_transit_cards", 1),
Feature("pay_get_wallet_status", 1),
Feature("pay_global_actions", 1),
Feature("pay_gp3_support", 1),
Feature("pay_homescreen_sorting", 3),
Feature("pay_homescreen_bulletins", 2),
Feature("pay_onboarding", 2),
Feature("pay_mark_tos_accepted_for_partner", 1),
Feature("pay_move_card_on_other_device", 1),
Feature("pay_passes_field_update_notifications", 1),
Feature("pay_passes_notifications", 2),
Feature("pay_payment_method", 1),
Feature("pay_payment_method_action_tokens", 2),
Feature("pay_payment_method_server_action", 1),
Feature("pay_provision_se_prepaid_card", 1),
Feature("pay_request_module", 1),
Feature("pay_reverse_purchase", 1),
Feature("pay_save_passes", 5),
Feature("pay_save_passes_jwt", 3),
Feature("pay_save_purchased_card", 1),
Feature("pay_sync_bundle", 2),
Feature("pay_settings", 1),
Feature("pay_topup_se_prepaid_card", 1),
Feature("pay_list_commuter_pass_renewal_options_for_se_prepaid_card", 1),
Feature("pay_transactions", 6),
Feature("pay_update_bundle_with_client_settings", 1),
Feature("pay_clock_skew_millis", 1),
Feature("pay_se_postpaid_transactions", 1),
Feature("pay_se_prepaid_transactions", 1),
Feature("pay_get_clock_skew_millis", 1),
Feature("pay_renew_commuter_pass_for_se_prepaid_card", 1),
Feature("pay_remove_se_postpaid_token", 1),
Feature("pay_change_se_postpaid_default_status", 1),
Feature("pay_wear_payment_methods", 2),
Feature("pay_wear_closed_loop_cards", 1),
Feature("pay_perform_wear_operation", 1),
Feature("pay_delete_se_prepaid_card", 1),
Feature("pay_transit_issuer_tos", 1),
Feature("pay_get_se_mfi_prepaid_cards", 1),
Feature("pay_get_last_user_present_timestamp", 1),
Feature("pay_mdoc", 7),
Feature("pay_get_se_feature_readiness_status", 1),
Feature("pay_recover_se_card", 1),
Feature("pay_set_wallet_item_surfacing", 2),
Feature("pay_set_se_transit_default", 1),
Feature("pay_get_wallet_bulletins", 2),
Feature("pay_mse_operation", 1),
Feature("pay_clear_bulletin_interaction_for_dev", 1),
Feature("pay_get_pending_intent_for_wallet_on_wear", 2),
Feature("pay_get_predefined_rotating_barcode_values", 1),
Feature("pay_get_mdl_refresh_timestamps", 1),
Feature("pay_store_mdl_refresh_timestamp", 1),
Feature("pay_perform_id_card_operation", 1),
Feature("pay_block_closed_loop_cards", 1),
Feature("pay_delete_data_for_tests", 1),
Feature("pay_perform_closed_loop_operation", 1)
)
})
}
}
class PayServiceImpl : IPayService.Stub() {
override fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean =
warnOnTransactionIssues(code, reply, flags, TAG) { super.onTransact(code, data, reply, flags) }
}

View file

@ -0,0 +1,92 @@
/*
* SPDX-FileCopyrightText: 2024 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.pay
import android.util.Log
import com.google.android.gms.common.Feature
import com.google.android.gms.common.api.CommonStatusCodes
import com.google.android.gms.common.api.Status
import com.google.android.gms.common.internal.ConnectionInfo
import com.google.android.gms.common.internal.GetServiceRequest
import com.google.android.gms.common.internal.IGmsCallbacks
import com.google.android.gms.pay.CheckReadinessForEmoneyRequest
import com.google.android.gms.pay.GetMdocCredentialRequest
import com.google.android.gms.pay.GetPayApiAvailabilityStatusRequest
import com.google.android.gms.pay.GetPendingIntentForWalletOnWearRequest
import com.google.android.gms.pay.NotifyCardTapEventRequest
import com.google.android.gms.pay.NotifyEmoneyCardStatusUpdateRequest
import com.google.android.gms.pay.PayApiAvailabilityStatus
import com.google.android.gms.pay.PushEmoneyCardRequest
import com.google.android.gms.pay.SavePassesRequest
import com.google.android.gms.pay.SyncBundleRequest
import com.google.android.gms.pay.internal.IPayServiceCallbacks
import com.google.android.gms.pay.internal.IThirdPartyPayService
import org.microg.gms.BaseService
import org.microg.gms.common.GmsService
private const val TAG = "ThirdPartyPayService"
class ThirdPartyPayService : BaseService(TAG, GmsService.PAY) {
override fun handleServiceRequest(callback: IGmsCallbacks, request: GetServiceRequest, service: GmsService) {
callback.onPostInitCompleteWithConnectionInfo(CommonStatusCodes.SUCCESS, ThirdPartyPayServiceImpl().asBinder(), ConnectionInfo().apply {
features = arrayOf(
Feature("pay_get_pay_api_availability_status", 3),
Feature("pay_save_passes", 5),
Feature("pay_save_passes_jwt", 3),
Feature("pay_sync_bundle", 2),
Feature("pay_get_pending_intent_for_wallet_on_wear", 2),
Feature("pay_get_mdoc_credential_pending_intent", 1),
Feature("pay_notify_card_tap_event", 1),
Feature("pay_check_readiness_for_emoney", 1),
Feature("pay_push_emoney_card", 1),
Feature("pay_notify_emoney_card_status_update", 1)
)
})
}
}
class ThirdPartyPayServiceImpl : IThirdPartyPayService.Stub() {
override fun getPayApiAvailabilityStatus(request: GetPayApiAvailabilityStatusRequest?, callback: IPayServiceCallbacks) {
Log.d(TAG, "onPayApiAvailabilityStatus: Reporting NOT_ELIGIBLE")
callback.onPayApiAvailabilityStatus(Status.SUCCESS, PayApiAvailabilityStatus.NOT_ELIGIBLE)
}
override fun savePasses(request: SavePassesRequest?, callback: IPayServiceCallbacks) {
Log.d(TAG, "savePasses: return SERVICE_MISSING")
callback.onPendingIntent(Status(CommonStatusCodes.SERVICE_MISSING))
}
override fun syncBundle(request: SyncBundleRequest?, callback: IPayServiceCallbacks?) {
Log.d(TAG, "syncBundle Not yet implemented")
}
override fun getPendingForWalletOnWear(request: GetPendingIntentForWalletOnWearRequest?, callback: IPayServiceCallbacks?) {
Log.d(TAG, "getPendingForWalletOnWear Not yet implemented")
}
override fun getMdocCredential(request: GetMdocCredentialRequest?, callback: IPayServiceCallbacks?) {
Log.d(TAG, "getMdocCredential Not yet implemented")
}
override fun notifyCardTapEvent(request: NotifyCardTapEventRequest?, callback: IPayServiceCallbacks?) {
Log.d(TAG, "notifyCardTapEvent Not yet implemented")
}
override fun checkReadinessForEmoney(request: CheckReadinessForEmoneyRequest?, callback: IPayServiceCallbacks?) {
Log.d(TAG, "checkReadinessForEmoney Not yet implemented")
}
override fun pushEmoneyCard(request: PushEmoneyCardRequest?, callback: IPayServiceCallbacks?) {
Log.d(TAG, "pushEmoneyCard Not yet implemented")
}
override fun notifyEmoneyCardStatusUpdate(request: NotifyEmoneyCardStatusUpdateRequest?, callback: IPayServiceCallbacks?) {
Log.d(TAG, "notifyEmoneyCardStatusUpdate Not yet implemented")
}
}

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2023 microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<manifest />

View file

@ -0,0 +1,3 @@
package com.google.android.gms.pay;
parcelable CheckReadinessForEmoneyRequest;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.pay;
parcelable EmoneyReadiness;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.pay;
parcelable GetMdocCredentialRequest;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.pay;
parcelable GetPayApiAvailabilityStatusRequest;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.pay;
parcelable GetPendingIntentForWalletOnWearRequest;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.pay;
parcelable GetWalletStatusResponse;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.pay;
parcelable NotifyCardTapEventRequest;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.pay;
parcelable NotifyEmoneyCardStatusUpdateRequest;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.pay;
parcelable PayApiError;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.pay;
parcelable PushEmoneyCardRequest;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.pay;
parcelable SavePassesRequest;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.pay;
parcelable SyncBundleRequest;

View file

@ -0,0 +1,5 @@
package com.google.android.gms.pay.internal;
interface IPayService {
}

View file

@ -0,0 +1,35 @@
package com.google.android.gms.pay.internal;
import android.app.PendingIntent;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.pay.EmoneyReadiness;
import com.google.android.gms.pay.GetWalletStatusResponse;
import com.google.android.gms.pay.PayApiError;
interface IPayServiceCallbacks {
oneway void onStatus(in Status status) = 1;
// oneway void onGetPayGlobalActionCardsResponse(in Status status, in GetPayGlobalActionCardsResponse response) = 2;
oneway void onPendingIntentForWalletOnWear(in Status status, in PendingIntent pendingIntent) = 3;
// oneway void onProtoSafeParcelable(in Status status, in ProtoSafeParcelable proto) = 4;
// oneway void onDataChangeListenerResponse(in DataChangeListenerResponse response) = 5;
// oneway void onGetSortOrderResponse(in Status status, in GetSortOrderResponse response) = 6;
oneway void onStatusAndBoolean(in Status status, boolean b) = 7;
// oneway void onGetTransactionsResponse(in Status status, in GetTransactionsResponse response) = 8;
oneway void onPayApiError(in PayApiError error) = 9;
// oneway void onGetOutstandingPurchaseOrderIdResponse(in Status status, in GetOutstandingPurchaseOrderIdResponse response) = 10;
// oneway void onGetClosedLoopBundleResponse(in Status status, in GetClosedLoopBundleResponse response) = 11;
// oneway void onGetPayCardArtResponse(in Status status, in GetPayCardArtResponse response) = 12;
// oneway void onSyncTransactionsResponse(in Status status, in SyncTransactionsResponse response) = 13;
oneway void onStatusAndByteArray(in Status status, in byte[] bArr) = 14;
// oneway void onGetPassesResponse(in Status status, in GetPassesResponse response) = 15;
oneway void onStatusAndLong(in Status status, long l) = 16;
oneway void onPendingIntent(in Status status) = 17;
// oneway void onGp3SupportInfo(in Status status, Gp3SupportInfo info) = 18;
oneway void onPayApiAvailabilityStatus(in Status status, int availabilityStatus) = 19;
// oneway void onGetTransitCardsResponse(in Status status, in GetTransitCardsResponse response) = 20;
// oneway void onGetWalletStatus(in Status status, in GetWalletStatusResponse getWalletStatusResponse) = 21;
// oneway void onGetSeFeatureReadinessStatusResponse(in Status status, in GetSeFeatureReadinessStatusResponse response) = 22;
// oneway void onSyncTransactionByIdResponse(in Status status, in SyncTransactionByIdResponse response) = 23;
// oneway void onGetImagesForValuableResponse(in Status status, in GetImagesForValuableResponse response) = 24;
oneway void onEmoneyReadiness(in Status status, in EmoneyReadiness emoneyReadiness) = 25;
}

View file

@ -0,0 +1,24 @@
package com.google.android.gms.pay.internal;
import com.google.android.gms.pay.GetPayApiAvailabilityStatusRequest;
import com.google.android.gms.pay.internal.IPayServiceCallbacks;
import com.google.android.gms.pay.SavePassesRequest;
import com.google.android.gms.pay.SyncBundleRequest;
import com.google.android.gms.pay.CheckReadinessForEmoneyRequest;
import com.google.android.gms.pay.GetMdocCredentialRequest;
import com.google.android.gms.pay.GetPendingIntentForWalletOnWearRequest;
import com.google.android.gms.pay.NotifyCardTapEventRequest;
import com.google.android.gms.pay.PushEmoneyCardRequest;
import com.google.android.gms.pay.NotifyEmoneyCardStatusUpdateRequest;
interface IThirdPartyPayService {
void getPayApiAvailabilityStatus(in GetPayApiAvailabilityStatusRequest request, in IPayServiceCallbacks callback) = 1; // Reply via onPayApiAvailabilityStatus
void savePasses(in SavePassesRequest request, in IPayServiceCallbacks callback) = 2; // Reply via onPendingIntent
void syncBundle(in SyncBundleRequest request, in IPayServiceCallbacks callback) = 3;
void getPendingForWalletOnWear(in GetPendingIntentForWalletOnWearRequest request, in IPayServiceCallbacks callback) = 4; // Reply via onPendingIntentForWalletOnWear
void getMdocCredential(in GetMdocCredentialRequest request, in IPayServiceCallbacks callback) = 5;
void notifyCardTapEvent(in NotifyCardTapEventRequest request, in IPayServiceCallbacks callback) = 6; // Reply via onStatus or onPayApiError
void checkReadinessForEmoney(in CheckReadinessForEmoneyRequest request, in IPayServiceCallbacks callback) = 7; // Reply via onEmoneyReadiness
void pushEmoneyCard(in PushEmoneyCardRequest request, in IPayServiceCallbacks callback) = 8; // Reply via onPendingIntent
void notifyEmoneyCardStatusUpdate(in NotifyEmoneyCardStatusUpdateRequest request, in IPayServiceCallbacks callback) = 9; // Reply via onStatus
}

View file

@ -0,0 +1,32 @@
package com.google.android.gms.pay;
import android.os.Parcel;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
@Hide
@SafeParcelable.Class
public class CheckReadinessForEmoneyRequest extends AbstractSafeParcelable {
@Field(1)
public String serviceProvider;
@Nullable
@Field(2)
public String accountName;
@Constructor
public CheckReadinessForEmoneyRequest(@Param(1) String serviceProvider, @Nullable @Param(2) String accountName) {
this.serviceProvider = serviceProvider;
this.accountName = accountName;
}
@Override
public void writeToParcel(Parcel out, int flags) {
CREATOR.writeToParcel(this, out, flags);
}
public static final SafeParcelableCreatorAndWriter<CheckReadinessForEmoneyRequest> CREATOR = findCreator(CheckReadinessForEmoneyRequest.class);
}

View file

@ -0,0 +1,56 @@
/*
* SPDX-FileCopyrightText: 2024 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.pay;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import java.util.Objects;
/**
* {@link Parcelable} representing an e-money readiness result.
*/
public class EmoneyReadiness extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getEmoneyReadinessStatus")
private final @EmoneyReadinessStatus int emoneyReadinessStatus;
public EmoneyReadiness(@Param(1) @EmoneyReadinessStatus int emoneyReadinessStatus) {
this.emoneyReadinessStatus = emoneyReadinessStatus;
}
@Override
public final boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EmoneyReadiness)) return false;
EmoneyReadiness that = (EmoneyReadiness) o;
return emoneyReadinessStatus == that.emoneyReadinessStatus;
}
/**
* Gets the int value defined in {@link EmoneyReadinessStatus}.
*/
public @EmoneyReadinessStatus int getEmoneyReadinessStatus() {
return emoneyReadinessStatus;
}
@Override
public int hashCode() {
return Objects.hashCode(new Object[]{emoneyReadinessStatus});
}
@Override
public void writeToParcel(Parcel out, int flags) {
CREATOR.writeToParcel(this, out, flags);
}
public static final SafeParcelableCreatorAndWriter<EmoneyReadiness> CREATOR = findCreator(EmoneyReadiness.class);
}

View file

@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: 2024 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.pay;
import androidx.annotation.IntDef;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* E-money readiness status based on service provider and account.
*/
@Target({ElementType.TYPE_USE})
@Retention(RetentionPolicy.SOURCE)
@IntDef({EmoneyReadinessStatus.FEATURE_NOT_SUPPORTED, EmoneyReadinessStatus.READY, EmoneyReadinessStatus.APP_NOT_INSTALLED, EmoneyReadinessStatus.APP_UPGRADE_NEEDED, EmoneyReadinessStatus.NO_ACTIVE_ACCOUNT, EmoneyReadinessStatus.ACCOUNT_MISMATCH})
public @interface EmoneyReadinessStatus {
/**
* Indicates that the e-money feature is not supported yet or still waiting for launch.
*/
int FEATURE_NOT_SUPPORTED = 0;
/**
* Indicates that the e-money feature is available and ready to be used.
*/
int READY = 1;
/**
* Indicates that the Google Wallet app is not installed.
*/
int APP_NOT_INSTALLED = 2;
/**
* Indicates that the current Google Wallet app version or the Google Play services version needs to be upgraded.
*/
int APP_UPGRADE_NEEDED = 3;
/**
* Indicates that there is no active account currently in Google Wallet.
*/
int NO_ACTIVE_ACCOUNT = 4;
/**
* Indicates that the provided account does not match the active account currently in Google Wallet.
*/
int ACCOUNT_MISMATCH = 5;
}

View file

@ -0,0 +1,33 @@
package com.google.android.gms.pay;
import android.os.Parcel;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
@Hide
@SafeParcelable.Class
public class GetMdocCredentialRequest extends AbstractSafeParcelable {
@Field(1)
public String unknownFieldA;
@Field(2)
public byte[] unknownFieldB;
@Field(5)
public byte[] unknownFieldC;
@Constructor
public GetMdocCredentialRequest(@Param(1) String unknownFieldA, @Param(2) byte[] unknownFieldB, @Param(5) byte[] unknownFieldC) {
this.unknownFieldA = unknownFieldA;
this.unknownFieldB = unknownFieldB;
this.unknownFieldC = unknownFieldC;
}
@Override
public void writeToParcel(Parcel out, int flags) {
CREATOR.writeToParcel(this, out, flags);
}
public static final SafeParcelableCreatorAndWriter<GetMdocCredentialRequest> CREATOR = findCreator(GetMdocCredentialRequest.class);
}

View file

@ -0,0 +1,35 @@
package com.google.android.gms.pay;
import android.os.Parcel;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
import org.microg.gms.utils.ToStringHelper;
@Hide
@SafeParcelable.Class
public class GetPayApiAvailabilityStatusRequest extends AbstractSafeParcelable {
@Field(1)
public int requestType;
@Constructor
public GetPayApiAvailabilityStatusRequest(@Param(1) @PayClient.RequestType int requestType) {
this.requestType = requestType;
}
@Override
public void writeToParcel(Parcel out, int flags) {
CREATOR.writeToParcel(this, out, flags);
}
public static final SafeParcelableCreatorAndWriter<GetPayApiAvailabilityStatusRequest> CREATOR = findCreator(GetPayApiAvailabilityStatusRequest.class);
@Override
public String toString() {
return ToStringHelper.name("GetPayApiAvailabilityStatusRequest")
.field("requestType", requestType)
.end();
}
}

View file

@ -0,0 +1,30 @@
package com.google.android.gms.pay;
import android.os.Parcel;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
@Hide
@SafeParcelable.Class
public class GetPendingIntentForWalletOnWearRequest extends AbstractSafeParcelable {
@Field(2)
public String wearNodeId;
@Field(3)
public int intentSource;
@Constructor
public GetPendingIntentForWalletOnWearRequest(@Param(2) String wearNodeId, @Param(3) int intentSource) {
this.wearNodeId = wearNodeId;
this.intentSource = intentSource;
}
@Override
public void writeToParcel(Parcel out, int flags) {
CREATOR.writeToParcel(this, out, flags);
}
public static final SafeParcelableCreatorAndWriter<GetPendingIntentForWalletOnWearRequest> CREATOR = findCreator(GetPendingIntentForWalletOnWearRequest.class);
}

View file

@ -0,0 +1,30 @@
package com.google.android.gms.pay;
import android.os.Parcel;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
@Hide
@SafeParcelable.Class
public class GetWalletStatusResponse extends AbstractSafeParcelable {
@Field(1)
public boolean isWalletUiAvailable;
@Field(2)
public int[] foundIssues;
@Constructor
public GetWalletStatusResponse(@Param(1) boolean isWalletUiAvailable, @Param(2) int[] foundIssues) {
this.isWalletUiAvailable = isWalletUiAvailable;
this.foundIssues = foundIssues;
}
@Override
public void writeToParcel(Parcel out, int flags) {
CREATOR.writeToParcel(this, out, flags);
}
public static final SafeParcelableCreatorAndWriter<GetWalletStatusResponse> CREATOR = findCreator(GetWalletStatusResponse.class);
}

View file

@ -0,0 +1,29 @@
package com.google.android.gms.pay;
import android.os.Parcel;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
@Hide
@SafeParcelable.Class
public class NotifyCardTapEventRequest extends AbstractSafeParcelable {
@Nullable
@Field(1)
public String json;
@Constructor
public NotifyCardTapEventRequest(@Nullable @Param(1) String json) {
this.json = json;
}
@Override
public void writeToParcel(Parcel out, int flags) {
CREATOR.writeToParcel(this, out, flags);
}
public static final SafeParcelableCreatorAndWriter<NotifyCardTapEventRequest> CREATOR = findCreator(NotifyCardTapEventRequest.class);
}

View file

@ -0,0 +1,27 @@
package com.google.android.gms.pay;
import android.os.Parcel;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
@Hide
@SafeParcelable.Class
public class NotifyEmoneyCardStatusUpdateRequest extends AbstractSafeParcelable {
@Field(1)
public String json;
@Constructor
public NotifyEmoneyCardStatusUpdateRequest(@Param(1) String json) {
this.json = json;
}
@Override
public void writeToParcel(Parcel out, int flags) {
CREATOR.writeToParcel(this, out, flags);
}
public static final SafeParcelableCreatorAndWriter<NotifyEmoneyCardStatusUpdateRequest> CREATOR = findCreator(NotifyEmoneyCardStatusUpdateRequest.class);
}

View file

@ -0,0 +1,32 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.pay;
import android.app.Activity;
import android.content.Context;
import org.microg.gms.pay.PayClientImpl;
/**
* Entry point for Pay API.
*/
public class Pay {
/**
* Creates a new instance of {@link PayClient} for use in an {@link Activity}. This client should not be used outside of the given {@code Activity}.
*/
public static PayClient getClient(Activity activity) {
return new PayClientImpl(activity);
}
/**
* Creates a new instance of {@link PayClient} for use in a non-{@code Activity} {@link Context}.
*/
public static PayClient getClient(Context context) {
return new PayClientImpl(context);
}
}

View file

@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.pay;
import androidx.annotation.IntDef;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Pay API availability status on the device.
*/
@Target({ElementType.TYPE_USE})
@Retention(RetentionPolicy.SOURCE)
@IntDef({PayApiAvailabilityStatus.AVAILABLE, PayApiAvailabilityStatus.NOT_ELIGIBLE})
public @interface PayApiAvailabilityStatus {
/**
* Indicates that the Pay API requested is available and ready to be used.
*/
int AVAILABLE = 0;
/**
* Indicates that the user is currently not eligible for using the Pay API requested. The user may become eligible in the future.
*/
int NOT_ELIGIBLE = 2;
}

View file

@ -0,0 +1,19 @@
package com.google.android.gms.pay;
import android.os.Parcel;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
@Hide
@SafeParcelable.Class
public class PayApiError extends AbstractSafeParcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
CREATOR.writeToParcel(this, out, flags);
}
public static final SafeParcelableCreatorAndWriter<PayApiError> CREATOR = findCreator(PayApiError.class);
}

View file

@ -0,0 +1,188 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.pay;
import android.app.Activity;
import android.app.PendingIntent;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.IntentSenderRequest;
import androidx.annotation.IntDef;
import com.google.android.gms.common.api.Api;
import com.google.android.gms.common.api.HasApiKey;
import com.google.android.gms.tasks.Task;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Interface for Pay API.
*/
public interface PayClient extends HasApiKey<Api.ApiOptions.NotRequiredOptions> {
/**
* Debug message passed back in {@code onActivityResult()} when calling {@link #savePasses(String, Activity, int)} or
* {@link #savePassesJwt(String, Activity, int)}.
*/
String EXTRA_API_ERROR_MESSAGE = "extra_api_error_message";
/**
* Checks the e-money readiness for a service provider and account.
* <p>
* Important: Only apps on the allowlist for the e-money feature can call this method; otherwise, the result is a failed {@link Task}.
*
* @param serviceProvider The service provider to check readiness.
* @param accountName The email account to check readiness.
* @return One of the possible {@link EmoneyReadinessStatus}.
*/
Task<EmoneyReadiness> checkReadinessForEmoney(String serviceProvider, String accountName);
/**
* Gets the {@link PayApiAvailabilityStatus} of the current user and device.
*
* @param requestType A {@link PayClient.RequestType} for how the API will be used.
* @return One of the possible {@link PayApiAvailabilityStatus}.
*/
Task<@PayApiAvailabilityStatus Integer> getPayApiAvailabilityStatus(@RequestType int requestType);
/**
* Create a {@link PendingIntent} for the Wear Wallet activity. May return an error if pay is not supported in this region or if the watch is not reachable.
*
* @param wearNodeId The node id of the watch.
* @param intentSource The {@link PayClient.WearWalletIntentSource} that launches the requested page.
*/
Task<PendingIntent> getPendingIntentForWalletOnWear(String wearNodeId, @WearWalletIntentSource int intentSource);
/**
* Provides the product name in this market.
*/
PayClient.ProductName getProductName();
/**
* Notifies Google Play services of a card tap event.
* <p>
* Only apps on the allowlist can call this method; otherwise, the result is a failed {@link Task}.
*
* @param eventJson The event details in JSON format.
*/
Task<Void> notifyCardTapEvent(String eventJson);
/**
* Notifies Google Play services if an e-money card has been updated.
* <p>
* Important: Only apps on the allowlist for the e-money feature can call this method; otherwise, the result is a failed {@link Task}.
*
* @param json The e-money card status update details in JSON format.
*/
Task<Void> notifyEmoneyCardStatusUpdate(String json);
/**
* Saves an e-money card in JSON format.
* <p>
* Important: Only apps on the allowlist for the e-money feature can call this method; otherwise, the result is a failed {@link Task}.
*
* @param json The e-money card details in JSON format.
* @param activityResultLauncher an {@link ActivityResultLauncher} registered by caller to handle the activity results.
*/
Task<Void> pushEmoneyCard(String json, ActivityResultLauncher<IntentSenderRequest> activityResultLauncher);
/**
* Saves one or multiple passes in a JSON format.
* <p>
* Must be called from an {@code Activity}.
*
* @param json A JSON string request to save one or multiple passes. The JSON format is consistent with the JWT save link format. Refer to
* Google Pay API for Passes for an overview on how save links are generated. Only focus on how the JSON is formatted.
* There is no need to sign the JSON string.
* @param activity The {@code Activity} that will receive the callback result.
* @param requestCode An integer request code that will be passed back in {@code onActivityResult()}, allowing you to identify whom this result came from.
*/
void savePasses(String json, Activity activity, int requestCode);
/**
* Saves one or multiple passes in a JWT format.
* <p>
* Must be called from an {@code Activity}.
*
* @param jwt A JWT string token to save one or multiple passes. The token format is the same used in the JWT save link format. Refer to
* Google Pay API for Passes for an overview on how save links are generated.
* @param activity The {@code Activity} that will receive the callback result.
* @param requestCode An integer request code that will be passed back in {@code onActivityResult()}, allowing you to identify whom this result came from.
*/
void savePassesJwt(String jwt, Activity activity, int requestCode);
/**
* Indicates what the product is called in this market
*/
enum ProductName {
GOOGLE_PAY,
GOOGLE_WALLET
}
/**
* All possible request types that will be used by callers of {@link PayClient#getPayApiAvailabilityStatus(int)}.
*/
@Target({ElementType.TYPE_USE})
@Retention(RetentionPolicy.SOURCE)
@IntDef({RequestType.CARD_PROVISIONING_DEEP_LINK, RequestType.SAVE_PASSES, RequestType.SAVE_PASSES_JWT})
@interface RequestType {
/**
* Checks support of card provisioning deep links.
*/
int CARD_PROVISIONING_DEEP_LINK = 1;
/**
* Checks availability of the {@link PayClient#savePasses(String, Activity, int)} API.
*/
int SAVE_PASSES = 2;
/**
* Checks availability of the {@link PayClient#savePassesJwt(String, Activity, int)} API.
*/
int SAVE_PASSES_JWT = 3;
}
/**
* Possible result codes passed back in {@code onActivityResult()} when calling {@link PayClient#savePasses(String, Activity, int)} or
* {@link PayClient#savePassesJwt(String, Activity, int)}. These are in addition to {@link Activity#RESULT_OK} and {@link Activity#RESULT_CANCELED}.
*/
@Target({ElementType.TYPE_USE})
@Retention(RetentionPolicy.SOURCE)
@IntDef({Activity.RESULT_OK, Activity.RESULT_CANCELED, SavePassesResult.API_UNAVAILABLE, SavePassesResult.SAVE_ERROR, SavePassesResult.INTERNAL_ERROR})
@interface SavePassesResult {
/**
* The {@link PayClient#savePasses(String, Activity, int)} or {@link PayClient#savePassesJwt(String, Activity, int) API is unavailable.
* Use {@link PayClient#getPayApiAvailabilityStatus(int)} before calling the API.
*/
int API_UNAVAILABLE = 1;
/**
* An error occurred while saving the passes. Check {@code EXTRA_API_ERROR_MESSAGE} to debug the issue.
*/
int SAVE_ERROR = 2;
/**
* Indicates that an internal error occurred while calling the API. Retry the API call. If the error persists assume that the API is not available.
*/
int INTERNAL_ERROR = 3;
}
/**
* Intent source for Wear Card Management Activity. Behavior may depend on the source.
*/
@Target({ElementType.TYPE_USE})
@Retention(RetentionPolicy.SOURCE)
@IntDef({WearWalletIntentSource.OOBE, WearWalletIntentSource.SETTINGS})
@interface WearWalletIntentSource {
/**
* Start Wear Wallet for out of box experience
*/
int OOBE = 20;
/**
* Start Wear Wallet from settings
*/
int SETTINGS = 21;
}
}

View file

@ -0,0 +1,27 @@
package com.google.android.gms.pay;
import android.os.Parcel;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
@Hide
@SafeParcelable.Class
public class PushEmoneyCardRequest extends AbstractSafeParcelable {
@Field(1)
public String json;
@Constructor
public PushEmoneyCardRequest(@Param(1) String json) {
this.json = json;
}
@Override
public void writeToParcel(Parcel out, int flags) {
CREATOR.writeToParcel(this, out, flags);
}
public static final SafeParcelableCreatorAndWriter<PushEmoneyCardRequest> CREATOR = findCreator(PushEmoneyCardRequest.class);
}

View file

@ -0,0 +1,33 @@
package com.google.android.gms.pay;
import android.os.Parcel;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
@Hide
@SafeParcelable.Class
public class SavePassesRequest extends AbstractSafeParcelable {
@Nullable
@Field(1)
public String json;
@Nullable
@Field(2)
public String jwt;
@Constructor
public SavePassesRequest(@Nullable @Param(1) String json, @Nullable @Param(2) String jwt) {
this.json = json;
this.jwt = jwt;
}
@Override
public void writeToParcel(Parcel out, int flags) {
CREATOR.writeToParcel(this, out, flags);
}
public static final SafeParcelableCreatorAndWriter<SavePassesRequest> CREATOR = findCreator(SavePassesRequest.class);
}

View file

@ -0,0 +1,27 @@
package com.google.android.gms.pay;
import android.os.Parcel;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
@Hide
@SafeParcelable.Class
public class SyncBundleRequest extends AbstractSafeParcelable {
@Field(1)
public String unknownField;
@Constructor
public SyncBundleRequest(@Param(1) String unknownField) {
this.unknownField = unknownField;
}
@Override
public void writeToParcel(Parcel out, int flags) {
CREATOR.writeToParcel(this, out, flags);
}
public static final SafeParcelableCreatorAndWriter<SyncBundleRequest> CREATOR = findCreator(SyncBundleRequest.class);
}

View file

@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.pay;
import android.content.Context;
import android.os.IBinder;
import org.microg.gms.common.GmsClient;
import com.google.android.gms.pay.internal.IPayService;
import org.microg.gms.common.GmsService;
import com.google.android.gms.common.api.internal.ConnectionCallbacks;
import com.google.android.gms.common.api.internal.OnConnectionFailedListener;
public class PayApiClient extends GmsClient<IPayService> {
public PayApiClient(Context context, ConnectionCallbacks callbacks, OnConnectionFailedListener connectionFailedListener) {
super(context, callbacks, connectionFailedListener, GmsService.PAY.ACTION);
serviceId = GmsService.PAY.SERVICE_ID;
}
@Override
protected IPayService interfaceFromBinder(IBinder binder) {
return IPayService.Stub.asInterface(binder);
}
}

View file

@ -0,0 +1,131 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.pay;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.os.RemoteException;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.IntentSenderRequest;
import com.google.android.gms.common.api.Api;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.GoogleApi;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.pay.*;
import com.google.android.gms.pay.internal.IPayServiceCallbacks;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.Tasks;
import java.lang.ref.WeakReference;
public class PayClientImpl extends GoogleApi<Api.ApiOptions.NotRequiredOptions> implements PayClient {
private static final Api<Api.ApiOptions.NotRequiredOptions> API = new Api<>((options, context, looper, clientSettings, callbacks, connectionFailedListener) -> new ThirdPartyPayApiClient(context, callbacks, connectionFailedListener));
public PayClientImpl(Context context) {
super(context, API, Api.ApiOptions.NO_OPTIONS);
}
@Override
public Task<EmoneyReadiness> checkReadinessForEmoney(String serviceProvider, String accountName) {
return null;
}
@Override
public Task<@PayApiAvailabilityStatus Integer> getPayApiAvailabilityStatus(@RequestType int requestType) {
return this.<Integer, ThirdPartyPayApiClient>scheduleTask((client, completionSource) -> {
client.getServiceInterface().getPayApiAvailabilityStatus(new GetPayApiAvailabilityStatusRequest(requestType), new PayServiceCallbacks() {
@Override
public void onPayApiAvailabilityStatus(Status status, int availabilityStatus) {
if (status.isSuccess() && availabilityStatus == 3) {
// Invalid availabilityStatus
completionSource.trySetException(new ApiException(Status.INTERNAL_ERROR));
} else if (availabilityStatus == 1) {
if (status.isSuccess()) {
completionSource.trySetResult(PayApiAvailabilityStatus.NOT_ELIGIBLE);
} else {
completionSource.trySetException(new ApiException(status));
}
} else {
if (status.isSuccess()) {
completionSource.trySetResult(availabilityStatus);
} else {
completionSource.trySetException(new ApiException(status));
}
}
}
});
});
}
@Override
public Task<PendingIntent> getPendingIntentForWalletOnWear(String wearNodeId, @WearWalletIntentSource int intentSource) {
return null;
}
@Override
public ProductName getProductName() {
return ProductName.GOOGLE_WALLET;
}
@Override
public Task<Void> notifyCardTapEvent(String eventJson) {
return null;
}
@Override
public Task<Void> notifyEmoneyCardStatusUpdate(String json) {
return null;
}
@Override
public Task<Void> pushEmoneyCard(String json, ActivityResultLauncher<IntentSenderRequest> activityResultLauncher) {
return null;
}
@Override
public void savePasses(String json, Activity activity, int requestCode) {
savePasses(new SavePassesRequest(json, null), activity, requestCode);
}
@Override
public void savePassesJwt(String jwt, Activity activity, int requestCode) {
savePasses(new SavePassesRequest(null, jwt), activity, requestCode);
}
private void savePasses(SavePassesRequest request, Activity activity, int requestCode) {
// We don't want to keep a reference to the activity to not leak it
WeakReference<Activity> weakActivity = new WeakReference<>(activity);
PayServiceCallbacks callbacks = new PayServiceCallbacks() {
@Override
public void onPendingIntent(Status status) {
Activity activity = weakActivity.get();
if (activity != null) {
if (status.hasResolution()) {
try {
status.startResolutionForResult(activity, requestCode);
} catch (IntentSender.SendIntentException e) {
// Ignored
}
} else {
PendingIntent resultIntent = activity.createPendingResult(requestCode, new Intent(), PendingIntent.FLAG_ONE_SHOT);
if (resultIntent != null) {
try {
resultIntent.send(status.isSuccess() ? -1 : status.getStatusCode());
} catch (PendingIntent.CanceledException e) {
// Ignored
}
}
}
}
}
};
this.<Void, ThirdPartyPayApiClient>scheduleTask((client, completionSource) -> client.getServiceInterface().savePasses(request, callbacks))
.addOnFailureListener((exception) -> callbacks.onPendingIntent(Status.INTERNAL_ERROR));
}
}

View file

@ -0,0 +1,59 @@
/*
* SPDX-FileCopyrightText: 2024 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.pay;
import android.app.PendingIntent;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.pay.EmoneyReadiness;
import com.google.android.gms.pay.PayApiError;
import com.google.android.gms.pay.internal.IPayServiceCallbacks;
public class PayServiceCallbacks extends IPayServiceCallbacks.Stub {
@Override
public void onStatus(Status status) {
throw new UnsupportedOperationException();
}
@Override
public void onPendingIntentForWalletOnWear(Status status, PendingIntent pendingIntent) {
throw new UnsupportedOperationException();
}
@Override
public void onStatusAndBoolean(Status status, boolean b) {
throw new UnsupportedOperationException();
}
@Override
public void onPayApiError(PayApiError error) {
throw new UnsupportedOperationException();
}
@Override
public void onStatusAndByteArray(Status status, byte[] bArr) {
throw new UnsupportedOperationException();
}
@Override
public void onStatusAndLong(Status status, long l) {
throw new UnsupportedOperationException();
}
@Override
public void onPendingIntent(Status status) {
throw new UnsupportedOperationException();
}
@Override
public void onPayApiAvailabilityStatus(Status status, int i) {
throw new UnsupportedOperationException();
}
@Override
public void onEmoneyReadiness(Status status, EmoneyReadiness emoneyReadiness) {
throw new UnsupportedOperationException();
}
}

View file

@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: 2024 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.pay;
import android.content.Context;
import android.os.IBinder;
import com.google.android.gms.pay.internal.IThirdPartyPayService;
import org.microg.gms.common.GmsClient;
import org.microg.gms.common.GmsService;
import com.google.android.gms.common.api.internal.ConnectionCallbacks;
import com.google.android.gms.common.api.internal.OnConnectionFailedListener;
public class ThirdPartyPayApiClient extends GmsClient<IThirdPartyPayService> {
public ThirdPartyPayApiClient(Context context, ConnectionCallbacks callbacks, OnConnectionFailedListener connectionFailedListener) {
super(context, callbacks, connectionFailedListener, GmsService.PAY.SECONDARY_ACTIONS[0]);
serviceId = GmsService.PAY.SERVICE_ID;
}
@Override
protected IThirdPartyPayService interfaceFromBinder(IBinder binder) {
return IThirdPartyPayService.Stub.asInterface(binder);
}
}