Skip to content

Commit

Permalink
Load device profile data for licensing user agent
Browse files Browse the repository at this point in the history
  • Loading branch information
fynngodau committed Jan 11, 2024
1 parent 8934281 commit 4fe9bb9
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 28 deletions.
1 change: 1 addition & 0 deletions vending-app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ android {
dependencies {
implementation project(':fake-signature')
implementation project(':play-services-auth')
implementation project(':play-services-base-core')

implementation "com.squareup.wire:wire-runtime:$wireVersion"
implementation "com.android.volley:volley:$volleyVersion"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ public abstract class LicenseChecker<D, R> {

static final String AUTH_TOKEN_SCOPE = "oauth2:https://www.googleapis.com/auth/googleplay";

public abstract Request<?> createRequest(String packageName, String auth, int versionCode, D data,
public abstract LicenseRequest<?> createRequest(String packageName, String auth, int versionCode, D data,
BiConsumer<Integer, R> then, Response.ErrorListener errorListener);

public void checkLicense(Account account, AccountManager accountManager,
public void checkLicense(Account account, AccountManager accountManager, String androidId,
String packageName, PackageManager packageManager,
RequestQueue queue, D queryData,
BiConsumerWithException<Integer, R, RemoteException> onResult)
Expand Down Expand Up @@ -118,8 +118,9 @@ public void checkLicense(Account account, AccountManager accountManager,
future -> {
try {
String auth = future.getResult().getString(KEY_AUTHTOKEN);
Request<?> request = createRequest(packageName, auth,
LicenseRequest<?> request = createRequest(packageName, auth,
versionCode, queryData, onRequestFinished, onRequestError);
request.ANDROID_ID = Long.decode("0x" + androidId);
request.setShouldCache(false);
queue.add(request);
} catch (AuthenticatorException | IOException | OperationCanceledException e) {
Expand Down Expand Up @@ -149,7 +150,7 @@ private static <A, B, T extends Exception> void safeSendResult(
public static class V1 extends LicenseChecker<Long, Tuple<String, String>> {

@Override
public Request<V1Container> createRequest(String packageName, String auth, int versionCode, Long nonce, BiConsumer<Integer, Tuple<String, String>> then,
public LicenseRequest<V1Container> createRequest(String packageName, String auth, int versionCode, Long nonce, BiConsumer<Integer, Tuple<String, String>> then,
Response.ErrorListener errorListener) {
return new LicenseRequest.V1(
packageName, auth, versionCode, nonce, response -> {
Expand All @@ -170,7 +171,7 @@ public Request<V1Container> createRequest(String packageName, String auth, int v

public static class V2 extends LicenseChecker<Unit, String> {
@Override
public Request<String> createRequest(String packageName, String auth, int versionCode, Unit data,
public LicenseRequest<String> createRequest(String packageName, String auth, int versionCode, Unit data,
BiConsumer<Integer, String> then, Response.ErrorListener errorListener) {
return new LicenseRequest.V2(
packageName, auth, versionCode, response -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,27 @@
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.google.android.gms.common.BuildConfig;

import org.microg.gms.profile.Build;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

import okio.ByteString;

public abstract class LicenseRequest<T> extends Request<T> {

private final String xPsRh;
private final String auth;
private static final String TAG = "FakeLicenseRequest";

private static final int BASE64_FLAGS = Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING;
private static final long ANDROID_ID = 1;
long ANDROID_ID = 1;
private static final String FINSKY_VERSION = "Finsky/37.5.24-29%20%5B0%5D%20%5BPR%5D%20565477504";

private final Response.Listener<T> successListener;

Expand All @@ -55,6 +61,10 @@ protected LicenseRequest(String url, String auth, Response.Listener<T> successLi
this.auth = auth;

this.successListener = successListener;
}

@Override
public Map<String, String> getHeaders() {

long millis = System.currentTimeMillis();
TimestampContainer.Builder timestamp = new TimestampContainer.Builder()
Expand Down Expand Up @@ -107,9 +117,9 @@ protected LicenseRequest(String url, String auth, Response.Listener<T> successLi
.deviceMeta(new DeviceMeta.Builder()
.android(
new AndroidVersionMeta.Builder()
.androidSdk(0)
.buildNumber("")
.androidVersion("")
.androidSdk(Build.VERSION.SDK_INT)
.buildNumber(Build.ID)
.androidVersion(Build.VERSION.RELEASE)
.unknown(0)
.build()
)
Expand All @@ -119,13 +129,13 @@ protected LicenseRequest(String url, String auth, Response.Listener<T> successLi
.build()
)
.userAgent(new UserAgent.Builder()
.deviceProductName("")
.deviceSoc("")
.deviceModelName("")
.finskyVersion("")
.deviceName("")
.deviceName(Build.DEVICE)
.deviceHardware(Build.HARDWARE)
.deviceModelName(Build.MODEL)
.finskyVersion(FINSKY_VERSION)
.deviceProductName(Build.MODEL)
.androidId(ANDROID_ID) // must not be 0
.deviceSignature("")
.buildFingerprint(Build.FINGERPRINT)
.build()
)
.uuid(new Uuid.Builder()
Expand All @@ -134,22 +144,29 @@ protected LicenseRequest(String url, String auth, Response.Listener<T> successLi
.build()
)
.build().encode();
this.xPsRh = new String(Base64.encode(Util.encodeGzip(header), BASE64_FLAGS));

//Log.d(TAG, "Product " + Build.PRODUCT + ", Board " + Build.BOARD + " Model " + Build.MODEL + " Device " + Build.DEVICE);
String xPsRh = new String(Base64.encode(Util.encodeGzip(header), BASE64_FLAGS));

Log.v(TAG, "X-PS-RH: " + xPsRh);
}

@Override
public Map<String, String> getHeaders() {
String userAgent = FINSKY_VERSION + " (api=3,versionCode=" + BuildConfig.VERSION_CODE + ",sdk=" + Build.VERSION.SDK +
",device=" + encodeString(Build.DEVICE) + ",hardware=" + encodeString(Build.HARDWARE) + ",product=" + encodeString(Build.PRODUCT) +
",platformVersionRelease=" + encodeString(Build.VERSION.RELEASE) + ",model=" + encodeString(Build.MODEL) + ",buildId=" + encodeString(Build.ID) +
",isWideScreen=" + 0 + ",supportedAbis=" + String.join(";", Build.SUPPORTED_ABIS) + ")";
Log.v(TAG, "User-Agent: " + userAgent);

return Map.of(
"X-PS-RH", xPsRh,
"User-Agent", userAgent,
"Authorization", "Bearer " + auth,
"Accept-Language", "en-US",
"Connection", "Keep-Alive"
);
}

private static String encodeString(String s) {
return URLEncoder.encode(s).replace("+", "%20");
}

@Override
protected void deliverResponse(T response) {
successListener.onResponse(response);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,24 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.net.Uri;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Log;

import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;

import org.microg.gms.auth.AuthConstants;
import org.microg.gms.profile.Build;
import org.microg.gms.profile.ProfileManager;

import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

import kotlin.Unit;
Expand All @@ -43,6 +52,8 @@ public class LicensingService extends Service {

private static final String PREFERENCE_LICENSING_ENABLED = "play_licensing";

private static final Uri PROFILE_PROVIDER = Uri.parse("content://com.google.android.gms.microg.profile");

private String androidId;

private final ILicensingService.Stub mLicenseService = new ILicensingService.Stub() {
Expand Down Expand Up @@ -93,7 +104,7 @@ public void checkLicense(long nonce, String packageName, ILicenseResultListener
private void checkLicense(long nonce, String packageName, PackageManager packageManager,
ILicenseResultListener listener, Queue<Account> remainingAccounts) throws RemoteException {
new LicenseChecker.V1().checkLicense(
remainingAccounts.poll(), accountManager, packageName, packageManager,
remainingAccounts.poll(), accountManager, androidId, packageName, packageManager,
queue, nonce,
(responseCode, stringTuple) -> {
if (responseCode != LICENSED && !remainingAccounts.isEmpty()) {
Expand Down Expand Up @@ -128,7 +139,7 @@ private void checkLicenseV2(String packageName, PackageManager packageManager,
ILicenseV2ResultListener listener, Bundle extraParams,
Queue<Account> remainingAccounts) throws RemoteException {
new LicenseChecker.V2().checkLicense(
remainingAccounts.poll(), accountManager, packageName, packageManager, queue, Unit.INSTANCE,
remainingAccounts.poll(), accountManager, androidId, packageName, packageManager, queue, Unit.INSTANCE,
(responseCode, data) -> {
/*
* Suppress failures on V2. V2 is commonly used by free apps whose checker
Expand Down Expand Up @@ -167,6 +178,32 @@ private void handleNoAccounts(String packageName, PackageManager packageManager)
};

public IBinder onBind(Intent intent) {


Cursor cursor = null;
try {
cursor = getContentResolver().query(
PROFILE_PROVIDER, null, null, null, null
);

if (cursor == null || cursor.getColumnCount() != 2) {
Log.e(TAG, "profile provider not available");
} else {
Map<String, String> profileData = new HashMap<>();
while (cursor.moveToNext()) {
profileData.put(cursor.getString(0), cursor.getString(1));
}
ProfileManager.INSTANCE.applyProfileData(profileData);
}

} finally {
if (cursor != null) {
cursor.close();
}
}

androidId = String.valueOf(Settings.Secure.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID));

queue = Volley.newRequestQueue(this);
accountManager = AccountManager.get(this);
notificationRunnable = new LicenseServiceNotificationRunnable(this);
Expand Down
8 changes: 4 additions & 4 deletions vending-app/src/main/proto/LicenseRequest.proto
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ message UnknownByte12 {

message UserAgent {
// The names of these attributes are vague guesses and should be adapted if needed.
optional string deviceProductName = 1; // e.g. "OnePlusNord"
optional string deviceSoc = 2; // e.g. "qcom"
optional string deviceName = 1; // e.g. "OnePlusNord"
optional string deviceHardware = 2; // e.g. "qcom"
optional string deviceModelName = 3; // e.g. "OnePlus Nord"
optional string finskyVersion = 4; // e.g. "Finsky/37.5.24-29%20%5B0%5D%20%5BPR%5D%20565477504"
optional string deviceName = 5; // e.g. "OnePlusNord"; difference to 1 not yet clear
optional string deviceProductName = 5; // e.g. "OnePlusNord"
optional uint64 androidId = 6;
optional string deviceSignature = 7; // e.g. "google/walleye/walleye:8.1.0/OPM1.171019.011/4448085:user/release-keys"
optional string buildFingerprint = 7; // e.g. "google/walleye/walleye:8.1.0/OPM1.171019.011/4448085:user/release-keys"
}

message Uuid {
Expand Down

0 comments on commit 4fe9bb9

Please sign in to comment.