Repo Created
This commit is contained in:
parent
eb305e2886
commit
a8c22c65db
4784 changed files with 329907 additions and 2 deletions
55
play-services-basement/build.gradle
Normal file
55
play-services-basement/build.gradle
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015 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.common"
|
||||
|
||||
compileSdkVersion androidCompileSdk
|
||||
buildToolsVersion "$androidBuildVersionTools"
|
||||
|
||||
aidlPackagedList "com/google/android/gms/common/api/Status.aidl"
|
||||
aidlPackagedList "com/google/android/gms/common/ConnectionResult.aidl"
|
||||
aidlPackagedList "com/google/android/gms/common/internal/IAccountAccessor.aidl"
|
||||
aidlPackagedList "com/google/android/gms/common/internal/ICancelToken.aidl"
|
||||
aidlPackagedList "com/google/android/gms/common/server/FavaDiagnosticsEntity.aidl"
|
||||
aidlPackagedList "com/google/android/gms/dynamic/IObjectWrapper.aidl"
|
||||
|
||||
buildFeatures {
|
||||
aidl = true
|
||||
buildConfig = true
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
versionName version
|
||||
minSdkVersion androidMinSdk
|
||||
targetSdkVersion androidTargetSdk
|
||||
buildConfigField "int", "VERSION_CODE", "$appVersionCode"
|
||||
consumerProguardFile 'consumer-rules.pro'
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
}
|
||||
}
|
||||
|
||||
apply from: '../gradle/publish-android.gradle'
|
||||
|
||||
description = 'microG implementation of play-services-basement'
|
||||
|
||||
dependencies {
|
||||
// Dependencies from play-services-basement:18.8.0
|
||||
api 'androidx.collection:collection:1.0.0'
|
||||
api 'androidx.core:core:1.2.0'
|
||||
api 'androidx.fragment:fragment:1.1.0'
|
||||
// TODO: Dependencies from play-services-stats:17.1.0
|
||||
api 'androidx.legacy:legacy-support-core-utils:1.0.0'
|
||||
|
||||
annotationProcessor project(':safe-parcel-processor')
|
||||
}
|
||||
19
play-services-basement/consumer-rules.pro
Normal file
19
play-services-basement/consumer-rules.pro
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
# Keep AutoSafeParcelables
|
||||
-keep public class * extends org.microg.safeparcel.AutoSafeParcelable {
|
||||
@com.google.android.gms.common.internal.safeparcel.SafeParcelable$Field *;
|
||||
@org.microg.safeparcel.SafeParceled *;
|
||||
}
|
||||
|
||||
# Keep asInterface method cause it's accessed from SafeParcel
|
||||
-keepattributes InnerClasses
|
||||
-keep public class * extends android.os.IInterface {
|
||||
public static * asInterface(android.os.IBinder);
|
||||
}
|
||||
-keep public class * extends android.os.Binder { public static *; }
|
||||
|
||||
# Keep name of SafeParcelables and their creators
|
||||
-keepnames public class * implements com.google.android.gms.common.internal.safeparcel.SafeParcelable
|
||||
-keepnames public class * implements com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter
|
||||
44
play-services-basement/ktx/build.gradle
Normal file
44
play-services-basement/ktx/build.gradle
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021, 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-basement")
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
|
||||
}
|
||||
|
||||
android {
|
||||
namespace "org.microg.gms.basement.ktx"
|
||||
|
||||
compileSdkVersion androidCompileSdk
|
||||
buildToolsVersion "$androidBuildVersionTools"
|
||||
|
||||
defaultConfig {
|
||||
versionName version
|
||||
minSdkVersion androidMinSdk
|
||||
targetSdkVersion androidTargetSdk
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = 1.8
|
||||
}
|
||||
}
|
||||
|
||||
apply from: '../../gradle/publish-android.gradle'
|
||||
|
||||
description = 'microG kotlin extensions for play-services-basement'
|
||||
7
play-services-basement/ktx/src/main/AndroidManifest.xml
Normal file
7
play-services-basement/ktx/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ SPDX-FileCopyrightText: 2021, microG Project Team
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<manifest />
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (C) 2019 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.dynamic
|
||||
|
||||
inline fun <reified T> IObjectWrapper?.unwrap(): T? = ObjectWrapper.unwrapTyped(this, T::class.java)
|
||||
13
play-services-basement/src/main/AndroidManifest.xml
Normal file
13
play-services-basement/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ SPDX-FileCopyrightText: 2016 microG Project Team
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application>
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.version"
|
||||
android:value="@integer/google_play_services_version"/>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package com.google.android.gms.common;
|
||||
|
||||
parcelable ConnectionResult;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package com.google.android.gms.common;
|
||||
|
||||
parcelable GoogleCertificatesLookupQuery;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package com.google.android.gms.common;
|
||||
|
||||
parcelable GoogleCertificatesLookupResponse;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package com.google.android.gms.common;
|
||||
|
||||
parcelable GoogleCertificatesQuery;
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.api;
|
||||
|
||||
parcelable ApiMetadata;
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.api;
|
||||
|
||||
parcelable ComplianceOptions;
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.api;
|
||||
|
||||
parcelable Scope;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package com.google.android.gms.common.api;
|
||||
|
||||
parcelable Status;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.internal;
|
||||
parcelable ConnectionInfo;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package com.google.android.gms.common.internal;
|
||||
|
||||
parcelable GetServiceRequest;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.google.android.gms.common.internal;
|
||||
|
||||
interface IAccountAccessor {
|
||||
Account getAccount() = 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.google.android.gms.common.internal;
|
||||
|
||||
interface ICancelToken {
|
||||
void cancel();
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.google.android.gms.common.internal;
|
||||
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
interface ICertData {
|
||||
IObjectWrapper getWrappedBytes();
|
||||
int remoteHashCode();
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.internal;
|
||||
|
||||
import android.os.Bundle;
|
||||
import com.google.android.gms.common.internal.ConnectionInfo;
|
||||
|
||||
interface IGmsCallbacks {
|
||||
void onPostInitComplete(int statusCode, IBinder binder, in Bundle params);
|
||||
void onAccountValidationComplete(int statusCode, in Bundle params);
|
||||
void onPostInitCompleteWithConnectionInfo(int statusCode, IBinder binder, in ConnectionInfo info);
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package com.google.android.gms.common.internal;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.google.android.gms.common.internal.IGmsCallbacks;
|
||||
import com.google.android.gms.common.internal.GetServiceRequest;
|
||||
import com.google.android.gms.common.internal.ValidateAccountRequest;
|
||||
|
||||
interface IGmsServiceBroker {
|
||||
void getPlusService(IGmsCallbacks callback, int code, String packageName, String authPackage, in String[] scopes, String accountName, in Bundle params) = 0;
|
||||
void getPanoramaService(IGmsCallbacks callback, int code, String packageName, in Bundle params) = 1;
|
||||
void getAppDataSearchService(IGmsCallbacks callback, int code, String packageName) = 2;
|
||||
void getWalletService(IGmsCallbacks callback, int code) = 3;
|
||||
void getPeopleService(IGmsCallbacks callback, int code, String str, in Bundle params) = 4;
|
||||
void getReportingService(IGmsCallbacks callback, int code, String str, in Bundle params) = 5;
|
||||
void getLocationService(IGmsCallbacks callback, int code, String str, in Bundle params) = 6;
|
||||
void getGoogleLocationManagerService(IGmsCallbacks callback, int code, String str, in Bundle params) = 7;
|
||||
void getGamesService(IGmsCallbacks callback, int code, String packageName, String accountName, in String[] scopes, String gamePackageName, IBinder popupWindowToken, String desiredLocale, in Bundle params) = 8;
|
||||
void getAppStateService(IGmsCallbacks callback, int code, String packageName, String accountName, in String[] scopes) = 9;
|
||||
void getPlayLogService(IGmsCallbacks callback, int code, String packageName, in Bundle params) = 10;
|
||||
void getAdMobService(IGmsCallbacks callback, int code, String packageName, in Bundle params) = 11;
|
||||
void getDroidGuardService(IGmsCallbacks callback, int code, String packageName, in Bundle params) = 12;
|
||||
void getLockboxService(IGmsCallbacks callback, int code, String packageName, in Bundle params) = 13;
|
||||
void getCastMirroringService(IGmsCallbacks callback, int code, String packageName, in Bundle params) = 14;
|
||||
void getNetworkQualityService(IGmsCallbacks callback, int code, String packageName, in Bundle params) = 15;
|
||||
void getGoogleIdentityService(IGmsCallbacks callback, int code, String packageName, in Bundle params) = 16;
|
||||
void getGoogleFeedbackService(IGmsCallbacks callback, int code, String packageName, in Bundle params) = 17;
|
||||
void getCastService(IGmsCallbacks callback, int code, String packageName, IBinder binder, in Bundle params) = 18;
|
||||
void getDriveService(IGmsCallbacks callback, int code, String packageName, in String[] args, String str2, in Bundle params) = 19;
|
||||
void getLightweightAppDataSearchService(IGmsCallbacks callback, int code, String packageName) = 20;
|
||||
void getSearchAdministrationService(IGmsCallbacks callback, int code, String packageName) = 21;
|
||||
void getAutoBackupService(IGmsCallbacks callback, int code, String packageName, in Bundle params) = 22;
|
||||
void getAddressService(IGmsCallbacks callback, int code, String packageName) = 23;
|
||||
|
||||
void getWalletServiceWithPackageName(IGmsCallbacks callback, int code, String packageName) = 41;
|
||||
|
||||
void getService(IGmsCallbacks callback, in GetServiceRequest request) = 45;
|
||||
void validateAccount(IGmsCallbacks callback, in ValidateAccountRequest request) = 46;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.google.android.gms.common.internal;
|
||||
|
||||
import com.google.android.gms.common.GoogleCertificatesLookupQuery;
|
||||
import com.google.android.gms.common.GoogleCertificatesLookupResponse;
|
||||
import com.google.android.gms.common.GoogleCertificatesQuery;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
interface IGoogleCertificatesApi {
|
||||
IObjectWrapper getGoogleCertificates() = 0;
|
||||
IObjectWrapper getGoogleReleaseCertificates() = 1;
|
||||
boolean isGoogleReleaseSigned(String packageName, IObjectWrapper certData) = 2;
|
||||
boolean isGoogleSigned(String packageName, IObjectWrapper certData) = 3;
|
||||
boolean isGoogleOrPlatformSigned(in GoogleCertificatesQuery query, IObjectWrapper packageManager) = 4;
|
||||
GoogleCertificatesLookupResponse isPackageGoogleOrPlatformSigned(in GoogleCertificatesLookupQuery query) = 5;
|
||||
boolean isPackageGoogleOrPlatformSignedAvailable() = 6;
|
||||
GoogleCertificatesLookupResponse queryPackageSigned(in GoogleCertificatesLookupQuery query) = 7;
|
||||
boolean isFineGrainedPackageVerificationAvailable() = 8;
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package com.google.android.gms.common.internal;
|
||||
|
||||
parcelable ValidateAccountRequest;
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.google.android.gms.dynamic;
|
||||
|
||||
/**
|
||||
* The concrete class implementing IObjectWrapper must have exactly one declared private field
|
||||
* for the wrapped object. Preferably, this is an instance of the ObjectWrapper<T> class.
|
||||
*/
|
||||
interface IObjectWrapper {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.google.android.gms.dynamite;
|
||||
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
|
||||
interface IDynamiteLoader {
|
||||
int getModuleVersion(IObjectWrapper wrappedContext, String moduleId) = 0;
|
||||
int getModuleVersion2(IObjectWrapper wrappedContext, String moduleId, boolean updateConfigIfRequired) = 2;
|
||||
int getModuleVersionV2(IObjectWrapper wrappedContext, String moduleId, boolean updateConfigIfRequired) = 4;
|
||||
IObjectWrapper getModuleVersionV3(IObjectWrapper wrappedContext, String moduleId, boolean updateConfigIfRequired, long requestStartTime) = 6;
|
||||
|
||||
IObjectWrapper createModuleContext(IObjectWrapper wrappedContext, String moduleId, int minVersion) = 1;
|
||||
IObjectWrapper createModuleContextV2(IObjectWrapper wrappedContext, String moduleId, int minVersion) = 3;
|
||||
IObjectWrapper createModuleContextV3(IObjectWrapper wrappedContext, String moduleId, int minVersion, IObjectWrapper cursorWrapped) = 7;
|
||||
|
||||
int getIDynamiteLoaderVersion() = 5;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: CC-BY-4.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.
|
||||
*/
|
||||
/**
|
||||
* Contains classes for Google Search Actions.
|
||||
*/
|
||||
package com.google.android.gms.actions;
|
||||
|
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2016 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.common;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.os.Parcel;
|
||||
import android.text.TextUtils;
|
||||
import androidx.annotation.NonNull;
|
||||
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 java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Contains all possible error codes for when a client fails to connect to Google Play services.
|
||||
* These error codes are used by {@link GoogleApiClient.OnConnectionFailedListener}.
|
||||
*/
|
||||
@SafeParcelable.Class
|
||||
public class ConnectionResult extends AbstractSafeParcelable {
|
||||
/**
|
||||
* The connection was successful.
|
||||
*/
|
||||
public static final int SUCCESS = 0;
|
||||
/**
|
||||
* Google Play services is missing on this device. The calling activity should pass this error
|
||||
* code to {@link GooglePlayServicesUtil#getErrorDialog(int, Activity, int)} to get a localized
|
||||
* error dialog that will resolve the error when shown.
|
||||
*/
|
||||
public static final int SERVICE_MISSING = 1;
|
||||
/**
|
||||
* The installed version of Google Play services is out of date. The calling activity should
|
||||
* pass this error code to {@link GooglePlayServicesUtil#getErrorDialog(int, Activity, int)} to
|
||||
* get a localized error dialog that will resolve the error when shown.
|
||||
*/
|
||||
public static final int SERVICE_VERSION_UPDATE_REQUIRED = 2;
|
||||
/**
|
||||
* The installed version of Google Play services has been disabled on this device. The calling
|
||||
* activity should pass this error code to
|
||||
* {@link GooglePlayServicesUtil#getErrorDialog(int, Activity, int)} to get a localized error
|
||||
* dialog that will resolve the error when shown.
|
||||
*/
|
||||
public static final int SERVICE_DISABLED = 3;
|
||||
/**
|
||||
* The client attempted to connect to the service but the user is not signed in. The client may
|
||||
* choose to continue without using the API or it may call
|
||||
* {@link #startResolutionForResult(Activity, int)} to prompt the user to sign in. After the
|
||||
* sign in activity returns with {@link Activity#RESULT_OK} further attempts to connect should
|
||||
* succeed.
|
||||
*/
|
||||
public static final int SIGN_IN_REQUIRED = 4;
|
||||
/**
|
||||
* The client attempted to connect to the service with an invalid account name specified.
|
||||
*/
|
||||
public static final int INVALID_ACCOUNT = 5;
|
||||
/**
|
||||
* Completing the connection requires some form of resolution. A resolution will be available
|
||||
* to be started with {@link #startResolutionForResult(Activity, int)}. If the result returned
|
||||
* is {@link Activity#RESULT_OK}, then further attempts to connect should either complete or
|
||||
* continue on to the next issue that needs to be resolved.
|
||||
*/
|
||||
public static final int RESOLUTION_REQUIRED = 6;
|
||||
/**
|
||||
* A network error occurred. Retrying should resolve the problem.
|
||||
*/
|
||||
public static final int NETWORK_ERROR = 7;
|
||||
/**
|
||||
* An internal error occurred. Retrying should resolve the problem.
|
||||
*/
|
||||
public static final int INTERNAL_ERROR = 8;
|
||||
/**
|
||||
* The version of the Google Play services installed on this device is not authentic.
|
||||
*/
|
||||
public static final int SERVICE_INVALID = 9;
|
||||
/**
|
||||
* The application is misconfigured. This error is not recoverable and will be treated as
|
||||
* fatal. The developer should look at the logs after this to determine more actionable
|
||||
* information.
|
||||
*/
|
||||
public static final int DEVELOPER_ERROR = 10;
|
||||
/**
|
||||
* The application is not licensed to the user. This error is not recoverable and will be
|
||||
* treated as fatal.
|
||||
*/
|
||||
public static final int LICENSE_CHECK_FAILED = 11;
|
||||
/**
|
||||
* The client canceled the connection by calling {@link GoogleApiClient#disconnect()}.
|
||||
* Only returned by {@link GoogleApiClient#blockingConnect()}.
|
||||
*/
|
||||
public static final int CANCELED = 13;
|
||||
/**
|
||||
* The timeout was exceeded while waiting for the connection to complete. Only returned by
|
||||
* {@link GoogleApiClient#blockingConnect()}.
|
||||
*/
|
||||
public static final int TIMEOUT = 14;
|
||||
/**
|
||||
* An interrupt occurred while waiting for the connection complete. Only returned by
|
||||
* {@link GoogleApiClient#blockingConnect()}.
|
||||
*/
|
||||
public static final int INTERRUPTED = 15;
|
||||
/**
|
||||
* One of the API components you attempted to connect to is not available. The API will not
|
||||
* work on this device, and updating Google Play services will not likely solve the problem.
|
||||
* Using the API on the device should be avoided.
|
||||
*/
|
||||
public static final int API_UNAVAILABLE = 16;
|
||||
/**
|
||||
* The client attempted to connect to the service but the user is not signed in. An error may have occurred when signing in the user and the error can not
|
||||
* be recovered with any user interaction. Alternately, the API may have been requested with {@link GoogleApiClient.Builder#addApiIfAvailable(Api, Scope...)}
|
||||
* and it may be the case that no required APIs needed authentication, so authentication did not occur.
|
||||
* <p>
|
||||
* When seeing this error code, there is no resolution for the sign-in failure.
|
||||
*/
|
||||
public static final int SIGN_IN_FAILED = 17;
|
||||
/**
|
||||
* Google Play service is currently being updated on this device.
|
||||
*/
|
||||
public static final int SERVICE_UPDATING = 18;
|
||||
|
||||
/**
|
||||
* Service doesn't have one or more required permissions.
|
||||
*/
|
||||
public static final int SERVICE_MISSING_PERMISSION = 19;
|
||||
/**
|
||||
* The current user profile is restricted and cannot use authenticated features. (Jelly Bean MR2+ Restricted Profiles for Android tablets)
|
||||
*/
|
||||
public static final int RESTRICTED_PROFILE = 20;
|
||||
/**
|
||||
* There was a user-resolvable issue connecting to Google Play services, but when attempting to start the resolution, the activity was not found.
|
||||
* <p>
|
||||
* This can occur when attempting to resolve issues connecting to Google Play services on emulators with Google APIs but not Google Play Store.
|
||||
*/
|
||||
public static final int RESOLUTION_ACTIVITY_NOT_FOUND = 22;
|
||||
/**
|
||||
* The API being requested is disabled on this device for this application. Trying again at a later time may succeed.
|
||||
*/
|
||||
public static final int API_DISABLED = 23;
|
||||
/**
|
||||
* The API being requested is disabled for this connection attempt, but may work for other connections.
|
||||
*/
|
||||
public static final int API_DISABLED_FOR_CONNECTION = 24;
|
||||
|
||||
/**
|
||||
* The Drive API requires external storage (such as an SD card), but no external storage is
|
||||
* mounted. This error is recoverable if the user installs external storage (if none is
|
||||
* present) and ensures that it is mounted (which may involve disabling USB storage mode,
|
||||
* formatting the storage, or other initialization as required by the device).
|
||||
* <p/>
|
||||
* This error should never be returned on a device with emulated external storage. On devices
|
||||
* with emulated external storage, the emulated "external storage" is always present regardless
|
||||
* of whether the device also has removable storage.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int DRIVE_EXTERNAL_STORAGE_REQUIRED = 1500;
|
||||
|
||||
@Field(1)
|
||||
int versionCode = 1;
|
||||
@Field(value = 2, getterName = "getErrorCode")
|
||||
private int statusCode;
|
||||
@Field(value = 3, getterName = "getResolution")
|
||||
private PendingIntent resolution;
|
||||
@Field(value = 4, getterName = "getErrorMessage")
|
||||
private String message;
|
||||
|
||||
private ConnectionResult() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a connection result.
|
||||
*
|
||||
* @param statusCode The status code.
|
||||
*/
|
||||
public ConnectionResult(int statusCode) {
|
||||
this(statusCode, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a connection result.
|
||||
*
|
||||
* @param statusCode The status code.
|
||||
* @param resolution A pending intent that will resolve the issue when started, or null.
|
||||
*/
|
||||
public ConnectionResult(int statusCode, PendingIntent resolution) {
|
||||
this(statusCode, resolution, getStatusString(statusCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a connection result.
|
||||
*
|
||||
* @param statusCode The status code.
|
||||
* @param resolution A pending intent that will resolve the issue when started, or null.
|
||||
* @param message An additional error message for the connection result, or null.
|
||||
*/
|
||||
@Constructor
|
||||
public ConnectionResult(@Param(2) int statusCode, @Param(3) PendingIntent resolution, @Param(4) String message) {
|
||||
this.statusCode = statusCode;
|
||||
this.resolution = resolution;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
static String getStatusString(int statusCode) {
|
||||
switch (statusCode) {
|
||||
case -1:
|
||||
return "UNKNOWN";
|
||||
case 0:
|
||||
return "SUCCESS";
|
||||
case 1:
|
||||
return "SERVICE_MISSING";
|
||||
case 2:
|
||||
return "SERVICE_VERSION_UPDATE_REQUIRED";
|
||||
case 3:
|
||||
return "SERVICE_DISABLED";
|
||||
case 4:
|
||||
return "SIGN_IN_REQUIRED";
|
||||
case 5:
|
||||
return "INVALID_ACCOUNT";
|
||||
case 6:
|
||||
return "RESOLUTION_REQUIRED";
|
||||
case 7:
|
||||
return "NETWORK_ERROR";
|
||||
case 8:
|
||||
return "INTERNAL_ERROR";
|
||||
case 9:
|
||||
return "SERVICE_INVALID";
|
||||
case 10:
|
||||
return "DEVELOPER_ERROR";
|
||||
case 11:
|
||||
return "LICENSE_CHECK_FAILED";
|
||||
case 13:
|
||||
return "CANCELED";
|
||||
case 14:
|
||||
return "TIMEOUT";
|
||||
case 15:
|
||||
return "INTERRUPTED";
|
||||
case 16:
|
||||
return "API_UNAVAILABLE";
|
||||
case 17:
|
||||
return "SIGN_IN_FAILED";
|
||||
case 18:
|
||||
return "SERVICE_UPDATING";
|
||||
case 19:
|
||||
return "SERVICE_MISSING_PERMISSION";
|
||||
case 20:
|
||||
return "RESTRICTED_PROFILE";
|
||||
case 21:
|
||||
return "API_VERSION_UPDATE_REQUIRED";
|
||||
case 42:
|
||||
return "UPDATE_ANDROID_WEAR";
|
||||
case 99:
|
||||
return "UNFINISHED";
|
||||
case 1500:
|
||||
return "DRIVE_EXTERNAL_STORAGE_REQUIRED";
|
||||
default:
|
||||
return "UNKNOWN_ERROR_CODE(" + statusCode + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
} else if (!(o instanceof ConnectionResult)) {
|
||||
return false;
|
||||
} else {
|
||||
ConnectionResult r = (ConnectionResult) o;
|
||||
return statusCode == r.statusCode && resolution == null ? r.resolution == null : resolution.equals(r.resolution) && TextUtils.equals(message, r.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the type of error that interrupted connection.
|
||||
*
|
||||
* @return the error code, or {@link #SUCCESS} if no error occurred.
|
||||
*/
|
||||
public int getErrorCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an error message for connection result.
|
||||
*
|
||||
* @return the message
|
||||
*/
|
||||
public String getErrorMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* A pending intent to resolve the connection failure. This intent can be started with
|
||||
* {@link Activity#startIntentSenderForResult(IntentSender, int, Intent, int, int, int)} to
|
||||
* present UI to solve the issue.
|
||||
*
|
||||
* @return The pending intent to resolve the connection failure.
|
||||
*/
|
||||
public PendingIntent getResolution() {
|
||||
return resolution;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(new Object[]{statusCode, resolution, message});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if calling {@link #startResolutionForResult(Activity, int)} will start
|
||||
* any intents requiring user interaction.
|
||||
*
|
||||
* @return {@code true} if there is a resolution that can be started.
|
||||
*/
|
||||
public boolean hasResolution() {
|
||||
return statusCode != 0 && resolution != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the connection was successful.
|
||||
*
|
||||
* @return {@code true} if the connection was successful, {@code false} if there was an error.
|
||||
*/
|
||||
public boolean isSuccess() {
|
||||
return statusCode == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves an error by starting any intents requiring user interaction. See
|
||||
* {@link #SIGN_IN_REQUIRED}, and {@link #RESOLUTION_REQUIRED}.
|
||||
*
|
||||
* @param activity An Activity context to use to resolve the issue. The activity's
|
||||
* {@link Activity#onActivityResult} method will be invoked after the user
|
||||
* is done. If the resultCode is {@link Activity#RESULT_OK}, the application
|
||||
* should try to connect again.
|
||||
* @param requestCode The request code to pass to {@link Activity#onActivityResult}.
|
||||
* @throws IntentSender.SendIntentException If the resolution intent has been canceled or is no
|
||||
* longer able to execute the request.
|
||||
*/
|
||||
public void startResolutionForResult(Activity activity, int requestCode) throws
|
||||
IntentSender.SendIntentException {
|
||||
if (hasResolution()) {
|
||||
activity.startIntentSenderForResult(resolution.getIntentSender(), requestCode, null, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
CREATOR.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
public static final SafeParcelableCreatorAndWriter<ConnectionResult> CREATOR = findCreator(ConnectionResult.class);
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common;
|
||||
|
||||
import android.os.Parcel;
|
||||
import androidx.annotation.NonNull;
|
||||
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.utils.ToStringHelper;
|
||||
|
||||
@SafeParcelable.Class
|
||||
public class Feature extends AbstractSafeParcelable {
|
||||
@Field(value = 1, getterName = "getName")
|
||||
private String name;
|
||||
@Field(2)
|
||||
int oldVersion;
|
||||
@Field(value = 3, getterName = "getVersion", defaultValue = "-1")
|
||||
private long version = -1;
|
||||
|
||||
private Feature() {
|
||||
}
|
||||
|
||||
@Constructor
|
||||
public Feature(@Param(1) String name, @Param(3) long version) {
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
if (version == -1) return oldVersion;
|
||||
return version;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringHelper.name("Feature").value(name).value(getVersion()).end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
CREATOR.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
public static final SafeParcelableCreatorAndWriter<Feature> CREATOR = findCreator(Feature.class);
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import androidx.annotation.NonNull;
|
||||
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 com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
|
||||
@SafeParcelable.Class
|
||||
public class GoogleCertificatesLookupQuery extends AbstractSafeParcelable {
|
||||
@Field(value = 1, getterName = "getCallingPackage")
|
||||
String callingPackage;
|
||||
@Field(2)
|
||||
boolean allowTestKeys;
|
||||
@Field(3)
|
||||
boolean ignoreTestKeysOverride;
|
||||
@Field(4)
|
||||
IObjectWrapper contextWrapper;
|
||||
private Context context;
|
||||
@Field(5)
|
||||
boolean isChimeraPackage;
|
||||
@Field(6)
|
||||
boolean includeHashesInErrorMessage;
|
||||
|
||||
public String getCallingPackage() {
|
||||
return callingPackage;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
if (context == null && contextWrapper != null) {
|
||||
context = ObjectWrapper.unwrapTyped(contextWrapper, Context.class);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
CREATOR.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
public static final SafeParcelableCreatorAndWriter<GoogleCertificatesLookupQuery> CREATOR = findCreator(GoogleCertificatesLookupQuery.class);
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common;
|
||||
|
||||
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;
|
||||
|
||||
@SafeParcelable.Class
|
||||
public class GoogleCertificatesLookupResponse extends AbstractSafeParcelable {
|
||||
@Field(1)
|
||||
public final boolean result;
|
||||
@Field(2)
|
||||
public final String errorMessage;
|
||||
@Field(3)
|
||||
public final int statusValue;
|
||||
@Field(4)
|
||||
public final int firstPartyStatusValue;
|
||||
|
||||
@Constructor
|
||||
public GoogleCertificatesLookupResponse(@Param(1) boolean result, @Param(2) String errorMessage, @Param(3) int statusValue, @Param(4) int firstPartyStatusValue) {
|
||||
this.result = result;
|
||||
this.errorMessage = errorMessage;
|
||||
this.statusValue = statusValue;
|
||||
this.firstPartyStatusValue = firstPartyStatusValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
CREATOR.writeToParcel(this, out, flags);
|
||||
}
|
||||
|
||||
public static final SafeParcelableCreatorAndWriter<GoogleCertificatesLookupResponse> CREATOR = findCreator(GoogleCertificatesLookupResponse.class);
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
import android.os.RemoteException;
|
||||
import androidx.annotation.NonNull;
|
||||
import com.google.android.gms.common.internal.CertData;
|
||||
import com.google.android.gms.common.internal.ICertData;
|
||||
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 com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
import org.microg.gms.common.Hide;
|
||||
|
||||
@Hide
|
||||
@SafeParcelable.Class
|
||||
public class GoogleCertificatesQuery extends AbstractSafeParcelable {
|
||||
@Field(value = 1, getterName = "getCallingPackage")
|
||||
String callingPackage;
|
||||
@Field(2)
|
||||
IBinder certDataBinder;
|
||||
private CertData certData;
|
||||
@Field(3)
|
||||
boolean allowTestKeys;
|
||||
@Field(4)
|
||||
boolean ignoreTestKeysOverride;
|
||||
|
||||
public String getCallingPackage() {
|
||||
return callingPackage;
|
||||
}
|
||||
|
||||
public CertData getCertData() {
|
||||
if (certData == null && certDataBinder != null) {
|
||||
certData = CertData.unwrap(certDataBinder);
|
||||
}
|
||||
return certData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
CREATOR.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
public static final SafeParcelableCreatorAndWriter<GoogleCertificatesQuery> CREATOR = findCreator(GoogleCertificatesQuery.class);
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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.common;
|
||||
|
||||
/**
|
||||
* Indicates Google Play services is not available.
|
||||
*/
|
||||
public class GooglePlayServicesNotAvailableException extends Exception {
|
||||
/**
|
||||
* The error code returned by {@link GoogleApiAvailability#isGooglePlayServicesAvailable(Context)} call.
|
||||
*/
|
||||
public final int errorCode;
|
||||
|
||||
public GooglePlayServicesNotAvailableException(int errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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.common;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* {@code GooglePlayServicesRepairableException}s are special instances of {@link UserRecoverableException}s which are
|
||||
* thrown when Google Play services is not installed, up-to-date, or enabled. In these cases, client code can use
|
||||
* {@link #getConnectionStatusCode()} in conjunction with {@link GoogleApiAvailability#getErrorDialog(android.app.Activity, int, int)}
|
||||
* to provide users with a localized {@link Dialog} that will allow users to install, update, or otherwise enable Google Play services.
|
||||
*/
|
||||
public class GooglePlayServicesRepairableException extends UserRecoverableException {
|
||||
private final int connectionStatusCode;
|
||||
|
||||
/**
|
||||
* Creates a {@link GooglePlayServicesRepairableException}.
|
||||
*
|
||||
* @param connectionStatusCode a code for the {@link ConnectionResult} {@code statusCode} of the exception
|
||||
* @param message a string message for the exception
|
||||
* @param intent an intent that may be started to resolve the connection issue with Google Play services
|
||||
*/
|
||||
public GooglePlayServicesRepairableException(int connectionStatusCode, String message, Intent intent) {
|
||||
super(message, intent);
|
||||
this.connectionStatusCode = connectionStatusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ConnectionResult} {@code statusCode} of the exception.
|
||||
* <p>
|
||||
* This value may be passed in to {@link GoogleApiAvailability#getErrorDialog(android.app.Activity, int, int)} to
|
||||
* provide users with a localized {@link Dialog} that will allow users to install, update, or otherwise enable Google Play services.
|
||||
*/
|
||||
public int getConnectionStatusCode() {
|
||||
return connectionStatusCode;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015 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.common;
|
||||
|
||||
import org.microg.gms.common.Hide;
|
||||
|
||||
/**
|
||||
* OAuth 2.0 scopes for use with Google Play services. See the specific client methods for details on which scopes are required.
|
||||
*/
|
||||
public class Scopes {
|
||||
/**
|
||||
* OAuth 2.0 scope for viewing a user's basic profile information.
|
||||
*/
|
||||
public static final String PROFILE = "profile";
|
||||
@Hide
|
||||
public static final String OPENID = "openid";
|
||||
/**
|
||||
* OAuth 2.0 scope for accessing user's Google account email address.
|
||||
*/
|
||||
public static final String EMAIL = "email";
|
||||
/**
|
||||
* OAuth 2.0 scope for accessing the user's name, basic profile info and Google+ profile info.
|
||||
* <p>
|
||||
* When using this scope, your app will have access to:
|
||||
* <ul>
|
||||
* <li>the user's full name, profile picture, Google+ profile ID, age range, and language</li>
|
||||
* <li>any other publicly available information on the user's Google+ profile</li>
|
||||
* </ul>
|
||||
*
|
||||
* @deprecated We recommend switching to {@link #PROFILE} scope to get the one-tap sign-in experience. Your app will get much higher sign-in completion
|
||||
* rate by switching to profile scopes because of the streamlined user experience. And your existing users with PLUS_LOGIN grant will not be asked to
|
||||
* sign-in again.
|
||||
* If you really need user's age range and locale information (which is the only additional information you can get from PLUS_LOGIN as of
|
||||
* September 2016), use below scopes in addition to PROFILE:<ul>
|
||||
* <li>www.googleapis.com/auth/profile.agerange.read</li>
|
||||
* <li>www.googleapis.com/auth/profile.language.read</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String PLUS_LOGIN = "https://www.googleapis.com/auth/plus.login";
|
||||
/**
|
||||
* This scope was previously named PLUS_PROFILE.
|
||||
* <p>
|
||||
* When using this scope, it does the following:
|
||||
* <ul>
|
||||
* <li>It lets you know who the currently authenticated user is by letting you replace a Google+ user ID with "me", which represents the authenticated
|
||||
* user, in any call to the Google+ API.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static final String PLUS_ME = "https://www.googleapis.com/auth/plus.me";
|
||||
/**
|
||||
* Scope for accessing data from Google Play Games.
|
||||
*/
|
||||
public static final String GAMES = "https://www.googleapis.com/auth/games";
|
||||
@Hide
|
||||
public static final String GAMES_LITE = "https://www.googleapis.com/auth/games_lite";
|
||||
@Hide
|
||||
public static final String GAMES_FIRSTPARTY = "https://www.googleapis.com/auth/games.firstparty";
|
||||
/**
|
||||
* Scope for using the CloudSave service.
|
||||
*/
|
||||
public static final String CLOUD_SAVE = "https://www.googleapis.com/auth/datastoremobile";
|
||||
/**
|
||||
* Scope for using the App State service.
|
||||
*/
|
||||
public static final String APP_STATE = "https://www.googleapis.com/auth/appstate";
|
||||
/**
|
||||
* Scope for access user-authorized files from Google Drive.
|
||||
*/
|
||||
public static final String DRIVE_FILE = "https://www.googleapis.com/auth/drive.file";
|
||||
/**
|
||||
* Scope for accessing appfolder files from Google Drive.
|
||||
*/
|
||||
public static final String DRIVE_APPFOLDER = "https://www.googleapis.com/auth/drive.appdata";
|
||||
@Hide
|
||||
public static final String FITNESS_ACTIVITY_READ = "https://www.googleapis.com/auth/fitness.activity.read";
|
||||
@Hide
|
||||
public static final String FITNESS_ACTIVITY_READ_WRITE = "https://www.googleapis.com/auth/fitness.activity.write";
|
||||
@Hide
|
||||
public static final String FITNESS_LOCATION_READ = "https://www.googleapis.com/auth/fitness.location.read";
|
||||
@Hide
|
||||
public static final String FITNESS_LOCATION_READ_WRITE = "https://www.googleapis.com/auth/fitness.location.write";
|
||||
@Hide
|
||||
public static final String FITNESS_BODY_READ = "https://www.googleapis.com/auth/fitness.body.read";
|
||||
@Hide
|
||||
public static final String FITNESS_BODY_READ_WRITE = "https://www.googleapis.com/auth/fitness.body.write";
|
||||
@Hide
|
||||
public static final String USERINFO_EMAIL = "https://www.googleapis.com/auth/userinfo.email";
|
||||
@Hide
|
||||
public static final String USERINFO_PROFILE = "https://www.googleapis.com/auth/userinfo.profile";
|
||||
@Hide
|
||||
public static final String USER_BIRTHDAY_READ = "https://www.googleapis.com/auth/user.birthday.read";
|
||||
@Hide
|
||||
public static final String GMAIL_READONLY = "https://www.googleapis.com/auth/gmail.readonly";
|
||||
/**
|
||||
* Scope for cryptauthenrollment.googleapis.com (required for certain Google Workspace accounts)
|
||||
*/
|
||||
@Hide
|
||||
public static final String CRYPTAUTH = "https://www.googleapis.com/auth/cryptauth";
|
||||
}
|
||||
|
|
@ -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.common;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* UserRecoverableExceptions signal errors that can be recovered with user action, such as a user login.
|
||||
*/
|
||||
public class UserRecoverableException extends Exception {
|
||||
private final Intent intent;
|
||||
|
||||
public UserRecoverableException(String message, Intent intent) {
|
||||
super(message);
|
||||
this.intent = intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for an {@link Intent} that when supplied to {@link Activity#startActivityForResult(Intent, int)}, will allow user intervention.
|
||||
* @return Intent representing the ameliorating user action.
|
||||
*/
|
||||
public Intent getIntent() {
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020, 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.common.api;
|
||||
|
||||
import org.microg.gms.common.PublicApi;
|
||||
|
||||
/**
|
||||
* Exception to be returned by a Task when a call to Google Play services has failed.
|
||||
*/
|
||||
@PublicApi
|
||||
public class ApiException extends Exception {
|
||||
/**
|
||||
* @deprecated use {@link #getStatus()} instead
|
||||
*/
|
||||
@PublicApi
|
||||
protected final Status mStatus;
|
||||
|
||||
/**
|
||||
* Create an ApiException from a {@link com.google.android.gms.common.api.Status}.
|
||||
* @param status the Status instance containing a message and code.
|
||||
*/
|
||||
@PublicApi
|
||||
public ApiException(Status status) {
|
||||
mStatus = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status of the operation.
|
||||
*/
|
||||
@PublicApi
|
||||
public Status getStatus() {
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the status of the operation.
|
||||
* @return Status code resulting from the operation.
|
||||
* The value is one of the constants in {@link com.google.android.gms.common.api.CommonStatusCodes} or specific to the API in use.
|
||||
*/
|
||||
@PublicApi
|
||||
public int getStatusCode() {
|
||||
return mStatus.getStatusCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getMessage()} for a summary of the cause.
|
||||
*/
|
||||
@PublicApi
|
||||
public String getStatusMessage() {
|
||||
return getMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return mStatus.getStatusMessage();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2025 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.api;
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
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 ApiMetadata extends AbstractSafeParcelable {
|
||||
|
||||
public static final ApiMetadata DEFAULT = new ApiMetadata(null);
|
||||
public static final ApiMetadata SKIP = new ApiMetadata(true);
|
||||
|
||||
@Field(1)
|
||||
public final ComplianceOptions complianceOptions;
|
||||
|
||||
public final boolean skip;
|
||||
|
||||
@Constructor
|
||||
public ApiMetadata(@Param(1) ComplianceOptions complianceOptions) {
|
||||
this.complianceOptions = complianceOptions;
|
||||
this.skip = false;
|
||||
}
|
||||
|
||||
private ApiMetadata(boolean skip) {
|
||||
this.complianceOptions = null;
|
||||
this.skip = skip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
CREATOR.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
public static final SafeParcelableCreatorAndWriter<ApiMetadata> CREATOR = new ApiMetadataCreator();
|
||||
private static final SafeParcelableCreatorAndWriter<ApiMetadata> ORIGINAL_CREATOR = findCreator(ApiMetadata.class);
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringHelper.name("ApiMetadata").field("complianceOptions", complianceOptions).end();
|
||||
}
|
||||
|
||||
private static class ApiMetadataCreator implements SafeParcelableCreatorAndWriter<ApiMetadata> {
|
||||
private static final int METADATA_PRESENT_MAGIC = -204102970;
|
||||
|
||||
@Override
|
||||
public ApiMetadata createFromParcel(Parcel parcel) {
|
||||
int dataPosition = parcel.dataPosition();
|
||||
if (parcel.readInt() != METADATA_PRESENT_MAGIC) {
|
||||
parcel.setDataPosition(dataPosition - 4);
|
||||
return ApiMetadata.DEFAULT;
|
||||
}
|
||||
return ORIGINAL_CREATOR.createFromParcel(parcel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiMetadata[] newArray(int size) {
|
||||
return new ApiMetadata[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(ApiMetadata object, Parcel parcel, int flags) {
|
||||
if (object.skip) {
|
||||
parcel.setDataPosition(parcel.dataPosition() - 4);
|
||||
parcel.setDataSize(parcel.dataPosition() - 4);
|
||||
return;
|
||||
}
|
||||
parcel.writeInt(METADATA_PRESENT_MAGIC);
|
||||
ORIGINAL_CREATOR.writeToParcel(object, parcel, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.api;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.microg.gms.common.PublicApi;
|
||||
|
||||
@SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"})
|
||||
@PublicApi
|
||||
public class CommonStatusCodes {
|
||||
public static final int SUCCESS_CACHE = -1;
|
||||
public static final int SUCCESS = 0;
|
||||
@Deprecated
|
||||
public static final int SERVICE_MISSING = 1;
|
||||
@Deprecated
|
||||
public static final int SERVICE_VERSION_UPDATE_REQUIRED = 2;
|
||||
@Deprecated
|
||||
public static final int SERVICE_DISABLED = 3;
|
||||
public static final int SIGN_IN_REQUIRED = 4;
|
||||
public static final int INVALID_ACCOUNT = 5;
|
||||
public static final int RESOLUTION_REQUIRED = 6;
|
||||
public static final int NETWORK_ERROR = 7;
|
||||
public static final int INTERNAL_ERROR = 8;
|
||||
public static final int SERVICE_INVALID = 9;
|
||||
public static final int DEVELOPER_ERROR = 10;
|
||||
public static final int LICENSE_CHECK_FAILED = 11;
|
||||
public static final int ERROR = 13;
|
||||
public static final int INTERRUPTED = 14;
|
||||
public static final int TIMEOUT = 15;
|
||||
public static final int CANCELED = 16;
|
||||
public static final int API_NOT_CONNECTED = 17;
|
||||
public static final int DEAD_CLIENT = 18;
|
||||
|
||||
@NonNull
|
||||
public static String getStatusCodeString(int statusCode) {
|
||||
switch (statusCode) {
|
||||
case SUCCESS_CACHE:
|
||||
return "SUCCESS_CACHE";
|
||||
case SUCCESS:
|
||||
return "SUCCESS";
|
||||
case SERVICE_VERSION_UPDATE_REQUIRED:
|
||||
return "SERVICE_VERSION_UPDATE_REQUIRED";
|
||||
case SERVICE_DISABLED:
|
||||
return "SERVICE_DISABLED";
|
||||
case SIGN_IN_REQUIRED:
|
||||
return "SIGN_IN_REQUIRED";
|
||||
case INVALID_ACCOUNT:
|
||||
return "INVALID_ACCOUNT";
|
||||
case RESOLUTION_REQUIRED:
|
||||
return "RESOLUTION_REQUIRED";
|
||||
case NETWORK_ERROR:
|
||||
return "NETWORK_ERROR";
|
||||
case INTERNAL_ERROR:
|
||||
return "INTERNAL_ERROR";
|
||||
case SERVICE_INVALID:
|
||||
return "SERVICE_INVALID";
|
||||
case DEVELOPER_ERROR:
|
||||
return "DEVELOPER_ERROR";
|
||||
case LICENSE_CHECK_FAILED:
|
||||
return "LICENSE_CHECK_FAILED";
|
||||
case ERROR:
|
||||
return "ERROR";
|
||||
case INTERRUPTED:
|
||||
return "INTERRUPTED";
|
||||
case TIMEOUT:
|
||||
return "TIMEOUT";
|
||||
case CANCELED:
|
||||
return "CANCELED";
|
||||
case API_NOT_CONNECTED:
|
||||
return "API_NOT_CONNECTED";
|
||||
case DEAD_CLIENT:
|
||||
return "DEAD_CLIENT";
|
||||
default:
|
||||
return "unknown status code: " + statusCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2025 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.api;
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
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.utils.ToStringHelper;
|
||||
|
||||
@SafeParcelable.Class
|
||||
public class ComplianceOptions extends AbstractSafeParcelable {
|
||||
@Field(1)
|
||||
public int callerProductId;
|
||||
@Field(2)
|
||||
public int dataOwnerProductId;
|
||||
@Field(3)
|
||||
public int processingReason;
|
||||
@Field(4)
|
||||
public boolean isUserData;
|
||||
|
||||
public ComplianceOptions() {
|
||||
}
|
||||
|
||||
@Constructor
|
||||
public ComplianceOptions(@Param(1) int callerProductId, @Param(2) int dataOwnerProductId, @Param(3) int processingReason, @Param(4) boolean isUserData) {
|
||||
this.callerProductId = callerProductId;
|
||||
this.dataOwnerProductId = dataOwnerProductId;
|
||||
this.processingReason = processingReason;
|
||||
this.isUserData = isUserData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
CREATOR.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
public static final SafeParcelableCreatorAndWriter<ComplianceOptions> CREATOR = findCreator(ComplianceOptions.class);
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringHelper.name("ComplianceOptions").field("callerProductId", callerProductId).field("dataOwnerProductId", dataOwnerProductId).field("processingReason", processingReason).field("isUserData", isUserData).end();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.api;
|
||||
|
||||
/**
|
||||
* Represents a resource, or a holder of resources, which may be released once they are no longer needed.
|
||||
*/
|
||||
public interface Releasable {
|
||||
void release();
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020, 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.common.api;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
|
||||
import org.microg.gms.common.PublicApi;
|
||||
|
||||
/**
|
||||
* Exception to be returned by a Task when a call to Google Play services has failed with a
|
||||
* possible resolution.
|
||||
*/
|
||||
@PublicApi
|
||||
public class ResolvableApiException extends ApiException {
|
||||
@PublicApi
|
||||
public ResolvableApiException(Status status) {
|
||||
super(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* A pending intent to resolve the failure. This intent can be started with
|
||||
* {@link android.app.Activity#startIntentSenderForResult(IntentSender, int, Intent, int, int, int)}
|
||||
* to present UI to solve the issue.
|
||||
* @return The pending intent to resolve the failure.
|
||||
*/
|
||||
@PublicApi
|
||||
public PendingIntent getResolution() {
|
||||
return mStatus.getResolution();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves an error by starting any intents requiring user interaction.
|
||||
* See {@link com.google.android.gms.common.api.CommonStatusCodes#SIGN_IN_REQUIRED}, and
|
||||
* {@link com.google.android.gms.common.api.CommonStatusCodes#RESOLUTION_REQUIRED}.
|
||||
* @param activity An Activity context to use to resolve the issue. The activity's
|
||||
* onActivityResult method will be invoked after the user is done.
|
||||
* If the resultCode is {@link android.app.Activity#RESULT_OK},
|
||||
* the application should try to connect again.
|
||||
* @param requestCode The request code to pass to onActivityResult.
|
||||
*/
|
||||
@PublicApi
|
||||
public void startResolutionForResult(Activity activity, int requestCode) throws IntentSender.SendIntentException {
|
||||
mStatus.startResolutionForResult(activity, requestCode);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 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.common.api;
|
||||
|
||||
import org.microg.gms.common.PublicApi;
|
||||
|
||||
/**
|
||||
* Represents the successful result of invoking an API method in Google Play services using a subclass of GoogleApi.
|
||||
* Wraps a instance of a {@link Result}.
|
||||
*/
|
||||
@PublicApi
|
||||
public class Response<T extends Result> {
|
||||
private T result;
|
||||
|
||||
public Response() {
|
||||
}
|
||||
|
||||
protected Response(T result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public T getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(T result) {
|
||||
this.result = result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.api;
|
||||
|
||||
import org.microg.gms.common.PublicApi;
|
||||
|
||||
/**
|
||||
* Represents the final result of invoking an API method in Google Play Services.
|
||||
*/
|
||||
@PublicApi
|
||||
public interface Result {
|
||||
public Status getStatus();
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.api;
|
||||
|
||||
/**
|
||||
* An interface for receiving a {@link Result} from a {@link PendingResult} as an asynchronous
|
||||
* callback.
|
||||
*/
|
||||
public interface ResultCallback<R extends Result> {
|
||||
/**
|
||||
* Called when the {@link Result} is ready. It is the responsibility of each callback to
|
||||
* release any resources associated with the result. Some result types may implement
|
||||
* {@link Releasable}, in which case {@link Releasable#release()} should be used to free the
|
||||
* associated resources.
|
||||
*
|
||||
* @param result The result from the API call. May not be null.
|
||||
*/
|
||||
public void onResult(R result);
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 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.common.api;
|
||||
|
||||
import android.os.Handler;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Callbacks for receiving a {@link Result} from a as an asynchronous callback. Contains separate callbacks for success and failure.
|
||||
* These methods are called on the main thread, unless overridden by {@link GoogleApiClient.Builder#setHandler(Handler)}.
|
||||
*/
|
||||
public abstract class ResultCallbacks<R extends Result> implements ResultCallback<R> {
|
||||
/**
|
||||
* Called when the {@link Result} is ready and a failure occurred.
|
||||
*
|
||||
* @param result Status resulting from the API call. Guaranteed to be non-null and unsuccessful.
|
||||
*/
|
||||
public abstract void onFailure(@NonNull Status result);
|
||||
|
||||
/**
|
||||
* Called when the {@link Result} is ready and was successful.
|
||||
* <p>
|
||||
* It is the responsibility of the callback to release any resources associated with the result if {@link #onSuccess(Result)} is called. Some result types may
|
||||
* implement {@link Releasable}, in which case {@link Releasable#release()} should be used to free the associated resources. If a failure occurs the result will be
|
||||
* released automatically.
|
||||
*
|
||||
* @param result The result from the API call. Never null.
|
||||
*/
|
||||
public abstract void onSuccess(@NonNull R result);
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.api;
|
||||
|
||||
import android.os.Parcel;
|
||||
import androidx.annotation.NonNull;
|
||||
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.PublicApi;
|
||||
|
||||
/**
|
||||
* Describes an OAuth 2.0 scope to request. This has security implications for the user, and
|
||||
* requesting additional scopes will result in authorization dialogs.
|
||||
*/
|
||||
@PublicApi
|
||||
@SafeParcelable.Class
|
||||
public class Scope extends AbstractSafeParcelable {
|
||||
@Field(1)
|
||||
int versionCode = 1;
|
||||
@Field(value = 2, getterName = "getScopeUri")
|
||||
private final String scopeUri;
|
||||
|
||||
private Scope() {
|
||||
scopeUri = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new scope with the given URI.
|
||||
*/
|
||||
@Constructor
|
||||
public Scope(@Param(2) String scopeUri) {
|
||||
this.scopeUri = scopeUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return this == o || o instanceof Scope && scopeUri.equals(((Scope) o).scopeUri);
|
||||
}
|
||||
|
||||
public String getScopeUri() {
|
||||
return scopeUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return scopeUri.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return scopeUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
CREATOR.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
public static final SafeParcelableCreatorAndWriter<Scope> CREATOR = findCreator(Scope.class);
|
||||
}
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.api;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.IntentSender.SendIntentException;
|
||||
import android.os.Parcel;
|
||||
import androidx.annotation.NonNull;
|
||||
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.PublicApi;
|
||||
import org.microg.gms.utils.ToStringHelper;
|
||||
|
||||
/**
|
||||
* Represents the results of work.
|
||||
*/
|
||||
@PublicApi
|
||||
@SafeParcelable.Class
|
||||
public final class Status extends AbstractSafeParcelable implements Result {
|
||||
@PublicApi(exclude = true)
|
||||
public static final Status INTERNAL_ERROR = new Status(CommonStatusCodes.INTERNAL_ERROR, "Internal error");
|
||||
@PublicApi(exclude = true)
|
||||
public static final Status CANCELED = new Status(CommonStatusCodes.CANCELED, "Cancelled");
|
||||
@PublicApi(exclude = true)
|
||||
public static final Status SUCCESS_CACHE = new Status(CommonStatusCodes.SUCCESS_CACHE, "Success");
|
||||
@PublicApi(exclude = true)
|
||||
public static final Status SUCCESS = new Status(CommonStatusCodes.SUCCESS, "Success");
|
||||
|
||||
@Field(1000)
|
||||
int versionCode = 1;
|
||||
|
||||
@Field(value = 1, getterName = "getStatusCode")
|
||||
private final int statusCode;
|
||||
|
||||
@Field(value = 2, getterName = "getStatusMessage")
|
||||
private final String statusMessage;
|
||||
|
||||
@Field(value = 3, getterName = "getResolution")
|
||||
private final PendingIntent resolution;
|
||||
|
||||
private Status() {
|
||||
statusCode = 0;
|
||||
statusMessage = null;
|
||||
resolution = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a representation of the status resulting from a GoogleApiClient operation.
|
||||
*
|
||||
* @param statusCode The status code.
|
||||
*/
|
||||
public Status(int statusCode) {
|
||||
this(statusCode, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a representation of the status resulting from a GoogleApiClient operation.
|
||||
*
|
||||
* @param statusCode The status code.
|
||||
* @param statusMessage The message associated with this status, or null.
|
||||
*/
|
||||
public Status(int statusCode, String statusMessage) {
|
||||
this(statusCode, statusMessage, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a representation of the status resulting from a GoogleApiClient operation.
|
||||
*
|
||||
* @param statusCode The status code.
|
||||
* @param statusMessage The message associated with this status, or null.
|
||||
* @param resolution A pending intent that will resolve the issue when started, or null.
|
||||
*/
|
||||
@Constructor
|
||||
public Status(@Param(1) int statusCode, @Param(2) String statusMessage, @Param(3) PendingIntent resolution) {
|
||||
this.statusCode = statusCode;
|
||||
this.statusMessage = statusMessage;
|
||||
this.resolution = resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* A pending intent to resolve the failure. This intent can be started with
|
||||
* {@link Activity#startIntentSenderForResult(IntentSender, int, Intent, int, int, int)} to
|
||||
* present UI to solve the issue.
|
||||
*
|
||||
* @return The pending intent to resolve the failure.
|
||||
*/
|
||||
public PendingIntent getResolution() {
|
||||
return resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status of this result. Use {@link #isSuccess()} to determine whether the call
|
||||
* was successful, and {@link #getStatusCode()} to determine what the error cause was.
|
||||
* <p>
|
||||
* Certain errors are due to failures that can be resolved by launching a particular intent.
|
||||
* The resolution intent is available via {@link #getResolution()}.
|
||||
*/
|
||||
@Override
|
||||
public Status getStatus() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the status of the operation.
|
||||
*
|
||||
* @return Status code resulting from the operation. The value is one of the constants in
|
||||
* {@link CommonStatusCodes} or specific to the APIs added to the GoogleApiClient.
|
||||
*/
|
||||
public int getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
public String getStatusMessage() {
|
||||
return statusMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if calling {@link #startResolutionForResult(Activity, int)} will start any
|
||||
* intents requiring user interaction.
|
||||
*
|
||||
* @return true if there is a resolution that can be started.
|
||||
*/
|
||||
public boolean hasResolution() {
|
||||
return resolution != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the operation was canceled.
|
||||
*/
|
||||
public boolean isCanceled() {
|
||||
return statusCode == CommonStatusCodes.CANCELED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the operation was interrupted.
|
||||
*/
|
||||
public boolean isInterrupted() {
|
||||
return statusCode == CommonStatusCodes.INTERRUPTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the operation was successful.
|
||||
*
|
||||
* @return true if the operation was successful, false if there was an error.
|
||||
*/
|
||||
public boolean isSuccess() {
|
||||
return statusCode <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves an error by starting any intents requiring user interaction. See
|
||||
* {@link CommonStatusCodes#SIGN_IN_REQUIRED}, and {@link CommonStatusCodes#RESOLUTION_REQUIRED}.
|
||||
*
|
||||
* @param activity An Activity context to use to resolve the issue. The activity's
|
||||
* onActivityResult method will be invoked after the user is done. If the
|
||||
* resultCode is {@link Activity#RESULT_OK}, the application should try to
|
||||
* connect again.
|
||||
* @param requestCode The request code to pass to onActivityResult.
|
||||
* @throws SendIntentException If the resolution intent has been canceled or is no longer able
|
||||
* to execute the request.
|
||||
*/
|
||||
public void startResolutionForResult(Activity activity, int requestCode) throws SendIntentException {
|
||||
if (hasResolution()) {
|
||||
activity.startIntentSenderForResult(resolution.getIntentSender(), requestCode, null, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringHelper.name("Status").field("code", statusCode).field("message", statusMessage).field("resolution", resolution).end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
CREATOR.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
public static final SafeParcelableCreatorAndWriter<Status> CREATOR = findCreator(Status.class);
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.api.internal;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import com.google.android.gms.common.api.Status;
|
||||
import org.microg.gms.common.Hide;
|
||||
|
||||
@Hide
|
||||
public interface StatusExceptionMapper {
|
||||
@NonNull
|
||||
Exception getException(@NonNull Status status);
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.internal;
|
||||
|
||||
import android.os.IInterface;
|
||||
import androidx.annotation.NonNull;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import org.microg.gms.common.Hide;
|
||||
|
||||
@Hide
|
||||
public abstract class BaseGmsClient<T extends IInterface> {
|
||||
public interface ConnectionProgressReportCallbacks {
|
||||
void onReportServiceBinding(@NonNull ConnectionResult connectionResult);
|
||||
}
|
||||
|
||||
public interface SignOutCallbacks {
|
||||
void onSignOutComplete();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.internal;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class BinderWrapper implements Parcelable {
|
||||
public IBinder binder;
|
||||
|
||||
public BinderWrapper(IBinder binder) {
|
||||
this.binder = binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeStrongBinder(binder);
|
||||
}
|
||||
|
||||
public static final Creator<BinderWrapper> CREATOR = new Creator<BinderWrapper>() {
|
||||
@Override
|
||||
public BinderWrapper createFromParcel(Parcel source) {
|
||||
return new BinderWrapper(source.readStrongBinder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinderWrapper[] newArray(int size) {
|
||||
return new BinderWrapper[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (C) 2019 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.internal;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.gms.dynamic.IObjectWrapper;
|
||||
import com.google.android.gms.dynamic.ObjectWrapper;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class CertData extends ICertData.Stub {
|
||||
private final byte[] bytes;
|
||||
private final int hashCode;
|
||||
|
||||
public CertData(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
if (bytes.length < 25) throw new RuntimeException("CertData to small");
|
||||
hashCode = Arrays.hashCode(Arrays.copyOfRange(bytes, 0, 25));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof ICertData)) return false;
|
||||
ICertData cert = (ICertData) obj;
|
||||
try {
|
||||
if (cert.remoteHashCode() != hashCode()) return false;
|
||||
return Arrays.equals(ObjectWrapper.unwrapTyped(cert.getWrappedBytes(), byte[].class), getBytes());
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IObjectWrapper getWrappedBytes() throws RemoteException {
|
||||
return ObjectWrapper.wrap(getBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int remoteHashCode() throws RemoteException {
|
||||
return hashCode();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CertData unwrap(IBinder certDataBinder) {
|
||||
if (certDataBinder instanceof CertData) {
|
||||
return (CertData) certDataBinder;
|
||||
} else if (certDataBinder instanceof IObjectWrapper) {
|
||||
return unwrap((IObjectWrapper) certDataBinder);
|
||||
} else if (certDataBinder instanceof ICertData) {
|
||||
return unwrap((ICertData) certDataBinder);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CertData unwrap(IObjectWrapper certDataWrapper) {
|
||||
CertData certData = ObjectWrapper.unwrapTyped(certDataWrapper, CertData.class);
|
||||
if (certData != null) return certData;
|
||||
byte[] bytes = ObjectWrapper.unwrapTyped(certDataWrapper, byte[].class);
|
||||
if (bytes != null) return new CertData(bytes);
|
||||
ICertData iCertData = ObjectWrapper.unwrapTyped(certDataWrapper, ICertData.class);
|
||||
if (iCertData != null) return unwrap(iCertData);
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CertData unwrap(ICertData iCertData) {
|
||||
if (iCertData == null) return null;
|
||||
if (iCertData instanceof CertData) return (CertData) iCertData;
|
||||
try {
|
||||
byte[] bytes = ObjectWrapper.unwrapTyped(iCertData.getWrappedBytes(), byte[].class);
|
||||
if (bytes != null) {
|
||||
return new CertData(bytes);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// Ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.internal;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import androidx.annotation.NonNull;
|
||||
import com.google.android.gms.common.Feature;
|
||||
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;
|
||||
|
||||
@SafeParcelable.Class
|
||||
public class ConnectionInfo extends AbstractSafeParcelable {
|
||||
@Field(1)
|
||||
public Bundle params;
|
||||
@Field(2)
|
||||
public Feature[] features;
|
||||
@Field(3)
|
||||
public int unknown3;
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
CREATOR.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
public static final SafeParcelableCreatorAndWriter<ConnectionInfo> CREATOR = findCreator(ConnectionInfo.class);
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.internal;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
import androidx.annotation.NonNull;
|
||||
import com.google.android.gms.common.Feature;
|
||||
import com.google.android.gms.common.api.Scope;
|
||||
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.Constants;
|
||||
import org.microg.gms.common.GmsService;
|
||||
import org.microg.gms.utils.ToStringHelper;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@SafeParcelable.Class
|
||||
public class GetServiceRequest extends AbstractSafeParcelable {
|
||||
@Field(1)
|
||||
int versionCode = 6;
|
||||
@Field(2)
|
||||
public final int serviceId;
|
||||
@Field(3)
|
||||
public int gmsVersion;
|
||||
@Field(4)
|
||||
public String packageName;
|
||||
@Field(5)
|
||||
public IBinder accountAccessor;
|
||||
@Field(6)
|
||||
public Scope[] scopes;
|
||||
@Field(7)
|
||||
public Bundle extras;
|
||||
@Field(8)
|
||||
public Account account;
|
||||
@Field(9)
|
||||
@Deprecated
|
||||
long field9;
|
||||
@Field(10)
|
||||
public Feature[] defaultFeatures;
|
||||
@Field(11)
|
||||
public Feature[] apiFeatures;
|
||||
@Field(12)
|
||||
public boolean supportsConnectionInfo;
|
||||
@Field(13)
|
||||
int field13;
|
||||
@Field(14)
|
||||
boolean field14;
|
||||
@Field(15)
|
||||
public String attributionTag;
|
||||
|
||||
private GetServiceRequest() {
|
||||
serviceId = -1;
|
||||
gmsVersion = Constants.GMS_VERSION_CODE;
|
||||
}
|
||||
|
||||
@Constructor
|
||||
public GetServiceRequest(@Param(2) int serviceId) {
|
||||
this.serviceId = serviceId;
|
||||
this.gmsVersion = Constants.GMS_VERSION_CODE;
|
||||
this.supportsConnectionInfo = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringHelper.name("GetServiceRequest")
|
||||
.value(GmsService.nameFromServiceId(serviceId))
|
||||
.field("packageName", packageName)
|
||||
.field("gmsVersion", gmsVersion)
|
||||
.field("scopes", scopes)
|
||||
.field("extras", extras)
|
||||
.field("account", account)
|
||||
.field("defaultFeatures", defaultFeatures)
|
||||
.field("apiFeatures", apiFeatures)
|
||||
.field("supportsConnectionInfo", supportsConnectionInfo)
|
||||
.field("attributionTag", attributionTag)
|
||||
.end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
CREATOR.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
public static SafeParcelableCreatorAndWriter<GetServiceRequest> CREATOR = findCreator(GetServiceRequest.class);
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.internal;
|
||||
|
||||
import android.os.Parcel;
|
||||
import androidx.annotation.NonNull;
|
||||
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;
|
||||
|
||||
@SafeParcelable.Class
|
||||
public class ValidateAccountRequest extends AbstractSafeParcelable {
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
CREATOR.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
public static SafeParcelableCreatorAndWriter<ValidateAccountRequest> CREATOR = findCreator(ValidateAccountRequest.class);
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.internal.safeparcel;
|
||||
|
||||
public abstract class AbstractSafeParcelable implements SafeParcelable {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends AbstractSafeParcelable> SafeParcelableCreatorAndWriter<T> findCreator(java.lang.Class<T> tClass) {
|
||||
java.lang.Class<?> upmostClass = tClass;
|
||||
while (upmostClass.getEnclosingClass() != null) upmostClass = upmostClass.getEnclosingClass();
|
||||
String upmostClassName = upmostClass.getName();
|
||||
int idx = upmostClassName.lastIndexOf('.');
|
||||
String packagePrefix = idx > 0 ? upmostClassName.substring(0, idx + 1) : "";
|
||||
String creatorClassName = packagePrefix + tClass.getSimpleName() + "$000Creator";
|
||||
try {
|
||||
return (SafeParcelableCreatorAndWriter<T>) java.lang.Class.forName(creatorClassName).newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("No Creator found for " + tClass.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.internal.safeparcel;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
@SuppressWarnings("MagicNumber")
|
||||
public final class SafeParcelReader {
|
||||
|
||||
private SafeParcelReader() {
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static int halfOf(int i) {
|
||||
return i & 0xFFFF;
|
||||
}
|
||||
|
||||
public static int getFieldId(int header) {
|
||||
return header & 0xFFFF;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static int readSingleInt(Parcel parcel) {
|
||||
return parcel.readInt();
|
||||
}
|
||||
|
||||
public static int readHeader(Parcel parcel) {
|
||||
return parcel.readInt();
|
||||
}
|
||||
|
||||
private static int readSize(Parcel parcel, int header) {
|
||||
if ((header & 0xFFFF0000) != 0xFFFF0000)
|
||||
return header >> 16 & 0xFFFF;
|
||||
return parcel.readInt();
|
||||
}
|
||||
|
||||
private static void readExpectedSize(Parcel parcel, int header, int expectedSize) {
|
||||
int i = readSize(parcel, header);
|
||||
if (i != expectedSize)
|
||||
throw new ReadException("Expected size " + expectedSize + " got " + i + " (0x" + Integer.toHexString(i) + ")", parcel);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static int readStart(Parcel parcel) {
|
||||
return readObjectHeader(parcel);
|
||||
}
|
||||
|
||||
public static int readObjectHeader(Parcel parcel) {
|
||||
int header = readHeader(parcel);
|
||||
int size = readSize(parcel, header);
|
||||
int start = parcel.dataPosition();
|
||||
if (getFieldId(header) != SafeParcelable.SAFE_PARCEL_OBJECT_MAGIC)
|
||||
throw new ReadException("Expected object header. Got 0x" + Integer.toHexString(header), parcel);
|
||||
int end = start + size;
|
||||
if ((end < start) || (end > parcel.dataSize()))
|
||||
throw new ReadException("Size read is invalid start=" + start + " end=" + end, parcel);
|
||||
return end;
|
||||
}
|
||||
|
||||
public static int readInt(Parcel parcel, int header) {
|
||||
readExpectedSize(parcel, header, 4);
|
||||
return parcel.readInt();
|
||||
}
|
||||
|
||||
public static byte readByte(Parcel parcel, int header) {
|
||||
readExpectedSize(parcel, header, 4);
|
||||
return (byte) parcel.readInt();
|
||||
}
|
||||
|
||||
public static short readShort(Parcel parcel, int header) {
|
||||
readExpectedSize(parcel, header, 4);
|
||||
return (short) parcel.readInt();
|
||||
}
|
||||
|
||||
public static boolean readBool(Parcel parcel, int header) {
|
||||
readExpectedSize(parcel, header, 4);
|
||||
return parcel.readInt() != 0;
|
||||
}
|
||||
|
||||
public static long readLong(Parcel parcel, int header) {
|
||||
readExpectedSize(parcel, header, 8);
|
||||
return parcel.readLong();
|
||||
}
|
||||
|
||||
public static float readFloat(Parcel parcel, int header) {
|
||||
readExpectedSize(parcel, header, 4);
|
||||
return parcel.readFloat();
|
||||
}
|
||||
|
||||
public static double readDouble(Parcel parcel, int header) {
|
||||
readExpectedSize(parcel, header, 8);
|
||||
return parcel.readDouble();
|
||||
}
|
||||
|
||||
public static String readString(Parcel parcel, int header) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
String string = parcel.readString();
|
||||
parcel.setDataPosition(start + size);
|
||||
return string;
|
||||
}
|
||||
|
||||
public static IBinder readBinder(Parcel parcel, int header) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
IBinder binder = parcel.readStrongBinder();
|
||||
parcel.setDataPosition(start + size);
|
||||
return binder;
|
||||
}
|
||||
|
||||
public static <T extends Parcelable> T readParcelable(Parcel parcel, int header, Parcelable.Creator<T> creator) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
T t = creator.createFromParcel(parcel);
|
||||
parcel.setDataPosition(start + size);
|
||||
return t;
|
||||
}
|
||||
|
||||
public static ArrayList readList(Parcel parcel, int header, ClassLoader classLoader) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
ArrayList list = parcel.readArrayList(classLoader);
|
||||
parcel.setDataPosition(start + size);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static HashMap readMap(Parcel parcel, int header, ClassLoader classLoader) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
HashMap map = parcel.readHashMap(classLoader);
|
||||
parcel.setDataPosition(start + size);
|
||||
return map;
|
||||
}
|
||||
|
||||
public static <T extends Parcelable> ArrayList<T> readParcelableList(Parcel parcel, int header, Parcelable.Creator<T> creator) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
ArrayList<T> list = parcel.createTypedArrayList(creator);
|
||||
parcel.setDataPosition(start + size);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static ArrayList<String> readStringList(Parcel parcel, int header) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
ArrayList<String> list = parcel.createStringArrayList();
|
||||
parcel.setDataPosition(start + size);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static ArrayList<Integer> readIntegerList(Parcel parcel, int header) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
int length = parcel.readInt();
|
||||
ArrayList<Integer> list = new ArrayList<>(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
list.add(parcel.readInt());
|
||||
}
|
||||
parcel.setDataPosition(start + size);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static ArrayList<Long> readLongList(Parcel parcel, int header) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
int length = parcel.readInt();
|
||||
ArrayList<Long> list = new ArrayList<>(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
list.add(parcel.readLong());
|
||||
}
|
||||
parcel.setDataPosition(start + size);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static ArrayList<Float> readFloatList(Parcel parcel, int header) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
int length = parcel.readInt();
|
||||
ArrayList<Float> list = new ArrayList<>(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
list.add(parcel.readFloat());
|
||||
}
|
||||
parcel.setDataPosition(start + size);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static ArrayList<Double> readDoubleList(Parcel parcel, int header) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
int length = parcel.readInt();
|
||||
ArrayList<Double> list = new ArrayList<>(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
list.add(parcel.readDouble());
|
||||
}
|
||||
parcel.setDataPosition(start + size);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static ArrayList<Boolean> readBooleanList(Parcel parcel, int header) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
int length = parcel.readInt();
|
||||
ArrayList<Boolean> list = new ArrayList<>(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
list.add(parcel.readInt() != 0);
|
||||
}
|
||||
parcel.setDataPosition(start + size);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T extends Parcelable> T[] readParcelableArray(Parcel parcel, int header, Parcelable.Creator<T> creator) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
T[] arr = parcel.createTypedArray(creator);
|
||||
parcel.setDataPosition(start + size);
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static String[] readStringArray(Parcel parcel, int header) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
String[] arr = parcel.createStringArray();
|
||||
parcel.setDataPosition(start + size);
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static byte[] readByteArray(Parcel parcel, int header) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
byte[] arr = parcel.createByteArray();
|
||||
parcel.setDataPosition(start + size);
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static byte[][] readByteArrayArray(Parcel parcel, int header) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
int length = parcel.readInt();
|
||||
byte[][] arr = new byte[length][];
|
||||
for (int i = 0; i < length; i++) {
|
||||
arr[i] = parcel.createByteArray();
|
||||
}
|
||||
parcel.setDataPosition(start + size);
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static float[] readFloatArray(Parcel parcel, int header) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
float[] arr = parcel.createFloatArray();
|
||||
parcel.setDataPosition(start + size);
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static int[] readIntArray(Parcel parcel, int header) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
int[] arr = parcel.createIntArray();
|
||||
parcel.setDataPosition(start + size);
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static Bundle readBundle(Parcel parcel, int header, ClassLoader classLoader) {
|
||||
int size = readSize(parcel, header);
|
||||
if (size == 0)
|
||||
return null;
|
||||
int start = parcel.dataPosition();
|
||||
Bundle bundle = parcel.readBundle(classLoader);
|
||||
parcel.setDataPosition(start + size);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
public static void skip(Parcel parcel, int header) {
|
||||
int size = readSize(parcel, header);
|
||||
parcel.setDataPosition(parcel.dataPosition() + size);
|
||||
}
|
||||
|
||||
public static class ReadException extends RuntimeException {
|
||||
public ReadException(String message, Parcel parcel) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.internal.safeparcel;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("MagicNumber")
|
||||
public final class SafeParcelWriter {
|
||||
|
||||
private SafeParcelWriter() {
|
||||
}
|
||||
|
||||
private static void writeHeader(Parcel parcel, int fieldId, int size) {
|
||||
if (size >= 0xFFFF) {
|
||||
parcel.writeInt(0xFFFF0000 | fieldId);
|
||||
parcel.writeInt(size);
|
||||
} else {
|
||||
parcel.writeInt(size << 16 | fieldId);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static int writeStart(Parcel parcel) {
|
||||
return writeObjectHeader(parcel);
|
||||
}
|
||||
|
||||
public static int writeObjectHeader(Parcel parcel) {
|
||||
writeHeader(parcel, SafeParcelable.SAFE_PARCEL_OBJECT_MAGIC, 0xFFFF);
|
||||
return parcel.dataPosition();
|
||||
}
|
||||
|
||||
private static int writeObjectHeader(Parcel parcel, int fieldId) {
|
||||
writeHeader(parcel, fieldId, 0xFFFF);
|
||||
return parcel.dataPosition();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void writeEnd(Parcel parcel, int start) {
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
|
||||
public static void finishObjectHeader(Parcel parcel, int start) {
|
||||
int end = parcel.dataPosition();
|
||||
int length = end - start;
|
||||
parcel.setDataPosition(start - 4);
|
||||
parcel.writeInt(length);
|
||||
parcel.setDataPosition(end);
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, Boolean val) {
|
||||
if (val == null) return;
|
||||
writeHeader(parcel, fieldId, 4);
|
||||
parcel.writeInt(val ? 1 : 0);
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, Byte val) {
|
||||
if (val == null) return;
|
||||
writeHeader(parcel, fieldId, 4);
|
||||
parcel.writeInt(val);
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, Short val) {
|
||||
if (val == null) return;
|
||||
writeHeader(parcel, fieldId, 4);
|
||||
parcel.writeInt(val);
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, Integer val) {
|
||||
if (val == null) return;
|
||||
writeHeader(parcel, fieldId, 4);
|
||||
parcel.writeInt(val);
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, Long val) {
|
||||
if (val == null) return;
|
||||
writeHeader(parcel, fieldId, 8);
|
||||
parcel.writeLong(val);
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, Float val) {
|
||||
if (val == null) return;
|
||||
writeHeader(parcel, fieldId, 4);
|
||||
parcel.writeFloat(val);
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, Double val) {
|
||||
if (val == null) return;
|
||||
writeHeader(parcel, fieldId, 8);
|
||||
parcel.writeDouble(val);
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, String val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeString(val);
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, Parcelable val, int flags, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
val.writeToParcel(parcel, flags);
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, Bundle val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeBundle(val);
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, byte[] val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeByteArray(val);
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, byte[][] val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeInt(val.length);
|
||||
for (byte[] arr : val) {
|
||||
parcel.writeByteArray(arr);
|
||||
}
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, float[] val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeFloatArray(val);
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, int[] val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeIntArray(val);
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, String[] val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeStringArray(val);
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeStringList(Parcel parcel, int fieldId, List<String> val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeStringList(val);
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeIntegerList(Parcel parcel, int fieldId, List<Integer> val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeInt(val.size());
|
||||
for (Integer i : val) {
|
||||
parcel.writeInt(i);
|
||||
}
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeLongList(Parcel parcel, int fieldId, List<Long> val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeInt(val.size());
|
||||
for (Long l : val) {
|
||||
parcel.writeLong(l);
|
||||
}
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeFloatList(Parcel parcel, int fieldId, List<Float> val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeInt(val.size());
|
||||
for (Float f : val) {
|
||||
parcel.writeFloat(f);
|
||||
}
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeDoubleList(Parcel parcel, int fieldId, List<Double> val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeInt(val.size());
|
||||
for (Double d : val) {
|
||||
parcel.writeDouble(d);
|
||||
}
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeBooleanList(Parcel parcel, int fieldId, List<Boolean> val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeInt(val.size());
|
||||
for (Boolean b : val) {
|
||||
parcel.writeInt(b ? 1 : 0);
|
||||
}
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T extends Parcelable> void writeArrayPart(Parcel parcel, T val, int flags) {
|
||||
int before = parcel.dataPosition();
|
||||
parcel.writeInt(1);
|
||||
int start = parcel.dataPosition();
|
||||
val.writeToParcel(parcel, flags);
|
||||
int end = parcel.dataPosition();
|
||||
parcel.setDataPosition(before);
|
||||
parcel.writeInt(end - start);
|
||||
parcel.setDataPosition(end);
|
||||
}
|
||||
|
||||
public static <T extends Parcelable> void write(Parcel parcel, int fieldId, T[] val, int flags, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeInt(val.length);
|
||||
for (T t : val) {
|
||||
if (t == null) {
|
||||
parcel.writeInt(0);
|
||||
} else {
|
||||
writeArrayPart(parcel, t, flags);
|
||||
}
|
||||
}
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends Parcelable> void write(Parcel parcel, int fieldId, List<T> val, int flags, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeInt(val.size());
|
||||
for (T t : val) {
|
||||
if (t == null) {
|
||||
parcel.writeInt(0);
|
||||
} else {
|
||||
writeArrayPart(parcel, t, flags);
|
||||
}
|
||||
}
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, Parcel val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.appendFrom(val, 0, val.dataSize());
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, List val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeList(val);
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, Map val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeMap(val);
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(Parcel parcel, int fieldId, IBinder val, boolean mayNull) {
|
||||
if (val == null) {
|
||||
if (mayNull) {
|
||||
writeHeader(parcel, fieldId, 0);
|
||||
}
|
||||
} else {
|
||||
int start = writeObjectHeader(parcel, fieldId);
|
||||
parcel.writeStrongBinder(val);
|
||||
finishObjectHeader(parcel, start);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.internal.safeparcel;
|
||||
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
public interface SafeParcelable extends Parcelable {
|
||||
int SAFE_PARCEL_OBJECT_MAGIC = 0x4F45;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@interface Class {
|
||||
}
|
||||
|
||||
@Target(ElementType.CONSTRUCTOR)
|
||||
@interface Constructor {
|
||||
|
||||
}
|
||||
|
||||
@Target(ElementType.PARAMETER)
|
||||
@interface Param {
|
||||
int value();
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
@interface Field {
|
||||
int value();
|
||||
|
||||
boolean mayNull() default false;
|
||||
|
||||
java.lang.Class<?> subClass() default SafeParcelable.class;
|
||||
|
||||
boolean useValueParcel() default false;
|
||||
|
||||
boolean useDirectList() default false;
|
||||
|
||||
long versionCode() default -1;
|
||||
|
||||
String defaultValue() default "";
|
||||
|
||||
String type() default "";
|
||||
|
||||
String getterName() default "";
|
||||
|
||||
String getter() default "";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.internal.safeparcel;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public interface SafeParcelableCreatorAndWriter<T extends SafeParcelable> extends Parcelable.Creator<T> {
|
||||
void writeToParcel(T object, Parcel parcel, int flags);
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.common.internal.safeparcel;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class SafeParcelableSerializer {
|
||||
public static <T extends SafeParcelable> T deserializeFromBytes(byte[] bytes, Parcelable.Creator<T> tCreator) {
|
||||
if (bytes == null) return null;
|
||||
Parcel parcel = Parcel.obtain();
|
||||
parcel.unmarshall(bytes, 0, bytes.length);
|
||||
parcel.setDataPosition(0);
|
||||
T parcelable = tCreator.createFromParcel(parcel);
|
||||
parcel.recycle();
|
||||
return parcelable;
|
||||
}
|
||||
|
||||
public static <T extends SafeParcelable> byte[] serializeToBytes(T parcelable) {
|
||||
if (parcelable == null) return null;
|
||||
Parcel parcel = Parcel.obtain();
|
||||
parcelable.writeToParcel(parcel, 0);
|
||||
byte[] bytes = parcel.marshall();
|
||||
parcel.recycle();
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: CC-BY-4.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.
|
||||
*/
|
||||
/**
|
||||
* Contains utility classes for Google Play services.
|
||||
*/
|
||||
package com.google.android.gms.common;
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.dynamic;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public interface LifecycleDelegate {
|
||||
View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup parent, @Nullable Bundle savedInstanceState);
|
||||
|
||||
void onCreate(@Nullable Bundle savedInstanceState);
|
||||
|
||||
void onDestroy();
|
||||
|
||||
void onDestroyView();
|
||||
|
||||
void onInflate(@NonNull Activity activity, @NonNull Bundle options, @Nullable Bundle onInflate);
|
||||
|
||||
void onLowMemory();
|
||||
|
||||
void onPause();
|
||||
|
||||
void onResume();
|
||||
|
||||
void onSaveInstanceState(@NonNull Bundle outState);
|
||||
|
||||
void onStart();
|
||||
|
||||
void onStop();
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.android.gms.dynamic;
|
||||
|
||||
import android.os.IBinder;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class ObjectWrapper<T> extends IObjectWrapper.Stub {
|
||||
private final T t;
|
||||
|
||||
public ObjectWrapper(T t) {
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Object unwrap(IObjectWrapper obj) {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (obj instanceof ObjectWrapper) {
|
||||
return ((ObjectWrapper) obj).t;
|
||||
}
|
||||
|
||||
IBinder binder = obj.asBinder();
|
||||
Field[] fields = binder.getClass().getDeclaredFields();
|
||||
|
||||
if (fields.length < 1) {
|
||||
throw new IllegalArgumentException("No fields were found");
|
||||
}
|
||||
|
||||
// Ignore synthetic field(s) from JaCoCo or elsewhere
|
||||
// https://www.jacoco.org/jacoco/trunk/doc/faq.html
|
||||
|
||||
@Nullable
|
||||
Field field = null;
|
||||
|
||||
for (Field currentField : fields) {
|
||||
if (currentField.isSynthetic()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (field == null) {
|
||||
field = currentField;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Too many non-synthetic fields were found");
|
||||
}
|
||||
}
|
||||
|
||||
if (field == null) {
|
||||
throw new IllegalArgumentException("No non-synthetic fields were found");
|
||||
}
|
||||
|
||||
if (!field.isAccessible()) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
return field.get(binder);
|
||||
} catch (NullPointerException localNullPointerException) {
|
||||
throw new IllegalArgumentException("Binder object is null.",
|
||||
localNullPointerException);
|
||||
} catch (IllegalArgumentException localIllegalArgumentException) {
|
||||
throw new IllegalArgumentException("remoteBinder is the wrong class.",
|
||||
localIllegalArgumentException);
|
||||
} catch (IllegalAccessException localIllegalAccessException) {
|
||||
throw new IllegalArgumentException("Could not access the field in remoteBinder.",
|
||||
localIllegalAccessException);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> T unwrapTyped(IObjectWrapper obj, Class<T> clazz) {
|
||||
try {
|
||||
return clazz.cast(unwrap(obj));
|
||||
} catch (ClassCastException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> ObjectWrapper<T> wrap(T t) {
|
||||
return new ObjectWrapper<T>(t);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.dynamic;
|
||||
|
||||
public interface OnDelegateCreatedListener<T extends LifecycleDelegate> {
|
||||
void onDelegateCreated(T delegate);
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.dynamite;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Objects;
|
||||
|
||||
public class DynamiteModule {
|
||||
private static final String TAG = "DynamiteModule";
|
||||
|
||||
public static final int NONE = 0;
|
||||
public static final int LOCAL = -1;
|
||||
public static final int REMOTE = 1;
|
||||
|
||||
@NonNull
|
||||
public static final VersionPolicy PREFER_REMOTE = (context, moduleId, versions) -> {
|
||||
VersionPolicy.SelectionResult result = new VersionPolicy.SelectionResult();
|
||||
result.remoteVersion = versions.getRemoteVersion(context, moduleId, true);
|
||||
if (result.remoteVersion != 0) {
|
||||
result.selection = REMOTE;
|
||||
} else {
|
||||
result.localVersion = versions.getLocalVersion(context, moduleId);
|
||||
if (result.localVersion != 0) {
|
||||
result.selection = LOCAL;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
@NonNull
|
||||
public static final VersionPolicy PREFER_LOCAL = (context, moduleId, versions) -> {
|
||||
VersionPolicy.SelectionResult result = new VersionPolicy.SelectionResult();
|
||||
result.localVersion = versions.getLocalVersion(context, moduleId);
|
||||
if (result.localVersion != 0) {
|
||||
result.selection = LOCAL;
|
||||
} else {
|
||||
result.remoteVersion = versions.getRemoteVersion(context, moduleId, true);
|
||||
if (result.remoteVersion != 0) {
|
||||
result.selection = REMOTE;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
public interface VersionPolicy {
|
||||
interface IVersions {
|
||||
int getLocalVersion(@NonNull Context context, @NonNull String moduleId);
|
||||
|
||||
int getRemoteVersion(@NonNull Context context, @NonNull String moduleId, boolean forceStaging) throws LoadingException;
|
||||
|
||||
IVersions Default = new IVersions() {
|
||||
@Override
|
||||
public int getLocalVersion(@NonNull Context context, @NonNull String moduleId) {
|
||||
return DynamiteModule.getLocalVersion(context, moduleId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRemoteVersion(@NonNull Context context, @NonNull String moduleId, boolean forceStaging) throws LoadingException {
|
||||
return DynamiteModule.getRemoteVersion(context, moduleId, forceStaging);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class SelectionResult {
|
||||
public int localVersion = 0;
|
||||
public int remoteVersion = 0;
|
||||
public int selection = NONE;
|
||||
}
|
||||
|
||||
SelectionResult selectModule(@NonNull Context context, @NonNull String moduleId, @NonNull IVersions versions) throws LoadingException;
|
||||
}
|
||||
|
||||
public static class LoadingException extends Exception {
|
||||
public LoadingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public LoadingException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
private Context moduleContext;
|
||||
|
||||
private DynamiteModule(Context moduleContext) {
|
||||
this.moduleContext = moduleContext;
|
||||
}
|
||||
|
||||
public Context getModuleContext() {
|
||||
return moduleContext;
|
||||
}
|
||||
|
||||
public static int getLocalVersion(@NonNull Context context, @NonNull String moduleId) {
|
||||
try {
|
||||
ClassLoader classLoader = context.getApplicationContext().getClassLoader();
|
||||
Class<?> clazz = classLoader.loadClass("com.google.android.gms.dynamite.descriptors." + moduleId + ".ModuleDescriptor");
|
||||
Field moduleIdField = clazz.getDeclaredField("MODULE_ID");
|
||||
Field moduleVersionField = clazz.getDeclaredField("MODULE_VERSION");
|
||||
if (!Objects.equals(moduleIdField.get(null), moduleId)) {
|
||||
Log.e(TAG, "Module descriptor id '" + moduleIdField.get(null) + "' didn't match expected id '" + moduleId + "'");
|
||||
return 0;
|
||||
}
|
||||
return moduleVersionField.getInt(null);
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.w(TAG, "Local module descriptor class for" + moduleId + " not found.");
|
||||
return 0;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to load module descriptor class.", e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getRemoteVersion(@NonNull Context context, @NonNull String moduleId) {
|
||||
return getRemoteVersion(context, moduleId, false);
|
||||
}
|
||||
|
||||
public static int getRemoteVersion(@NonNull Context context, @NonNull String moduleId, boolean forceStaging) {
|
||||
Log.e(TAG, "Remote modules not yet supported");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static DynamiteModule load(@NonNull Context context, @NonNull VersionPolicy policy, @NonNull String moduleId) throws LoadingException {
|
||||
Context applicationContext = context.getApplicationContext();
|
||||
if (applicationContext == null) throw new LoadingException("null application Context", null);
|
||||
try {
|
||||
VersionPolicy.SelectionResult result = policy.selectModule(context, moduleId, VersionPolicy.IVersions.Default);
|
||||
Log.i(TAG, "Considering local module " + moduleId + ":" + result.localVersion + " and remote module " + moduleId + ":" + result.remoteVersion);
|
||||
switch (result.selection) {
|
||||
case NONE:
|
||||
throw new LoadingException("No acceptable module " + moduleId + " found. Local version is " + result.localVersion + " and remote version is " + result.remoteVersion + ".");
|
||||
case LOCAL:
|
||||
Log.i(TAG, "Selected local version of " + moduleId);
|
||||
return new DynamiteModule(context);
|
||||
case REMOTE:
|
||||
throw new UnsupportedOperationException();
|
||||
default:
|
||||
throw new LoadingException("VersionPolicy returned invalid code:" + result.selection);
|
||||
}
|
||||
} catch (LoadingException loadingException) {
|
||||
throw loadingException;
|
||||
} catch (Throwable e) {
|
||||
throw new LoadingException("Failed to load remote module.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public IBinder instantiate(@NonNull String className) throws LoadingException {
|
||||
try {
|
||||
return (IBinder) this.moduleContext.getClassLoader().loadClass(className).newInstance();
|
||||
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | RuntimeException e) {
|
||||
throw new LoadingException("Failed to instantiate module class: " + className, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020, 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.security;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import java.security.Provider;
|
||||
|
||||
/**
|
||||
* A utility class for installing a dynamically updatable {@link Provider} to replace the platform default provider.
|
||||
*/
|
||||
public class ProviderInstaller {
|
||||
public static final String PROVIDER_NAME = "GmsCore_OpenSSL";
|
||||
|
||||
/**
|
||||
* Installs the dynamically updatable security provider, if it's not already installed.
|
||||
*
|
||||
* @throws GooglePlayServicesRepairableException
|
||||
* @throws GooglePlayServicesNotAvailableException
|
||||
*/
|
||||
public static void installIfNeeded(Context context) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously installs the dynamically updatable security provider, if it's not already installed. This method must be called on the UI thread.
|
||||
*
|
||||
* @param context
|
||||
* @param listener called when the installation completes
|
||||
*/
|
||||
public static void installIfNeededAsync(Context context, ProviderInstallListener listener) {
|
||||
if (listener != null) listener.onProviderInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for notification of the result of provider installation.
|
||||
*/
|
||||
public interface ProviderInstallListener {
|
||||
/**
|
||||
* Called when installing the provider fails. This method is always called on the UI thread.
|
||||
* <p>
|
||||
* Implementers may use {@code errorCode} with the standard UI elements provided by {@link GoogleApiAvailability}; or {@code recoveryIntent} to implement custom UI.
|
||||
*
|
||||
* @param errorCode error code for the failure, for use with {@link GoogleApiAvailability#showErrorDialogFragment(Activity, int, int)} or {@link GoogleApiAvailability#showErrorNotification(Context, ConnectionResult)}
|
||||
* @param recoveryIntent if non-null, an intent that can be used to install or update Google Play Services such that the provider can be installed
|
||||
*/
|
||||
void onProviderInstallFailed(int errorCode, Intent recoveryIntent);
|
||||
|
||||
/**
|
||||
* Called when installing the provider succeeds. This method is always called on the UI thread.
|
||||
*/
|
||||
void onProviderInstalled();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.google.android.gms.stats;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.legacy.content.WakefulBroadcastReceiver;
|
||||
import org.microg.gms.common.Hide;
|
||||
|
||||
/**
|
||||
* TODO: This should end up in play-services-stats eventually
|
||||
*/
|
||||
@Hide
|
||||
public abstract class GCoreWakefulBroadcastReceiver extends WakefulBroadcastReceiver {
|
||||
public static boolean completeWakefulIntent(@NonNull Context context, @Nullable Intent intent) {
|
||||
if (intent == null) return false;
|
||||
return WakefulBroadcastReceiver.completeWakefulIntent(intent);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.microg.gms.auth;
|
||||
|
||||
public class AuthConstants {
|
||||
public static final String DEFAULT_ACCOUNT = "<<default account>>";
|
||||
public static final String SCOPE_GET_ACCOUNT_ID = "^^_account_id_^^";
|
||||
public static final String PROVIDER_METHOD_GET_ACCOUNTS = "get_accounts";
|
||||
public static final String PROVIDER_METHOD_CLEAR_PASSWORD = "clear_password";
|
||||
public static final String PROVIDER_EXTRA_CLEAR_PASSWORD = "clear_password";
|
||||
public static final String PROVIDER_EXTRA_ACCOUNTS = "accounts";
|
||||
public static final String DEFAULT_ACCOUNT_TYPE = "com.google";
|
||||
public static final String WORK_ACCOUNT_TYPE = "com.google.work";
|
||||
|
||||
public static final String KEY_ACCOUNT_SERVICES = "services";
|
||||
public static final String KEY_ACCOUNT_CAPABILITIES = "capabilities";
|
||||
|
||||
public static final String GOOGLE_USER_ID = "GoogleUserId";
|
||||
public static final String GOOGLE_SIGN_IN_STATUS = "googleSignInStatus";
|
||||
public static final String GOOGLE_SIGN_IN_ACCOUNT = "googleSignInAccount";
|
||||
public static final String SIGN_IN_ACCOUNT = "signInAccount";
|
||||
public static final String ERROR_CODE = "errorCode";
|
||||
public static final String SIGN_IN_CREDENTIAL = "sign_in_credential";
|
||||
public static final String STATUS = "status";
|
||||
public static final String SCOPE_OAUTH2 = "oauth2:";
|
||||
public static final String SCOPE_EM_OP_PRO = "oauth2:email openid profile";
|
||||
public static final String GOOGLE_SIGN_IN_AUTHORIZATION_RESULT = "authorization_result";
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2019 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.microg.gms.common;
|
||||
|
||||
import com.google.android.gms.common.BuildConfig;
|
||||
|
||||
public class Constants {
|
||||
public static final int GMS_VERSION_CODE = (BuildConfig.VERSION_CODE / 1000) * 1000;
|
||||
public static final String GMS_PACKAGE_NAME = "com.google.android.gms";
|
||||
public static final String USER_MICROG_PACKAGE_NAME = "org.microg.gms";
|
||||
public static final String GSF_PACKAGE_NAME = "com.google.android.gsf";
|
||||
public static final String GMS_PACKAGE_SIGNATURE_SHA1 = "38918a453d07199354f8b19af05ec6562ced5788";
|
||||
public static final String GMS_SECONDARY_PACKAGE_SIGNATURE_SHA1 = "bd32424203e0fb25f36b57e5aa356f9bdd1da998";
|
||||
public static final String MICROG_PACKAGE_SIGNATURE_SHA1 = "10321bd893f69af97f7573aafe9de1dc0901f3a1";
|
||||
@Deprecated
|
||||
public static final int MAX_REFERENCE_VERSION = GMS_VERSION_CODE;
|
||||
public static final String VENDING_PACKAGE_NAME = "com.android.vending";
|
||||
}
|
||||
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.microg.gms.common;
|
||||
|
||||
public enum GmsService {
|
||||
UNKNOWN(-2),
|
||||
ANY(-1),
|
||||
GAMES(1, "com.google.android.gms.games.service.START", "com.google.android.gms.games.internal.connect.service.START"),
|
||||
PLUS(2, "com.google.android.gms.plus.service.START", "com.google.android.gms.plus.service.internal.START"),
|
||||
PANORAMA(3, "com.google.android.gms.panorama.service.START"),
|
||||
WALLET(4, "com.google.android.gms.wallet.service.BIND"),
|
||||
PEOPLE(5, "com.google.android.gms.people.service.START"),
|
||||
LOCATION(6),
|
||||
APPSTATE(7, "com.google.android.gms.appstate.service.START"),
|
||||
ADREQUEST(8, "com.google.android.gms.ads.service.START"),
|
||||
ACCOUNT(9, "com.google.android.gms.accounts.ACCOUNT_SERVICE"),
|
||||
CAST(10, "com.google.android.gms.cast.service.BIND_CAST_DEVICE_CONTROLLER_SERVICE"),
|
||||
DRIVE(11, "com.google.android.gms.drive.ApiService.START"),
|
||||
ADDRESS(12, "com.google.android.gms.identity.service.BIND"),
|
||||
CAR(13, "com.google.android.gms.car.service.START"),
|
||||
WEARABLE(14, "com.google.android.gms.wearable.BIND"),
|
||||
AUTH_PROXY(16, "com.google.android.gms.auth.service.START"),
|
||||
FITNESS(17, "com.google.android.gms.fitness.GoogleFitnessService.START"),
|
||||
REMINDERS(18, "com.google.android.gms.reminders.service.START"),
|
||||
LIGHTWEIGHT_INDEX(19, "com.google.android.gms.icing.LIGHTWEIGHT_INDEX_SERVICE"),
|
||||
DEVICE_CONNECTION(20, "com.google.android.gms.deviceconnection.service.START"),
|
||||
INDEX(21, "com.google.android.gms.icing.INDEX_SERVICE"),
|
||||
LOCATION_REPORTING(22, "com.google.android.gms.location.reporting.service.START", "com.google.android.location.reporting.service.START"),
|
||||
LOCATION_MANAGER(23, "com.google.android.location.internal.GoogleLocationManagerService.START"),
|
||||
PLAY_LOG(24, "com.google.android.gms.playlog.service.START"),
|
||||
DROIDGUARD(25, "com.google.android.gms.droidguard.service.START"),
|
||||
LOCKBOX(26, "com.google.android.gms.lockbox.service.START"),
|
||||
CAST_MIRRORING(27, "com.google.android.gms.cast_mirroring.service.START"),
|
||||
NETWORK_QUALITY(28, "com.google.android.gms.mdm.services.START"),
|
||||
FEEDBACK(29, "com.google.android.gms.feedback.internal.IFeedbackService"),
|
||||
SEARCH_ADMINISTRATION(30),
|
||||
PHOTO_AUTO_BACKUP(31, "com.google.android.gms.photos.autobackup.service.START"),
|
||||
SEARCH_QUERIES(32),
|
||||
SEARCH_GLOBAL(33),
|
||||
UDC(35, "com.google.android.gms.udc.service.START"),
|
||||
SEARCH_CORPORA(36),
|
||||
DEVICE_MANAGER(37, "com.google.android.gms.mdm.services.DeviceManagerApiService.START"),
|
||||
PSEUDONYMOUS_ID(38, "com.google.android.gms.pseudonymous.service.START"),
|
||||
COMMON(39, "com.google.android.gms.common.service.START"),
|
||||
CLEARCUT_LOGGER(40, "com.google.android.gms.clearcut.service.START"),
|
||||
USAGE_REPORTING(41, "com.google.android.gms.usagereporting.service.START"),
|
||||
KIDS(42, "com.google.android.gms.kids.service.START"),
|
||||
DOWNLOAD(43, "com.google.android.gms.common.download.START"),
|
||||
SIGN_IN(44, "com.google.android.gms.signin.service.START"),
|
||||
SAFETY_NET_CLIENT(45, "com.google.android.gms.safetynet.service.START"),
|
||||
GSERVICES(46, "com.google.android.gms.ads.gservice.START"),
|
||||
CONTEXT_MANAGER(47, "com.google.android.contextmanager.service.ContextManagerService.START"),
|
||||
AUDIO_MODEM(48, "com.google.android.gms.audiomodem.service.AudioModemService.START"),
|
||||
NEARBY_SHARING(49, "com.google.android.gms.nearby.sharing.service.NearbySharingService.START"),
|
||||
LIGHTWEIGHT_NETWORK_QUALITY(50, "com.google.android.gms.herrevad.services.LightweightNetworkQualityAndroidService.START"),
|
||||
PHENOTYPE(51, "com.google.android.gms.phenotype.service.START"),
|
||||
VOICE_UNLOCK(52, "com.google.android.gms.speech.service.START"),
|
||||
NEARBY_CONNECTIONS(54, "com.google.android.gms.nearby.connection.service.START"),
|
||||
FITNESS_SENSORS(55, "com.google.android.gms.fitness.SensorsApi"),
|
||||
FITNESS_RECORDING(56, "com.google.android.gms.fitness.RecordingApi"),
|
||||
FITNESS_HISTORY(57, "com.google.android.gms.fitness.HistoryApi"),
|
||||
FITNESS_SESSIONS(58, "com.google.android.gms.fitness.SessionsApi"),
|
||||
FITNESS_BLE(59, "com.google.android.gms.fitness.BleApi"),
|
||||
FITNESS_CONFIG(60, "com.google.android.gms.fitness.ConfigApi"),
|
||||
FITNESS_INTERNAL(61, "com.google.android.gms.fitness.InternalApi"),
|
||||
NEARBY_MESSAGES(62, "com.google.android.gms.nearby.messages.service.NearbyMessagesService.START"),
|
||||
HELP(63, "com.google.android.gms.googlehelp.service.GoogleHelpService.START"),
|
||||
CONFIG(64, "com.google.android.gms.config.START"),
|
||||
GEODATA(65, "com.google.android.gms.location.places.GeoDataApi"),
|
||||
SEARCH_IME(66),
|
||||
PLACE_DETECTION(67, "com.google.android.gms.location.places.PlaceDetectionApi"),
|
||||
CREDENTIALS(68, "com.google.android.gms.auth.api.credentials.service.START"),
|
||||
NEARBY_BOOTSTRAP(69, "com.google.android.gms.nearby.bootstrap.service.NearbyBootstrapService.START"),
|
||||
PLUS_INTERNAL(70),
|
||||
SOURCE_DEVICE(75, "com.google.android.gms.smartdevice.d2d.SourceDeviceService.START"),
|
||||
TARGET_DEVICE(76, "com.google.android.gms.smartdevice.d2d.TargetDeviceService.START"),
|
||||
APP_INVITE(77, "com.google.android.gms.appinvite.service.START"),
|
||||
TAP_AND_PAY(79, "com.google.android.gms.tapandpay.service.BIND"),
|
||||
CHROME_SYNC(80, "com.google.android.gms.chromesync.service.START"),
|
||||
ACCOUNTS(81, "com.google.android.gms.smartdevice.setup.accounts.AccountsService.START"),
|
||||
CAST_REMOTE_DISPLAY(83, "com.google.android.gms.cast.remote_display.service.START"),
|
||||
TRUST_AGENT(85, "com.google.android.gms.trustagent.StateApi.START"),
|
||||
AUTH_SIGN_IN(91, "com.google.android.gms.auth.api.signin.service.START"),
|
||||
MEASUREMENT(93, "com.google.android.gms.measurement.START"),
|
||||
FREIGHTER(98, "com.google.android.gms.freighter.service.START"),
|
||||
GUNS(110, "com.google.android.gms.notifications.service.START"),
|
||||
BLE(111, "com.google.android.gms.beacon.internal.IBleService.START"),
|
||||
FIREBASE_AUTH(112, "com.google.firebase.auth.api.gms.service.START"),
|
||||
APP_INDEXING(113),
|
||||
GASS(116, "com.google.android.gms.gass.START"),
|
||||
WORK_ACCOUNT(120, "com.google.android.gms.auth.account.workaccount.START"),
|
||||
INSTANT_APPS(121, "com.google.android.gms.instantapps.START"),
|
||||
CAST_FIRSTPATY(122, "com.google.android.gms.cast.firstparty.START"),
|
||||
AD_CACHE(123, "com.google.android.gms.ads.service.CACHE"),
|
||||
SMS_RETRIEVER(126, "com.google.android.gms.auth.api.phone.service.SmsRetrieverApiService.START"),
|
||||
CRYPT_AUTH(129, "com.google.android.gms.auth.cryptauth.cryptauthservice.START"),
|
||||
DYNAMIC_LINKS(131, "com.google.firebase.dynamiclinks.service.START"),
|
||||
FONTS(132, "com.google.android.gms.fonts.service.START"),
|
||||
ROMANESCO(135, "com.google.android.gms.romanesco.service.START"),
|
||||
TRAINER(139, "com.google.android.gms.learning.trainer.START"),
|
||||
FIDO2_REGULAR(148, "com.google.android.gms.fido.fido2.regular.START"),
|
||||
FIDO2_PRIVILEGED(149, "com.google.android.gms.fido.fido2.privileged.START"),
|
||||
DATA_DOWNLOAD(152, "com.google.android.mdd.service.START"),
|
||||
ACCOUNT_DATA(153, "com.google.android.gms.auth.account.data.service.START"),
|
||||
CONSTELLATION(155, "com.google.android.gms.constellation.service.START"),
|
||||
AUDIT(154, "com.google.android.gms.audit.service.START"),
|
||||
SYSTEM_UPDATE(157, "com.google.android.gms.update.START_API_SERVICE"),
|
||||
MOBSTORE(160, "com.google.android.mobstore.service.START"),
|
||||
USER_LOCATION(163, "com.google.android.gms.userlocation.service.START"),
|
||||
AD_HTTP(166, "com.google.android.gms.ads.service.HTTP"),
|
||||
LANGUAGE_PROFILE(167, "com.google.android.gms.languageprofile.service.START"),
|
||||
MDNS(168, "com.google.android.gms.mdns.service.START"),
|
||||
FOLSOM(172, "com.google.android.gms.auth.key.retrieval.service.START"),
|
||||
SEMANTIC_LOCATION(173, "com.google.android.gms.semanticlocation.service.START_ODLH"),
|
||||
FIDO2_ZEROPARTY(180, "com.google.android.gms.fido.fido2.zeroparty.START"),
|
||||
G1_RESTORE(181, "com.google.android.gms.backup.G1_RESTORE"),
|
||||
G1_BACKUP(182, "com.google.android.gms.backup.G1_BACKUP"),
|
||||
OSS_LICENSES(185, "com.google.android.gms.oss.licenses.service.START"),
|
||||
PAYSE(188, "com.google.android.gms.payse.service.BIND"),
|
||||
RCS(189, "com.google.android.gms.rcs.START"),
|
||||
CARRIER_AUTH(191, "com.google.android.gms.carrierauth.service.START"),
|
||||
SYSTEM_UPDATE_SINGLE_UESR(192, "com.google.android.gms.update.START_SINGLE_USER_API_SERVICE"),
|
||||
APP_USAGE(193, "com.google.android.gms.appusage.service.START"),
|
||||
NEARBY_SHARING_2(194, "com.google.android.gms.nearby.sharing.START_SERVICE"),
|
||||
AD_CONSENT_LOOKUP(195, "com.google.android.gms.ads.service.CONSENT_LOOKUP"),
|
||||
CREDENTIAL_MANAGER(196, "com.google.android.gms.credential.manager.service.firstparty.START"),
|
||||
PHONE_INTERNAL(197, "com.google.android.gms.auth.api.phone.service.InternalService.START"),
|
||||
PAY(198, "com.google.android.gms.pay.service.BIND", "com.google.android.gms.pay.service.THIRD_PARTY"),
|
||||
ASTERISM(199, "com.google.android.gms.asterism.service.START"),
|
||||
MODULE_RESTORE(201, "com.google.android.gms.backup.GMS_MODULE_RESTORE"),
|
||||
FACS_CACHE(202, "com.google.android.gms.facs.cache.service.START"),
|
||||
RECAPTCHA(205, "com.google.android.gms.recaptcha.service.START"),
|
||||
CONTACT_SYNC(208, "com.google.android.gms.people.contactssync.service.START"),
|
||||
IDENTITY_SIGN_IN(212, "com.google.android.gms.auth.api.identity.service.signin.START"),
|
||||
CREDENTIAL_STORE(214, "com.google.android.gms.fido.credentialstore.internal_service.START"),
|
||||
MDI_SYNC(215, "com.google.android.gms.mdisync.service.START"),
|
||||
EVENT_ATTESTATION(216, "com.google.android.gms.ads.identifier.service.EVENT_ATTESTATION"),
|
||||
SCHEDULER(218, "com.google.android.gms.scheduler.ACTION_PROXY_SCHEDULE"),
|
||||
AUTHORIZATION(219, "com.google.android.gms.auth.api.identity.service.authorization.START"),
|
||||
FACS_SYNC(220, "com.google.android.gms.facs.internal.service.START"),
|
||||
AUTH_CONFIG_SYNC(221, "com.google.android.gms.auth.config.service.START"),
|
||||
CREDENTIAL_SAVING(223, "com.google.android.gms.auth.api.identity.service.credentialsaving.START"),
|
||||
GOOGLE_AUTH(224, "com.google.android.gms.auth.account.authapi.START"),
|
||||
ENTERPRISE_LOADER(225, "com.google.android.gms.enterprise.loader.service.START"),
|
||||
THUNDERBIRD(226, "com.google.android.gms.thunderbird.service.START"),
|
||||
NEARBY_EXPOSURE(236, "com.google.android.gms.nearby.exposurenotification.START"),
|
||||
GMS_COMPLIANCE(257, "com.google.android.gms.gmscompliance.service.START"),
|
||||
BLOCK_STORE(258, "com.google.android.gms.auth.blockstore.service.START"),
|
||||
FIDO_SOURCE_DEVICE(262, "com.google.android.gms.fido.sourcedevice.service.START"),
|
||||
FAST_PAIR(265, "com.google.android.gms.nearby.fastpair.START"),
|
||||
MATCHSTICK_LIGHTER(268, "com.google.android.gms.matchstick.lighter.service.START"),
|
||||
FIDO_TARGET_DEVICE_INTERNAL(269, "com.google.android.gms.fido.targetdevice.internal_service.START"),
|
||||
TELEMETRY(270, "com.google.android.gms.common.telemetry.service.START"),
|
||||
SECOND_DEVICE_AUTH(275, "com.google.android.gms.setup.auth.SecondDeviceAuth.START"),
|
||||
LOCATION_SHARING_REPORTER(277, "com.google.android.gms.locationsharingreporter.service.START"),
|
||||
OCR(279, "com.google.android.gms.ocr.service.START"),
|
||||
POTOKENS(285, "com.google.android.gms.potokens.service.START"),
|
||||
OCR_INTERNAL(281, "com.google.android.gms.ocr.service.internal.START"),
|
||||
APP_SET(300, "com.google.android.gms.appset.service.START"),
|
||||
THREAD_NETWORK(305, "com.google.android.gms.threadnetwork.service.START"),
|
||||
MODULE_INSTALL(308, "com.google.android.gms.chimera.container.moduleinstall.ModuleInstallService.START"),
|
||||
SEMANTIC_LOCATION_HISTORY(314, "com.google.android.gms.semanticlocationhistory.service.START", "com.google.android.gms.semanticlocationhistory.zeroparty.service.START"),
|
||||
IN_APP_REACH(315, "com.google.android.gms.inappreach.service.START"),
|
||||
APP_ERRORS(334, "com.google.android.gms.apperrors.service.START_APP_ERROR"),
|
||||
;
|
||||
|
||||
public int SERVICE_ID;
|
||||
public String ACTION;
|
||||
public String[] SECONDARY_ACTIONS;
|
||||
|
||||
GmsService(int serviceId, String... actions) {
|
||||
this.SERVICE_ID = serviceId;
|
||||
this.ACTION = actions.length > 0 ? actions[0] : null;
|
||||
this.SECONDARY_ACTIONS = actions;
|
||||
}
|
||||
|
||||
public interface ADVERTISING_ID {
|
||||
// Has no service id
|
||||
String ACTION = "com.google.android.gms.ads.identifier.service.START";
|
||||
}
|
||||
|
||||
public static GmsService byServiceId(int serviceId) {
|
||||
for (GmsService service : values()) {
|
||||
if (service.SERVICE_ID == serviceId) return service;
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public static GmsService byAction(String action) {
|
||||
for (GmsService service : values()) {
|
||||
for (String serviceAction : service.SECONDARY_ACTIONS) {
|
||||
if (serviceAction.equals(action)) return service;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public static String nameFromServiceId(int serviceId) {
|
||||
return byServiceId(serviceId).toString(serviceId);
|
||||
}
|
||||
|
||||
public String toString(int serviceId) {
|
||||
if (this != UNKNOWN) return toString();
|
||||
return "UNKNOWN(" + serviceId + ")";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.common;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Hide the class, method or field from the public API.
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR})
|
||||
public @interface Hide {
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.microg.gms.common;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* An class, method or field is named public, if it can be used with the original play services
|
||||
* client library.
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR})
|
||||
public @interface PublicApi {
|
||||
/**
|
||||
* @return the first version that contains the given class, method or field
|
||||
*/
|
||||
String since() default "0";
|
||||
|
||||
/**
|
||||
* @return the last version that contains the given class, method or field
|
||||
*/
|
||||
String until() default "latest";
|
||||
|
||||
/**
|
||||
* Used on a method or field to exclude it from the public api if the corresponding class was
|
||||
* marked as public api.
|
||||
*
|
||||
* @return true if the method or field is not part of the public api
|
||||
* @deprecated use {@link Hide} instead
|
||||
*/
|
||||
@Deprecated
|
||||
boolean exclude() default false;
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2017 microG Project Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.microg.gms.gcm;
|
||||
|
||||
public final class GcmConstants {
|
||||
public static final String ACTION_C2DM_RECEIVE = "com.google.android.c2dm.intent.RECEIVE";
|
||||
public static final String ACTION_C2DM_REGISTER = "com.google.android.c2dm.intent.REGISTER";
|
||||
public static final String ACTION_C2DM_REGISTRATION = "com.google.android.c2dm.intent.REGISTRATION";
|
||||
public static final String ACTION_C2DM_UNREGISTER = "com.google.android.c2dm.intent.UNREGISTER";
|
||||
public static final String ACTION_GCM_SEND = "com.google.android.gcm.intent.SEND";
|
||||
public static final String ACTION_NOTIFICATION_OPEN = "com.google.android.gms.gcm.NOTIFICATION_OPEN";
|
||||
public static final String ACTION_NOTIFICATION_DISMISS = "com.google.android.gms.gcm.NOTIFICATION_DISMISS";
|
||||
public static final String ACTION_SCHEDULE = "com.google.android.gms.gcm.ACTION_SCHEDULE";
|
||||
public static final String ACTION_TASK_READY = "com.google.android.gms.gcm.ACTION_TASK_READY";
|
||||
public static final String ACTION_TASK_INITIALZE = "com.google.android.gms.gcm.SERVICE_ACTION_INITIALIZE";
|
||||
public static final String ACTION_INSTANCE_ID = "com.google.android.gms.iid.InstanceID";
|
||||
|
||||
public static final String EXTRA_APP = "app";
|
||||
public static final String EXTRA_APP_OVERRIDE = "org.microg.gms.gcm.APP_OVERRIDE";
|
||||
public static final String EXTRA_APP_ID = "appid";
|
||||
public static final String EXTRA_APP_VERSION_CODE = "app_ver";
|
||||
public static final String EXTRA_APP_VERSION_NAME = "app_ver_name";
|
||||
public static final String EXTRA_CLIENT_VERSION = "cliv";
|
||||
public static final String EXTRA_COMPONENT = "component";
|
||||
public static final String EXTRA_COLLAPSE_KEY = "collapse_key";
|
||||
public static final String EXTRA_DELAY = "google.delay";
|
||||
public static final String EXTRA_DELETE = "delete";
|
||||
public static final String EXTRA_ERROR = "error";
|
||||
public static final String EXTRA_FROM = "from";
|
||||
public static final String EXTRA_GSF_INTENT = "GSF";
|
||||
public static final String EXTRA_GMS_VERSION = "gmsv";
|
||||
public static final String EXTRA_IS_MESSENGER2 = "messenger2";
|
||||
public static final String EXTRA_KID = "kid";
|
||||
public static final String EXTRA_MESSENGER = "google.messenger";
|
||||
public static final String EXTRA_MESSAGE_TYPE = "message_type";
|
||||
public static final String EXTRA_MESSAGE_ID = "google.message_id";
|
||||
public static final String EXTRA_OS_VERSION = "osv";
|
||||
public static final String EXTRA_PENDING_INTENT = "com.google.android.gms.gcm.PENDING_INTENT";
|
||||
public static final String EXTRA_PUBLIC_KEY = "pub2";
|
||||
public static final String EXTRA_RAWDATA = "rawData";
|
||||
public static final String EXTRA_RAWDATA_BASE64 = "gcm.rawData64";
|
||||
public static final String EXTRA_REGISTRATION_ID = "registration_id";
|
||||
public static final String EXTRA_RETRY_AFTER = "Retry-After";
|
||||
public static final String EXTRA_SCHEDULER_ACTION = "scheduler_action";
|
||||
public static final String EXTRA_SCOPE = "scope";
|
||||
public static final String EXTRA_SENDER = "sender";
|
||||
public static final String EXTRA_SENDER_LEGACY = "legacy.sender";
|
||||
public static final String EXTRA_SEND_TO = "google.to";
|
||||
public static final String EXTRA_SEND_FROM = "google.from";
|
||||
public static final String EXTRA_SENT_TIME = "google.sent_time";
|
||||
public static final String EXTRA_SIGNATURE = "sig";
|
||||
public static final String EXTRA_SUBSCIPTION = "subscription";
|
||||
public static final String EXTRA_SUBTYPE = "subtype";
|
||||
public static final String EXTRA_USE_GSF = "useGsf";
|
||||
public static final String EXTRA_TAG = "tag";
|
||||
public static final String EXTRA_TOPIC = "gcm.topic";
|
||||
public static final String EXTRA_TTL = "google.ttl";
|
||||
public static final String EXTRA_UNREGISTERED = "unregistered";
|
||||
public static final String EXTRA_ACCOUNT_NAME = "a";
|
||||
public static final String EXTRA_REG_ID = "id";
|
||||
public static final String EXTRA_AUTHS_TOKEN = "t";
|
||||
public static final String EXTRA_GCM_BODY = "gcmb";
|
||||
public static final String EXTRA_GMS_GNOTS_PAYLOAD = "gms.gnots.payload";
|
||||
|
||||
public static final String MESSAGE_TYPE_GCM = "gcm";
|
||||
public static final String MESSAGE_TYPE_DELETED_MESSAGE = "deleted_message";
|
||||
public static final String MESSAGE_TYPE_SEND_ERROR = "send_error";
|
||||
public static final String MESSAGE_TYPE_SEND_EVENT = "send_event";
|
||||
|
||||
public static final String SCHEDULER_ACTION_CANCEL = "CANCEL_TASK";
|
||||
public static final String SCHEDULER_ACTION_CANCEL_ALL = "CANCEL_ALL";
|
||||
public static final String SCHEDULER_ACTION_SCHEDULE = "SCHEDULE_TASK";
|
||||
|
||||
public static final String PERMISSION_GTALK = "com.google.android.gtalkservice.permission.GTALK_SERVICE";
|
||||
public static final String PERMISSION_NETWORK_TASK = "com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE";
|
||||
public static final String PERMISSION_RECEIVE = "com.google.android.c2dm.permission.RECEIVE";
|
||||
public static final String PERMISSION_SEND = "com.google.android.c2dm.permission.SEND";
|
||||
|
||||
public static final String ERROR_SERVICE_NOT_AVAILABLE = "SERVICE_NOT_AVAILABLE";
|
||||
|
||||
public static final String ERROR_INVALID_FID = "Invalid argument for the given fid";
|
||||
|
||||
public static final String INSTANCE_ID_SCOPE_GCM = "GCM";
|
||||
|
||||
public static final String GCMID_INSTANCE_ID = "google.com/iid";
|
||||
public static final String GCMID_REFRESH = "gcm.googleapis.com/refresh";
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.utils;
|
||||
|
||||
import android.util.Base64;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ToStringHelper {
|
||||
private StringBuilder sb;
|
||||
private boolean hasField;
|
||||
private boolean hasValue;
|
||||
private boolean hasEnd;
|
||||
|
||||
public ToStringHelper(String name) {
|
||||
this.sb = new StringBuilder(name).append("[");
|
||||
}
|
||||
|
||||
public static ToStringHelper name(String name) {
|
||||
return new ToStringHelper(name);
|
||||
}
|
||||
|
||||
public ToStringHelper value(String val) {
|
||||
if (!hasField) {
|
||||
if (hasValue) sb.append(',');
|
||||
sb.append(val);
|
||||
hasValue = true;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ToStringHelper value(long val) {
|
||||
return value(Long.toString(val));
|
||||
}
|
||||
|
||||
public ToStringHelper value(double val) {
|
||||
return value(Double.toString(val));
|
||||
}
|
||||
|
||||
public ToStringHelper value(Object val) {
|
||||
if (val instanceof Long) value((long) val);
|
||||
if (val instanceof Double) value((double) val);
|
||||
return value(val, false);
|
||||
}
|
||||
|
||||
public ToStringHelper value(Object val, boolean forceNull) {
|
||||
if (val == null && !forceNull) return this;
|
||||
return value(val == null ? "null" : val.toString());
|
||||
}
|
||||
|
||||
public ToStringHelper value(byte[] val) {
|
||||
return value(val, false);
|
||||
}
|
||||
|
||||
public ToStringHelper value(byte[] val, boolean forceNull) {
|
||||
if (val == null && !forceNull) return this;
|
||||
return value(val == null ? "null" : Base64.encodeToString(val, Base64.NO_WRAP | Base64.NO_PADDING | Base64.URL_SAFE));
|
||||
}
|
||||
|
||||
private ToStringHelper fieldUnquoted(String name, String val) {
|
||||
if (hasValue || hasField) sb.append(", ");
|
||||
sb.append(name).append('=').append(val);
|
||||
hasField = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ToStringHelper field(String name, String val) {
|
||||
return field(name, val, false);
|
||||
}
|
||||
|
||||
public ToStringHelper field(String name, String val, boolean forceNull) {
|
||||
if (val == null && !forceNull) return this;
|
||||
if (val == null) return fieldUnquoted(name, "null");
|
||||
if (hasValue || hasField) sb.append(", ");
|
||||
sb.append(name).append("=\"").append(val.replace("\"", "\\\"")).append('"');
|
||||
hasField = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ToStringHelper field(String name, long val) {
|
||||
return fieldUnquoted(name, Long.toString(val));
|
||||
}
|
||||
|
||||
public ToStringHelper field(String name, double val) {
|
||||
return fieldUnquoted(name, Double.toString(val));
|
||||
}
|
||||
|
||||
public ToStringHelper field(String name, boolean val) {
|
||||
return fieldUnquoted(name, Boolean.toString(val));
|
||||
}
|
||||
|
||||
public ToStringHelper field(String name, Object val) {
|
||||
if (val instanceof Long) return field(name, (long) val);
|
||||
if (val instanceof Double) return field(name, (double) val);
|
||||
if (val instanceof Boolean) return field(name, (boolean) val);
|
||||
return field(name, val, false);
|
||||
}
|
||||
|
||||
public ToStringHelper field(String name, Object val, boolean forceNull) {
|
||||
if (val == null && !forceNull) return this;
|
||||
return fieldUnquoted(name, val == null ? "null" : val.toString());
|
||||
}
|
||||
|
||||
public ToStringHelper field(String name, byte[] val) {
|
||||
return field(name, val, false);
|
||||
}
|
||||
|
||||
public ToStringHelper field(String name, byte[] val, boolean forceNull) {
|
||||
if (val == null && !forceNull) return this;
|
||||
return fieldUnquoted(name, val == null ? "null" : Base64.encodeToString(val, Base64.NO_WRAP | Base64.NO_PADDING | Base64.URL_SAFE));
|
||||
}
|
||||
|
||||
public ToStringHelper field(String name, Object[] val) {
|
||||
return field(name, val, false);
|
||||
}
|
||||
|
||||
public ToStringHelper field(String name, Object[] val, boolean forceNull) {
|
||||
if (val == null && !forceNull) return this;
|
||||
return fieldUnquoted(name, val == null ? "null" : Arrays.toString(val));
|
||||
}
|
||||
|
||||
public String end() {
|
||||
if (!hasEnd) sb.append(']');
|
||||
hasEnd = true;
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.utils;
|
||||
|
||||
import android.os.WorkSource;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
public class WorkSourceUtil {
|
||||
private static final String TAG = "WorkSourceUtil";
|
||||
|
||||
private static Method getMethod(String name, Class<?>... parameterTypes) throws Exception {
|
||||
Method method = WorkSource.class.getMethod(name, parameterTypes);
|
||||
method.setAccessible(true);
|
||||
return method;
|
||||
}
|
||||
|
||||
private static <T> T invokeMethod(WorkSource workSource, Method method, Object... args) throws Exception {
|
||||
return (T) method.invoke(workSource, args);
|
||||
}
|
||||
|
||||
private static <T> T invokeMethod(WorkSource workSource, String name, Object... args) throws Exception {
|
||||
return invokeMethod(workSource, getMethod(name), args);
|
||||
}
|
||||
|
||||
public static void add(WorkSource workSource, int uid, String packageName) {
|
||||
try {
|
||||
invokeMethod(workSource, getMethod("add", Integer.TYPE, String.class), uid, packageName);
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
invokeMethod(workSource, getMethod("add", Integer.TYPE), uid);
|
||||
} catch (Exception ex) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int size(WorkSource workSource) {
|
||||
try {
|
||||
return invokeMethod(workSource, "size");
|
||||
} catch (Exception e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isEmpty(WorkSource workSource) {
|
||||
if (SDK_INT >= 28) {
|
||||
try {
|
||||
return invokeMethod(workSource, "isEmpty");
|
||||
} catch (Exception e) {
|
||||
// Ignore and fall-through to size()
|
||||
}
|
||||
}
|
||||
return size(workSource) == 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.safeparcel;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
|
||||
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
|
||||
|
||||
public abstract class AutoSafeParcelable extends AbstractSafeParcelable {
|
||||
private static final String TAG = "SafeParcel";
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
Creator<Parcelable> creator = SafeParcelReflectionUtil.getCreator(this.getClass());
|
||||
if (creator instanceof SafeParcelableCreatorAndWriter) {
|
||||
((SafeParcelableCreatorAndWriter<AutoSafeParcelable>) (SafeParcelableCreatorAndWriter<?>) creator).writeToParcel(this, dest, flags);
|
||||
} else {
|
||||
Log.w(TAG, "AutoSafeParcelable is not using SafeParcelableCreatorAndWriter");
|
||||
SafeParcelReflectionUtil.writeObject(this, dest, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends AbstractSafeParcelable> SafeParcelableCreatorAndWriter<T> findCreator(java.lang.Class<T> tClass) {
|
||||
try {
|
||||
return AbstractSafeParcelable.findCreator(tClass);
|
||||
} catch (Exception e) {
|
||||
if (AutoSafeParcelable.class.isAssignableFrom(tClass)) {
|
||||
return (SafeParcelableCreatorAndWriter<T>) new AutoCreator<>((java.lang.Class<AutoSafeParcelable>) tClass);
|
||||
} else {
|
||||
throw new RuntimeException("AutoSafeParcelable.findCreator() invoked with non-AutoSafeParcelable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static class AutoCreator<T extends AutoSafeParcelable> extends ReflectedSafeParcelableCreatorAndWriter<T> {
|
||||
public AutoCreator(java.lang.Class<T> tClass) {
|
||||
super(tClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.safeparcel;
|
||||
|
||||
import android.os.Parcel;
|
||||
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
public class ReflectedSafeParcelableCreatorAndWriter<T extends AutoSafeParcelable> implements SafeParcelableCreatorAndWriter<T> {
|
||||
|
||||
private final SafeParcelReflectionUtil.ClassDescriptor<T> descriptor;
|
||||
|
||||
public ReflectedSafeParcelableCreatorAndWriter(Class<T> tClass) {
|
||||
this.descriptor = new SafeParcelReflectionUtil.ClassDescriptor<>(tClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T createFromParcel(Parcel parcel) {
|
||||
return SafeParcelReflectionUtil.createObject(parcel, descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(T object, Parcel parcel, int flags) {
|
||||
SafeParcelReflectionUtil.writeObject(object, parcel, flags, descriptor);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T[] newArray(int i) {
|
||||
return (T[]) Array.newInstance(descriptor.tClass, i);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,538 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.safeparcel;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import com.google.android.gms.common.internal.safeparcel.SafeParcelReader;
|
||||
import com.google.android.gms.common.internal.safeparcel.SafeParcelWriter;
|
||||
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
|
||||
import org.microg.gms.common.Hide;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Hide
|
||||
public final class SafeParcelReflectionUtil {
|
||||
private static final String TAG = "SafeParcel";
|
||||
|
||||
private SafeParcelReflectionUtil() {
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static <T extends AutoSafeParcelable> T createObject(Class<T> tClass, Parcel in) {
|
||||
ClassDescriptor<T> descriptor = new ClassDescriptor<>(tClass);
|
||||
return createObject(in, descriptor);
|
||||
}
|
||||
|
||||
public static <T extends AutoSafeParcelable> T createObject(Parcel in, ClassDescriptor<T> descriptor) {
|
||||
try {
|
||||
Constructor<T> constructor = descriptor.constructor;
|
||||
T t = constructor.newInstance();
|
||||
readObject(t, in, descriptor);
|
||||
return t;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Can't construct object", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void writeObject(AutoSafeParcelable object, Parcel parcel, int flags) {
|
||||
if (object == null)
|
||||
throw new NullPointerException();
|
||||
Class<?> clazz = object.getClass();
|
||||
ClassDescriptor<?> descriptor = new ClassDescriptor<>(clazz);
|
||||
writeObject(object, parcel, flags, descriptor);
|
||||
}
|
||||
|
||||
public static <T extends AutoSafeParcelable> void writeObject(T object, Parcel parcel, int flags, ClassDescriptor<?> descriptor) {
|
||||
int start = SafeParcelWriter.writeObjectHeader(parcel);
|
||||
for (ClassDescriptor.FieldDescriptor fieldDescriptor : descriptor.fields.values()) {
|
||||
try {
|
||||
writeField(object, parcel, flags, fieldDescriptor);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error writing field: " + e);
|
||||
}
|
||||
}
|
||||
SafeParcelWriter.finishObjectHeader(parcel, start);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Deprecated
|
||||
public static <T extends AutoSafeParcelable> void readObject(T object, Parcel parcel) {
|
||||
if (object == null)
|
||||
throw new NullPointerException();
|
||||
Class<T> clazz = (Class<T>) object.getClass();
|
||||
ClassDescriptor<T> descriptor = new ClassDescriptor<>(clazz);
|
||||
readObject(object, parcel, descriptor);
|
||||
}
|
||||
|
||||
public static <T extends AutoSafeParcelable> void readObject(T object, Parcel parcel, ClassDescriptor<T> descriptor) {
|
||||
if (object == null)
|
||||
throw new NullPointerException();
|
||||
int end = SafeParcelReader.readObjectHeader(parcel);
|
||||
while (parcel.dataPosition() < end) {
|
||||
int header = SafeParcelReader.readHeader(parcel);
|
||||
int fieldId = SafeParcelReader.getFieldId(header);
|
||||
ClassDescriptor.FieldDescriptor fieldDescriptor = descriptor.fields.get(fieldId);
|
||||
if (fieldDescriptor == null) {
|
||||
Log.d(TAG, String.format("Unknown field id %d in %s, skipping.", fieldId, descriptor.tClass.getName()));
|
||||
SafeParcelReader.skip(parcel, header);
|
||||
} else {
|
||||
try {
|
||||
readField(object, parcel, header, fieldDescriptor);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, String.format("Error reading field: %d of type %s in %s, skipping.", fieldId, fieldDescriptor.type, descriptor.tClass.getName()), e);
|
||||
SafeParcelReader.skip(parcel, header);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parcel.dataPosition() > end) {
|
||||
throw new RuntimeException("Overread allowed size end=" + end);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Parcelable.Creator<Parcelable> getCreator(Field field) {
|
||||
Class<?> clazz = field.getType();
|
||||
if (clazz.isArray()) {
|
||||
clazz = clazz.getComponentType();
|
||||
}
|
||||
if (clazz != null && Parcelable.class.isAssignableFrom(clazz)) {
|
||||
return getCreator((Class<? extends Parcelable>) clazz);
|
||||
}
|
||||
throw new RuntimeException(clazz + " is not an Parcelable");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Parcelable.Creator<Parcelable> getCreator(Class<? extends Parcelable> clazz) {
|
||||
try {
|
||||
Field creatorField = clazz.getDeclaredField("CREATOR");
|
||||
creatorField.setAccessible(true);
|
||||
return (Parcelable.Creator<Parcelable>) creatorField.get(null);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new RuntimeException(clazz + " is an Parcelable without CREATOR");
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException("CREATOR in " + clazz + " is not accessible");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static Class<?> getSubClass(Field field) {
|
||||
SafeParceled safeParceled = field.getAnnotation(SafeParceled.class);
|
||||
SafeParcelable.Field safeParcelableField = field.getAnnotation(SafeParcelable.Field.class);
|
||||
if (safeParceled != null && safeParceled.subClass() != SafeParceled.class) {
|
||||
return safeParceled.subClass();
|
||||
} else if (safeParceled != null && !"undefined".equals(safeParceled.subType())) {
|
||||
try {
|
||||
return Class.forName(safeParceled.subType());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
} else if (safeParcelableField != null && safeParcelableField.subClass() != SafeParcelable.class) {
|
||||
return safeParcelableField.subClass();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static Class<?> getListItemClass(Field field) {
|
||||
Class<?> subClass = getSubClass(field);
|
||||
if (subClass != null || field.isAnnotationPresent(SafeParceled.class)) return subClass;
|
||||
Type type = field.getGenericType();
|
||||
if (type instanceof ParameterizedType) {
|
||||
ParameterizedType pt = (ParameterizedType) type;
|
||||
if (pt.getActualTypeArguments().length >= 1) {
|
||||
Type t = pt.getActualTypeArguments()[0];
|
||||
if (t instanceof Class) return (Class<?>) t;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static ClassLoader getClassLoader(Class<?> clazz) {
|
||||
return clazz == null || clazz.getClassLoader() == null ? ClassLoader.getSystemClassLoader() : clazz.getClassLoader();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static boolean isSafeParceledField(Field field) {
|
||||
return field.isAnnotationPresent(SafeParceled.class) || field.isAnnotationPresent(SafeParcelable.Field.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void writeField(AutoSafeParcelable object, Parcel parcel, int flags, ClassDescriptor.FieldDescriptor descriptor)
|
||||
throws IllegalAccessException {
|
||||
switch (descriptor.type) {
|
||||
case Parcelable:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (Parcelable) descriptor.field.get(object), flags, descriptor.mayNull);
|
||||
break;
|
||||
case Binder:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (IBinder) descriptor.field.get(object), descriptor.mayNull);
|
||||
break;
|
||||
case Interface:
|
||||
IInterface iInterface = ((IInterface) descriptor.field.get(object));
|
||||
IBinder iBinder = iInterface != null ? iInterface.asBinder() : null;
|
||||
SafeParcelWriter.write(parcel, descriptor.id, iBinder, descriptor.mayNull);
|
||||
break;
|
||||
case StringList:
|
||||
SafeParcelWriter.writeStringList(parcel, descriptor.id, ((List<String>) descriptor.field.get(object)), descriptor.mayNull);
|
||||
break;
|
||||
case IntegerList:
|
||||
SafeParcelWriter.writeIntegerList(parcel, descriptor.id, ((List<Integer>) descriptor.field.get(object)), descriptor.mayNull);
|
||||
break;
|
||||
case BooleanList:
|
||||
SafeParcelWriter.writeBooleanList(parcel, descriptor.id, ((List<Boolean>) descriptor.field.get(object)), descriptor.mayNull);
|
||||
break;
|
||||
case LongList:
|
||||
SafeParcelWriter.writeLongList(parcel, descriptor.id, ((List<Long>) descriptor.field.get(object)), descriptor.mayNull);
|
||||
break;
|
||||
case FloatList:
|
||||
SafeParcelWriter.writeFloatList(parcel, descriptor.id, ((List<Float>) descriptor.field.get(object)), descriptor.mayNull);
|
||||
break;
|
||||
case DoubleList:
|
||||
SafeParcelWriter.writeDoubleList(parcel, descriptor.id, ((List<Double>) descriptor.field.get(object)), descriptor.mayNull);
|
||||
break;
|
||||
case List: {
|
||||
Class<?> clazz = descriptor.listItemClass;
|
||||
if (clazz == null || !Parcelable.class.isAssignableFrom(clazz) || descriptor.useValueParcel) {
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (List<?>) descriptor.field.get(object), descriptor.mayNull);
|
||||
} else {
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (List<Parcelable>) descriptor.field.get(object), flags, descriptor.mayNull);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Map:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (Map) descriptor.field.get(object), descriptor.mayNull);
|
||||
break;
|
||||
case Bundle:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (Bundle) descriptor.field.get(object), descriptor.mayNull);
|
||||
break;
|
||||
case ParcelableArray:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (Parcelable[]) descriptor.field.get(object), flags, descriptor.mayNull);
|
||||
break;
|
||||
case StringArray:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (String[]) descriptor.field.get(object), descriptor.mayNull);
|
||||
break;
|
||||
case ByteArray:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (byte[]) descriptor.field.get(object), descriptor.mayNull);
|
||||
break;
|
||||
case ByteArrayArray:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (byte[][]) descriptor.field.get(object), descriptor.mayNull);
|
||||
break;
|
||||
case FloatArray:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (float[]) descriptor.field.get(object), descriptor.mayNull);
|
||||
break;
|
||||
case IntArray:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (int[]) descriptor.field.get(object), descriptor.mayNull);
|
||||
break;
|
||||
case Integer:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (Integer) descriptor.field.get(object));
|
||||
break;
|
||||
case Long:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (Long) descriptor.field.get(object));
|
||||
break;
|
||||
case Short:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (Short) descriptor.field.get(object));
|
||||
break;
|
||||
case Boolean:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (Boolean) descriptor.field.get(object));
|
||||
break;
|
||||
case Float:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (Float) descriptor.field.get(object));
|
||||
break;
|
||||
case Double:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (Double) descriptor.field.get(object));
|
||||
break;
|
||||
case String:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (String) descriptor.field.get(object), descriptor.mayNull);
|
||||
break;
|
||||
case Byte:
|
||||
SafeParcelWriter.write(parcel, descriptor.id, (Byte) descriptor.field.get(object));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void readField(AutoSafeParcelable object, Parcel parcel, int header, ClassDescriptor.FieldDescriptor descriptor)
|
||||
throws IllegalAccessException {
|
||||
switch (descriptor.type) {
|
||||
case Parcelable:
|
||||
descriptor.field.set(object, SafeParcelReader.readParcelable(parcel, header, descriptor.creator));
|
||||
break;
|
||||
case Binder:
|
||||
descriptor.field.set(object, SafeParcelReader.readBinder(parcel, header));
|
||||
break;
|
||||
case Interface: {
|
||||
boolean hasStub = false;
|
||||
for (Class<?> aClass : descriptor.field.getType().getDeclaredClasses()) {
|
||||
try {
|
||||
descriptor.field.set(object, aClass.getDeclaredMethod("asInterface", IBinder.class)
|
||||
.invoke(null, SafeParcelReader.readBinder(parcel, header)));
|
||||
hasStub = true;
|
||||
break;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
if (!hasStub) throw new RuntimeException("Field has broken interface: " + descriptor.field);
|
||||
break;
|
||||
}
|
||||
case StringList:
|
||||
descriptor.field.set(object, SafeParcelReader.readStringList(parcel, header));
|
||||
break;
|
||||
case IntegerList:
|
||||
descriptor.field.set(object, SafeParcelReader.readIntegerList(parcel, header));
|
||||
break;
|
||||
case BooleanList:
|
||||
descriptor.field.set(object, SafeParcelReader.readBooleanList(parcel, header));
|
||||
break;
|
||||
case LongList:
|
||||
descriptor.field.set(object, SafeParcelReader.readLongList(parcel, header));
|
||||
break;
|
||||
case FloatList:
|
||||
descriptor.field.set(object, SafeParcelReader.readFloatList(parcel, header));
|
||||
break;
|
||||
case DoubleList:
|
||||
descriptor.field.set(object, SafeParcelReader.readDoubleList(parcel, header));
|
||||
break;
|
||||
case List: {
|
||||
Class<?> clazz = descriptor.listItemClass;
|
||||
Object val;
|
||||
if (clazz == null || !Parcelable.class.isAssignableFrom(clazz) || descriptor.useValueParcel) {
|
||||
val = SafeParcelReader.readList(parcel, header, getClassLoader(clazz));
|
||||
} else {
|
||||
val = SafeParcelReader.readParcelableList(parcel, header, descriptor.creator);
|
||||
}
|
||||
descriptor.field.set(object, val);
|
||||
break;
|
||||
}
|
||||
case Map: {
|
||||
Class<?> clazz = descriptor.subClass;
|
||||
Object val = SafeParcelReader.readMap(parcel, header, getClassLoader(clazz));
|
||||
descriptor.field.set(object, val);
|
||||
break;
|
||||
}
|
||||
case Bundle: {
|
||||
Class<?> clazz = descriptor.subClass;
|
||||
Object val;
|
||||
if (clazz == null || !Parcelable.class.isAssignableFrom(clazz) || descriptor.useValueParcel /* should not happen on Bundles */) {
|
||||
val = SafeParcelReader.readBundle(parcel, header, getClassLoader(descriptor.field.getDeclaringClass()));
|
||||
} else {
|
||||
val = SafeParcelReader.readBundle(parcel, header, getClassLoader(clazz));
|
||||
}
|
||||
descriptor.field.set(object, val);
|
||||
break;
|
||||
}
|
||||
case ParcelableArray:
|
||||
descriptor.field.set(object, SafeParcelReader.readParcelableArray(parcel, header, descriptor.creator));
|
||||
break;
|
||||
case StringArray:
|
||||
descriptor.field.set(object, SafeParcelReader.readStringArray(parcel, header));
|
||||
break;
|
||||
case ByteArray:
|
||||
descriptor.field.set(object, SafeParcelReader.readByteArray(parcel, header));
|
||||
break;
|
||||
case ByteArrayArray:
|
||||
descriptor.field.set(object, SafeParcelReader.readByteArrayArray(parcel, header));
|
||||
break;
|
||||
case FloatArray:
|
||||
descriptor.field.set(object, SafeParcelReader.readFloatArray(parcel, header));
|
||||
break;
|
||||
case IntArray:
|
||||
descriptor.field.set(object, SafeParcelReader.readIntArray(parcel, header));
|
||||
break;
|
||||
case Integer: {
|
||||
int i = SafeParcelReader.readInt(parcel, header);
|
||||
if (descriptor.versionCode != -1 && i > descriptor.versionCode) {
|
||||
Log.d(TAG, String.format("Version code of %s (%d) is older than object read (%d).", descriptor.field.getDeclaringClass().getName(), descriptor.versionCode, i));
|
||||
}
|
||||
descriptor.field.set(object, i);
|
||||
break;
|
||||
}
|
||||
case Long: {
|
||||
long l = SafeParcelReader.readLong(parcel, header);
|
||||
if (descriptor.versionCode != -1 && l > descriptor.versionCode) {
|
||||
Log.d(TAG, String.format("Version code of %s (%d) is older than object read (%d).", descriptor.field.getDeclaringClass().getName(), descriptor.versionCode, l));
|
||||
}
|
||||
descriptor.field.set(object, l);
|
||||
break;
|
||||
}
|
||||
case Short: {
|
||||
short i = SafeParcelReader.readShort(parcel, header);
|
||||
if (descriptor.versionCode != -1 && i > descriptor.versionCode) {
|
||||
Log.d(TAG, String.format("Version code of %s (%d) is older than object read (%d).", descriptor.field.getDeclaringClass().getName(), descriptor.versionCode, i));
|
||||
}
|
||||
descriptor.field.set(object, i);
|
||||
break;
|
||||
}
|
||||
case Boolean:
|
||||
descriptor.field.set(object, SafeParcelReader.readBool(parcel, header));
|
||||
break;
|
||||
case Float:
|
||||
descriptor.field.set(object, SafeParcelReader.readFloat(parcel, header));
|
||||
break;
|
||||
case Double:
|
||||
descriptor.field.set(object, SafeParcelReader.readDouble(parcel, header));
|
||||
break;
|
||||
case String:
|
||||
descriptor.field.set(object, SafeParcelReader.readString(parcel, header));
|
||||
break;
|
||||
case Byte:
|
||||
descriptor.field.set(object, SafeParcelReader.readByte(parcel, header));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected value: " + descriptor.type);
|
||||
}
|
||||
}
|
||||
|
||||
private enum SafeParcelType {
|
||||
Parcelable, Binder, Interface, Bundle,
|
||||
StringList, IntegerList, BooleanList, LongList, FloatList, DoubleList, List, Map,
|
||||
ParcelableArray, StringArray, ByteArray, ByteArrayArray, FloatArray, IntArray,
|
||||
Integer, Long, Short, Boolean, Float, Double, String, Byte;
|
||||
}
|
||||
|
||||
public static class ClassDescriptor<T> {
|
||||
Class<T> tClass;
|
||||
Constructor<T> constructor;
|
||||
Map<Integer, FieldDescriptor> fields = new HashMap<>();
|
||||
|
||||
public ClassDescriptor(Class<T> tClass) {
|
||||
this.tClass = tClass;
|
||||
try {
|
||||
constructor = tClass.getDeclaredConstructor();
|
||||
constructor.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, tClass + " has no default constructor");
|
||||
}
|
||||
Class<?> clazz = tClass;
|
||||
while (clazz != null) {
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
if (isSafeParceledField(field)) {
|
||||
FieldDescriptor fieldDescriptor = new FieldDescriptor(field);
|
||||
fields.put(fieldDescriptor.id, fieldDescriptor);
|
||||
}
|
||||
}
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
public static class FieldDescriptor {
|
||||
Field field;
|
||||
int id;
|
||||
boolean mayNull;
|
||||
SafeParcelable.Field annotation;
|
||||
SafeParceled legacyAnnotation;
|
||||
SafeParcelType type;
|
||||
Parcelable.Creator<? extends Parcelable> creator;
|
||||
long versionCode = -1;
|
||||
Class<?> listItemClass;
|
||||
boolean useValueParcel;
|
||||
Class<?> subClass;
|
||||
|
||||
public FieldDescriptor(Field field) {
|
||||
this.field = field;
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
Field accessFlagsField = Field.class.getDeclaredField("accessFlags");
|
||||
accessFlagsField.setAccessible(true);
|
||||
accessFlagsField.setInt(field, accessFlagsField.getInt(field) & ~Modifier.FINAL);
|
||||
} catch (Exception e) {
|
||||
// Ignored
|
||||
}
|
||||
this.annotation = field.getAnnotation(SafeParcelable.Field.class);
|
||||
this.legacyAnnotation = field.getAnnotation(SafeParceled.class);
|
||||
if (annotation != null) {
|
||||
this.id = annotation.value();
|
||||
this.mayNull = annotation.mayNull();
|
||||
this.useValueParcel = annotation.useValueParcel();
|
||||
this.versionCode = annotation.versionCode();
|
||||
} else if (legacyAnnotation != null) {
|
||||
this.id = legacyAnnotation.value();
|
||||
this.mayNull = legacyAnnotation.mayNull();
|
||||
this.useValueParcel = legacyAnnotation.useClassLoader();
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.type = getType();
|
||||
switch (type) {
|
||||
case Parcelable:
|
||||
case ParcelableArray:
|
||||
creator = getCreator(field);
|
||||
break;
|
||||
case List:
|
||||
if (listItemClass != null && Parcelable.class.isAssignableFrom(listItemClass)) {
|
||||
if (!this.useValueParcel) {
|
||||
creator = getCreator((Class<? extends Parcelable>) listItemClass);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Map:
|
||||
case Bundle:
|
||||
subClass = getSubClass(field);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private SafeParcelType getType() {
|
||||
Class<?> clazz = field.getType();
|
||||
Class<?> component = clazz.getComponentType();
|
||||
if (clazz.isArray() && component != null) {
|
||||
if (Parcelable.class.isAssignableFrom(component)) return SafeParcelType.ParcelableArray;
|
||||
if (String.class.isAssignableFrom(component)) return SafeParcelType.StringArray;
|
||||
if (byte.class.isAssignableFrom(component)) return SafeParcelType.ByteArray;
|
||||
if (byte[].class.isAssignableFrom(component)) return SafeParcelType.ByteArrayArray;
|
||||
if (float.class.isAssignableFrom(component)) return SafeParcelType.FloatArray;
|
||||
if (int.class.isAssignableFrom(component)) return SafeParcelType.IntArray;
|
||||
}
|
||||
if (Bundle.class.isAssignableFrom(clazz))
|
||||
return SafeParcelType.Bundle;
|
||||
if (Parcelable.class.isAssignableFrom(clazz))
|
||||
return SafeParcelType.Parcelable;
|
||||
if (IBinder.class.isAssignableFrom(clazz))
|
||||
return SafeParcelType.Binder;
|
||||
if (IInterface.class.isAssignableFrom(clazz))
|
||||
return SafeParcelType.Interface;
|
||||
if (clazz == List.class || clazz == ArrayList.class) {
|
||||
listItemClass = getListItemClass(field);
|
||||
if (listItemClass == String.class && !useValueParcel) return SafeParcelType.StringList;
|
||||
if (listItemClass == Integer.class && annotation.useDirectList()) return SafeParcelType.IntegerList;
|
||||
if (listItemClass == Boolean.class && annotation.useDirectList()) return SafeParcelType.BooleanList;
|
||||
if (listItemClass == Long.class && annotation.useDirectList()) return SafeParcelType.LongList;
|
||||
if (listItemClass == Float.class && annotation.useDirectList()) return SafeParcelType.FloatList;
|
||||
if (listItemClass == Double.class && annotation.useDirectList()) return SafeParcelType.DoubleList;
|
||||
return SafeParcelType.List;
|
||||
}
|
||||
if (clazz == Map.class || clazz == HashMap.class)
|
||||
return SafeParcelType.Map;
|
||||
if (clazz == int.class || clazz == Integer.class)
|
||||
return SafeParcelType.Integer;
|
||||
if (clazz == short.class || clazz == Short.class)
|
||||
return SafeParcelType.Short;
|
||||
if (clazz == boolean.class || clazz == Boolean.class)
|
||||
return SafeParcelType.Boolean;
|
||||
if (clazz == long.class || clazz == Long.class)
|
||||
return SafeParcelType.Long;
|
||||
if (clazz == float.class || clazz == Float.class)
|
||||
return SafeParcelType.Float;
|
||||
if (clazz == double.class || clazz == Double.class)
|
||||
return SafeParcelType.Double;
|
||||
if (clazz == byte.class || clazz == Byte.class)
|
||||
return SafeParcelType.Byte;
|
||||
if (clazz == java.lang.String.class)
|
||||
return SafeParcelType.String;
|
||||
throw new RuntimeException("Type is not yet usable with SafeParcelReflectionUtil: " + clazz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.safeparcel;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
@Deprecated
|
||||
public @interface SafeParceled {
|
||||
int value();
|
||||
|
||||
boolean mayNull() default false;
|
||||
|
||||
@Deprecated String subType() default "undefined";
|
||||
|
||||
Class subClass() default SafeParceled.class;
|
||||
|
||||
boolean useClassLoader() default false;
|
||||
}
|
||||
9
play-services-basement/src/main/res/values/version.xml
Normal file
9
play-services-basement/src/main/res/values/version.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ SPDX-FileCopyrightText: 2015 microG Project Team
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<integer name="google_play_services_version">12451000</integer>
|
||||
</resources>
|
||||
Loading…
Add table
Add a link
Reference in a new issue